From 854e284a8fca7264d59fbcca519be55fd3026fd5 Mon Sep 17 00:00:00 2001
From: Emmanuel Cazenave <ecazenave@entrouvert.com>
Date: Thu, 25 Apr 2019 15:23:36 +0200
Subject: [PATCH] planitec: change price code dynamically (#32472)

---
 passerelle/contrib/planitech/models.py | 37 ++++++++++++++++++++++----
 tests/test_planitech.py                | 29 ++++++++++++++++++++
 2 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/passerelle/contrib/planitech/models.py b/passerelle/contrib/planitech/models.py
index 1d871dea..25c5f122 100644
--- a/passerelle/contrib/planitech/models.py
+++ b/passerelle/contrib/planitech/models.py
@@ -105,6 +105,11 @@ CREATE_RESERVATION_SCHEMA = {
             "description": "VAT rate",
             "type": "number",
             "required": True
+        },
+        "price_code": {
+            "description": "User price code",
+            "type": "string",
+            "required": False
         }
     }
 }
@@ -165,6 +170,11 @@ GET_RESERVATION_PRICE_SCHEMA = {
             "description": "Rerservation type identifier",
             "type": "number",
             "required": True
+        },
+        "price_code": {
+            "description": "User price code",
+            "type": "string",
+            "required": False
         }
     }
 }
@@ -384,22 +394,39 @@ class PlanitechConnector(BaseResource):
         except RequestException as e:
             raise APIError("Authentication to Planitec failed: %s" % str(e))
 
-    def get_or_create_pairing(self, post_data):
+    def updateorcreate_user(self, post_data):
+        dyn_price_code = post_data.get('price_code')
+        price_code = dyn_price_code or self.price_code
+
         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(), 'price_code': self.price_code})
+                defaults={'external_id': uuid.uuid4().get_hex(), 'price_code': price_code})
             if created:
+                # Create planitec user
                 params = {
                     "externalUserIdentifier": pairing.external_id,
                     "name": post_data['last_name'],
                     "firstName": post_data['first_name'],
                     "mail": post_data['email'],
-                    "pricingCode": self.price_code
+                    "pricingCode": price_code
                 }
                 data = self._call_planitech(self.requests.post, 'createPerson', params)
                 if data.get('creationStatus') != 'OK':
                     raise APIError("Person creation failed: %s" % data.get('creationStatus'))
+
+            elif dyn_price_code and pairing.price_code != dyn_price_code:
+                # Update planitec user
+                pairing.price_code = dyn_price_code
+                pairing.save()
+                params = {
+                    'externalUserIdentifier': pairing.external_id,
+                    'pricingCode': dyn_price_code
+                }
+                data = self._call_planitech(self.requests.post, 'updatePerson', params)
+                if data.get('modificationStatus') != 'OK':
+                    raise APIError("Person update failed: %s" % data.get('modificationStatus'))
+
         return pairing
 
     @endpoint(
@@ -417,7 +444,7 @@ class PlanitechConnector(BaseResource):
         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)
+        pairing = self.updateorcreate_user(post_data)
 
         params = {
             "activityID": mste.Uint32(post_data['activity_id']),
@@ -457,7 +484,7 @@ class PlanitechConnector(BaseResource):
         end_datetime = combine_date_time(post_data['date'], post_data['end_time'])
         request_date = datetime.now()
 
-        pairing = self.get_or_create_pairing(post_data)
+        pairing = self.updateorcreate_user(post_data)
 
         params = {
             "activityID": mste.Uint32(post_data['activity_id']),
diff --git a/tests/test_planitech.py b/tests/test_planitech.py
index fa6eae5c..49349495 100644
--- a/tests/test_planitech.py
+++ b/tests/test_planitech.py
@@ -213,6 +213,35 @@ def test_create_reservation(app, connector, monkeypatch):
     assert reservation_args[1] == 'createReservation'
     assert Pairing.objects.count() == 1
 
+    # Changing price code update pairing and planitec user
+    new_params = params.copy()
+    new_params['price_code'] = 'T2'
+    new_side_effect = side_effect[:]
+    new_side_effect[0] = {
+        'modificationStatus': 'OK',
+        'externalUserIdentifier': '22b9c0d91fdc4f379d1356a4aaa9d38b',
+        'requestDate': datetime(2019, 1, 9, 15, 41),
+        'requestName': 'updatePerson',
+        'responseDate': datetime(2019, 1, 9, 15, 41)
+    }
+    mock_call_planitech = mock_planitech(monkeypatch, side_effect=new_side_effect)
+    response = app.post_json('/planitech/slug-planitech/createreservation', params=new_params)
+    json_resp = response.json
+    assert json_resp['err'] == 0
+    assert json_resp['data']['reservation_id'] == 1
+
+    person_args = mock_call_planitech.call_args_list[0][0]
+    assert person_args[1] == 'updatePerson'
+    person_args = person_args[2]
+    assert person_args['pricingCode'] == 'T2'
+    external_id = person_args['externalUserIdentifier']
+    assert Pairing.objects.count() == 1
+    pairing = Pairing.objects.get(external_id=external_id)
+    assert pairing.price_code == 'T2'
+
+    reservation_args = mock_call_planitech.call_args_list[1][0]
+    assert reservation_args[1] == 'createReservation'
+
     # Create reservation failed
     mock_call_planitech = mock_planitech(
         monkeypatch, return_value={
-- 
2.20.1

