Repository: mozmeao/basket

Issue:
Add Event ID and Event Name to SFDC integration
Please add the event id and event name (both text (50) len + type) to the subscription services methods that are inserting and updating information in Salesforce for transactions. 


Discussion:
@desiree-mofo Confirming the request here - all Subhub data sent to Salesforce by basket should include the event id and event name? If so, what are the corresponding field names in Salesforce? 
Field names are 
 Event_Id__c
 Event_Name__c
Both are Text(100) and are on the Opportunity object
@desiree-mofo are the names in the JSON data we receive `event_id` and `event_name` respectively? For which events are they sent?
@pmac  - they are sent on every event, but we only care about the ones hitting Opportunities (everything in the spreadsheet except contact_created) Spreadsheet linked below (which I just granted you access to) 
https://docs.google.com/spreadsheets/d/1z6aXj_9GUpl5g_hR2k_SmjY5tyhxvnoHGOr8e-cbo18/edit#gid=331823332

The field names should be coming through into Basket as event_id and event_type. I've asked Marty to update the spreadsheet with that info so we have it on file if necessary.

Resolving patch:
diff --git a/basket/news/backends/sfdc.py b/basket/news/backends/sfdc.py
--- a/basket/news/backends/sfdc.py
+++ b/basket/news/backends/sfdc.py
@@ -77,6 +77,7 @@ def cast_lower(value):
     'amo_homepage': 'AMO_Homepage_URL__c',
     'payee_id': 'PMT_Cust_Id__c',
     'fxa_id': 'FxA_Id__c',
+    'fxa_deleted': 'FxA_Account_Deleted__c',
 }
 INV_FIELD_MAP = {v: k for k, v in FIELD_MAP.items()}
 FIELD_DEFAULTS = {
@@ -332,30 +333,29 @@ def dev_addon(self):
         return self._dev_addon
 
     @time_request
-    def get(self, token=None, email=None, payee_id=None, amo_id=None):
+    def get(self, token=None, email=None, payee_id=None, amo_id=None, fxa_id=None):
         """
-        Get a contact record.
+        Get a contact record. One of the arguments is required.
 
         @param token: external ID
         @param email: email address
         @param payee_id: external ID from Stripe/payment processor
         @param amo_id: external ID from AMO
+        @param fxa_id: external ID from FxA
         @return: dict
         """
-        assert token or email or payee_id or amo_id, 'token, email, amo_id, or payee_id is required'
-
-        if token:
-            field = 'token'
-            value = token
-        elif email:
-            field = 'email'
-            value = email
-        elif payee_id:
-            field = 'payee_id'
-            value = payee_id
-        elif amo_id:
-            field = 'amo_id'
-            value = amo_id
+        arg_values = locals()
+        args = ('token', 'email', 'payee_id', 'amo_id', 'fxa_id')
+        field = None
+        value = None
+        for arg in args:
+            if arg_values[arg] is not None:
+                field = arg
+                value = arg_values[arg]
+                break
+
+        if field is None:
+            raise RuntimeError('One of the arguments is required: ' + ', '.join(args))
 
         id_field = FIELD_MAP[field]
         contact = self.contact.get_by_custom_id(id_field, value)
diff --git a/basket/news/tasks.py b/basket/news/tasks.py
--- a/basket/news/tasks.py
+++ b/basket/news/tasks.py
@@ -236,6 +236,9 @@ def fxa_email_changed(data):
 @et_task
 def fxa_delete(data):
     sfmc.upsert_row('FXA_Deleted', {'FXA_ID': data['uid']})
+    user_data = get_user_data(fxa_id=data['uid'], extra_fields=['id'])
+    if user_data:
+        sfdc.update(user_data, {'fxa_deleted': True})
 
 
 @et_task
@@ -790,6 +793,8 @@ def process_subhub_event_subscription_charge(data):
             'Credit_Card_Type__c': data['brand'],
             'currency__c': data['currency'],
             'Donation_Contact__c': user_data['id'],
+            'Event_Id__c': data['event_id'],
+            'Event_Name__c': data['event_type'],
             'Initial_Purchase__c': data['event_type'] == 'customer.subscription.created',
             'Invoice_Number__c': data['invoice_number'],
             'Last_4_Digits__c': data['last4'],
@@ -827,6 +832,8 @@ def process_subhub_event_subscription_cancel(data):
             'Billing_Cycle_Start__c': iso_format_unix_timestamp(data['current_period_start']),
             'CloseDate': iso_format_unix_timestamp(data['cancel_at']),
             'Donation_Contact__c': user_data['id'],
+            'Event_Id__c': data['event_id'],
+            'Event_Name__c': data['event_type'],
             'Name': 'Subscription Services',
             'Payment_Source__c': 'Stripe',
             'PMT_Subscription_ID__c': data['subscription_id'],
@@ -867,6 +874,8 @@ def process_subhub_event_payment_failed(data):
             'Amount': cents_to_dollars(data['amount_due']),
             'CloseDate': iso_format_unix_timestamp(data['created']),
             'Donation_Contact__c': user_data['id'],
+            'Event_Id__c': data['event_id'],
+            'Event_Name__c': data['event_type'],
             'Name': 'Subscription Services',
             'PMT_Subscription_ID__c': data['subscription_id'],
             'PMT_Transaction_ID__c': data['charge_id'],
diff --git a/basket/news/utils.py b/basket/news/utils.py
--- a/basket/news/utils.py
+++ b/basket/news/utils.py
@@ -294,7 +294,7 @@ def language_code_is_valid(code):
 ]
 
 
-def get_user_data(token=None, email=None, payee_id=None, amo_id=None,
+def get_user_data(token=None, email=None, payee_id=None, amo_id=None, fxa_id=None,
                   extra_fields=None, get_fxa=False):
     """Return a dictionary of the user's data from Exact Target.
     Look them up by their email or payment processor id (e.g. Stripe) if given,
@@ -334,7 +334,7 @@ def get_user_data(token=None, email=None, payee_id=None, amo_id=None,
     }
     """
     try:
-        user = sfdc.get(token, email, payee_id, amo_id)
+        user = sfdc.get(token, email, payee_id, amo_id, fxa_id)
     except sfapi.SalesforceResourceNotFound:
         return None
     except requests.exceptions.RequestException as e:


Test patch:
diff --git a/basket/news/tests/test_tasks.py b/basket/news/tests/test_tasks.py
--- a/basket/news/tests/test_tasks.py
+++ b/basket/news/tests/test_tasks.py
@@ -283,6 +283,8 @@ def test_charge_disputed(self, sfdc_mock):
 @patch('basket.news.tasks.sfdc')
 class SubHubEventTests(TestCase):
     charge_data = {
+        'event_id': 'the-event-id',
+        'event_type': 'customer.source.expiring',
         'customer_id': 'cus_1234',
         'plan_amount': '1000',
         'current_period_end': '1566305505',
@@ -352,6 +354,8 @@ def test_payment_failed(self, sfdc_mock, gud_mock):
         gud_mock.return_value = {'id': '1234'}
 
         data = {
+            'event_id': 'the-event-id',
+            'event_type': 'invoice.payment_failed',
             'customer_id': 'cus_1234',
             'amount_due': '1000',
             'created': '1566305505',
@@ -369,6 +373,8 @@ def test_payment_failed(self, sfdc_mock, gud_mock):
             'Amount': 10.00,
             'CloseDate': '2019-08-20T12:51:45',
             'Donation_Contact__c': '1234',
+            'Event_Id__c': data['event_id'],
+            'Event_Name__c': data['event_type'],
             'Name': 'Subscription Services',
             'PMT_Subscription_ID__c': data['subscription_id'],
             'PMT_Transaction_ID__c': data['charge_id'],
@@ -383,6 +389,8 @@ def test_subscription_cancel(self, sfdc_mock, gud_mock):
         gud_mock.return_value = {'id': '1234'}
 
         data = {
+            'event_id': 'the-event-id',
+            'event_type': 'customer.subscription_cancelled',
             'customer_id': 'cus_1234',
             'plan_amount': '1000',
             'current_period_end': '1566305505',
@@ -402,6 +410,8 @@ def test_subscription_cancel(self, sfdc_mock, gud_mock):
             'Billing_Cycle_Start__c': '2019-08-20T12:51:42',
             'CloseDate': '2019-08-20T12:51:49',
             'Donation_Contact__c': '1234',
+            'Event_Id__c': data['event_id'],
+            'Event_Name__c': data['event_type'],
             'Name': 'Subscription Services',
             'Payment_Source__c': 'Stripe',
             'PMT_Subscription_ID__c': data['subscription_id'],
@@ -428,6 +438,8 @@ def test_subscription_charge_initial(self, sfdc_mock, gud_mock):
             'Credit_Card_Type__c': data['brand'],
             'currency__c': data['currency'],
             'Donation_Contact__c': '1234',
+            'Event_Id__c': data['event_id'],
+            'Event_Name__c': data['event_type'],
             'Initial_Purchase__c': True,
             'Invoice_Number__c': data['invoice_number'],
             'Last_4_Digits__c': data['last4'],
@@ -458,6 +470,8 @@ def test_subscription_charge_recurring(self, sfdc_mock, gud_mock):
             'Credit_Card_Type__c': data['brand'],
             'currency__c': data['currency'],
             'Donation_Contact__c': '1234',
+            'Event_Id__c': data['event_id'],
+            'Event_Name__c': data['event_type'],
             'Initial_Purchase__c': False,
             'Invoice_Number__c': data['invoice_number'],
             'Last_4_Digits__c': data['last4'],