Repository: mozmeao/basket

Issue:
None value throwing errors in sfdc.py/to_vendor
Appears to be similar to #193. Changes to MoFo are impacting collecting subscriptions.

Specific error is [this line in sfdc.py in the `to_vendor` method](https://github.com/mozmeao/basket/blob/prod/basket/news/backends/sfdc.py#L165):

`if field in contact and len(contact[field]) > length:`

Error thrown is: `TypeError: object of type 'NoneType' has no len()`

Sentry shows `FirstName` has a value of `None`.

Error report is [here](https://sentry.prod.mozaws.net/operations/basket-prod/issues/5947191/).


Discussion:
Did the items I put in this morning not take?
After a quick look at the data, these errors doesn't appear to match that from yesterday.

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
@@ -138,7 +138,7 @@ def to_vendor(data):
             data['lang'] = 'en'
 
     for k, v in data.items():
-        if v != '' and k in FIELD_MAP:
+        if v is not None and v != '' and k in FIELD_MAP:
             if k in PROCESSORS_TO_VENDOR:
                 v = PROCESSORS_TO_VENDOR[k](v)
 


Test patch:
diff --git a/basket/news/tests/test_sfdc.py b/basket/news/tests/test_sfdc.py
--- a/basket/news/tests/test_sfdc.py
+++ b/basket/news/tests/test_sfdc.py
@@ -195,6 +195,64 @@ def test_to_vendor_blank_values(self):
         }
         self.assertDictEqual(to_vendor(data), contact)
 
+    def test_to_vendor_none_values(self):
+        data = {
+            'email': 'dude@example.com',
+            'token': 'totally-token-man',
+            'format': 'H',
+            'country': 'US',
+            'lang': 'en',
+            'source_url': 'https://www.example.com',
+            'first_name': None,
+            'last_name': None,
+            'fsa_allow_share': 'y',
+            'optout': 'no',
+            'optin': 'true',
+        }
+        contact = {
+            'Email_Format__c': 'H',
+            'Subscriber__c': True,
+            'Email_Language__c': 'en',
+            'Signup_Source_URL__c': 'https://www.example.com',
+            'Token__c': 'totally-token-man',
+            'Email': 'dude@example.com',
+            'MailingCountryCode': 'us',
+            'FSA_Allow_Info_Shared__c': True,
+            'HasOptedOutOfEmail': False,
+            'Double_Opt_In__c': True,
+        }
+        self.assertDictEqual(to_vendor(data), contact)
+
+    def test_to_vendor_truncated_values(self):
+        data = {
+            'email': 'dude@example.com',
+            'token': 'totally-token-man',
+            'format': 'H',
+            'country': 'US',
+            'lang': 'en',
+            'source_url': 'https://www.example.com',
+            'first_name': 'x' * 50,  # limited to 40 chars
+            'last_name': 'x' * 90,  # limited to 80 chars
+            'fsa_allow_share': 'y',
+            'optout': 'no',
+            'optin': 'true',
+        }
+        contact = {
+            'Email_Format__c': 'H',
+            'Subscriber__c': True,
+            'FirstName': 'x' * 40,
+            'LastName': 'x' * 80,
+            'Email_Language__c': 'en',
+            'Signup_Source_URL__c': 'https://www.example.com',
+            'Token__c': 'totally-token-man',
+            'Email': 'dude@example.com',
+            'MailingCountryCode': 'us',
+            'FSA_Allow_Info_Shared__c': True,
+            'HasOptedOutOfEmail': False,
+            'Double_Opt_In__c': True,
+        }
+        self.assertDictEqual(to_vendor(data), contact)
+
     def test_to_vendor_boolean_casting(self):
         data = {
             'email': 'dude@example.com',