Ejegg has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/342693 )
Change subject: WIP stop denormalizing paypal recurring messages in audit ...................................................................... WIP stop denormalizing paypal recurring messages in audit Change-Id: I6b0c881a16a4d5ab6f60dfe401aea576ccbf6f03 --- M audit/paypal/TrrFile.py M audit/paypal/tests/test_trr_file.py 2 files changed, 85 insertions(+), 125 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/tools refs/changes/93/342693/1 diff --git a/audit/paypal/TrrFile.py b/audit/paypal/TrrFile.py index bdd8b02..4ced975 100644 --- a/audit/paypal/TrrFile.py +++ b/audit/paypal/TrrFile.py @@ -153,7 +153,8 @@ if event_type in ('T00', 'T03', 'T05', 'T07', 'T22'): if row['Transaction Event Code'] == 'T0002': queue = 'recurring' - out = self.normalize_recurring(out) + if 'subscr_id' not in out or not out['subscr_id']: + raise Exception('Missing field subscr_id') elif row['Transaction Debit or Credit'] == 'DR': # sic: double-space is coming from the upstream log.info("-Debit\t{id}\t{date}\tPayment to".format(id=out['gateway_txn_id'], date=out['date'])) @@ -207,36 +208,3 @@ self.redis.send(queue_name, msg) - def normalize_recurring(self, msg): - 'Synthesize a raw PayPal message' - - if 'fee' not in msg: - msg['fee'] = 0 - - # TODO: Move validation elsewhere. - required_fields = ['subscr_id'] - for field in required_fields: - if field not in msg or not msg[field]: - raise Exception("Missing field " + field) - - # FIXME: Are the names available in these records? That would save us - # an API to fetch_donor_name. - out = { - 'gateway': 'paypal', - 'txn_type': 'subscr_payment', - 'gateway_txn_id': msg['gateway_txn_id'], - 'txn_id': msg['gateway_txn_id'], - 'subscr_id': msg['subscr_id'], - 'payment_date': msg['date'], - 'payer_email': msg['email'], - 'mc_currency': msg['currency'], - 'mc_gross': msg['gross'], - 'mc_fee': msg['fee'], - 'address_street': "\n".join([msg['street_address'], msg['supplemental_address_1']]), - 'address_city': msg['city'], - 'address_zip': msg['postal_code'], - 'address_state': msg['state_province'], - 'address_country_code': msg['country'], - } - - return out diff --git a/audit/paypal/tests/test_trr_file.py b/audit/paypal/tests/test_trr_file.py index fc1981c..1f3bc93 100644 --- a/audit/paypal/tests/test_trr_file.py +++ b/audit/paypal/tests/test_trr_file.py @@ -4,103 +4,21 @@ import audit.paypal.TrrFile -@patch("queue.redis_wrap.Redis") -@patch("civicrm.civicrm.Civicrm") -@patch("process.globals") -@patch("audit.paypal.paypal_api.PaypalApiClassic") -def test_recurring_charge_without_subscription(MockPaypalApi, MockGlobals, MockCivicrm, MockRedis): - ''' - Regression test for T143903 - ''' - row = { - "Column Type": "", - "Transaction ID": "", - "Invoice ID": "", - "PayPal Reference ID": "", - "PayPal Reference ID Type": "SUB", - "Transaction Event Code": "T0002", - # FIXME: Use and test real date format. - "Transaction Initiation Date": "Thu Oct 13 19:53:57 UTC 2016", - "Transaction Completion Date": "Thu Oct 13 19:53:58 UTC 2016", - # sic. - "Transaction Debit or Credit": "", - "Gross Transaction Amount": "10.00", - "Gross Transaction Currency": "", - "Fee Debit or Credit": "", - "Fee Amount": "", - "Fee Currency": "", - "Transactional Status": "", - "Insurance Amount": "", - "Sales Tax Amount": "", - "Shipping Amount": "", - "Transaction Subject": "", - "Transaction Note": "", - "Payer's Account ID": "", - "Payer Address Status": "", - "Item Name": "", - "Item ID": "", - "Option 1 Name": "", - "Option 1 Value": "", - "Option 2 Name": "", - "Option 2 Value": "", - "Auction Site": "", - "Auction Buyer ID": "", - "Auction Closing Date": "", - "Shipping Address Line1": "", - "Shipping Address Line2": "", - "Shipping Address City": "", - "Shipping Address State": "", - "Shipping Address Zip": "", - "Shipping Address Country": "", - "Shipping Method": "", - "Custom Field": "", - "Billing Address Line1": "", - "Billing Address Line2": "", - "Billing Address City": "", - "Billing Address State": "", - "Billing Address Zip": "", - "Billing Address Country": "", - "Consumer ID": "", - "First Name": "Malcolm", - "Last Name": "3X", - "Consumer Business Name": "", - "Card Type": "", - "Payment Source": "", - "Shipping Name": "", - "Authorization Review Status": "", - "Protection Eligibility": "", - "Payment Tracking ID": "", - } - MockCivicrm().transaction_exists.return_value = False - MockPaypalApi().fetch_donor_name.return_value = ("Malcolm", "3X") - - parser = audit.paypal.TrrFile.TrrFile("dummy_path") - with nose.tools.assert_raises(Exception) as cm: - parser.parse_line(row) - - # Should have failed with a specific missing field error. - # FIXME: Annoyingly, this masks any other, unexpected exception. - assert cm.exception.message == "Missing field subscr_id" - - # Make sure we didn't try to send anything to the queue. - MockRedis().send.assert_has_calls([]) - - -def get_refund_row(): +def get_base_row(): return { "Column Type": "SB", "Transaction ID": "AS7D98AS7D9A8S7D9AS", "Invoice ID": "", - "PayPal Reference ID": "3GJH3GJ3334214812", - "PayPal Reference ID Type": "TXN", - "Transaction Event Code": "T1107", + "PayPal Reference ID": "", + "PayPal Reference ID Type": "", + "Transaction Event Code": "", "Transaction Initiation Date": "2016/09/24 11:55:01 -0700", "Transaction Completion Date": "2016/09/24 11:55:01 -0700", - "Transaction Debit or Credit": "DR", + "Transaction Debit or Credit": "", "Gross Transaction Amount": "1000", "Gross Transaction Currency": "USD", - "Fee Debit or Credit": "CR", + "Fee Debit or Credit": "", "Fee Amount": "55", "Fee Currency": "USD", "Transactional Status": "S", @@ -108,7 +26,7 @@ "Sales Tax Amount": "0", "Shipping Amount": "0", "Transaction Subject": "", - "Transaction Note": "r", + "Transaction Note": "", "Payer's Account ID": "pranks...@anonymous.net", "Payer Address Status": "N", "Item Name": "Generous benificence", @@ -143,8 +61,62 @@ "Shipping Name": "", "Authorization Review Status": "", "Protection Eligibility": "", - "Payment Tracking ID": "", + "Payment Tracking ID": "" } + + +def get_refund_row(): + + row = get_base_row() + row.update({ + "PayPal Reference ID": "3GJH3GJ3334214812", + "PayPal Reference ID Type": "TXN", + "Transaction Event Code": "T1107", + "Transaction Debit or Credit": "DR", + "Fee Debit or Credit": "CR", + "Fee Amount": "55", + "Transaction Note": "r", + "Payer's Account ID": "pranks...@anonymous.net" + }) + return row + + +def get_recurring_row(): + row = get_base_row() + row.update({ + "PayPal Reference ID": "3GJH3GJ3334214812", + "PayPal Reference ID Type": "SUB", + "Transaction Event Code": "T0002", + "Gross Transaction Amount": "10.00", + }) + return row + + +@patch("queue.redis_wrap.Redis") +@patch("civicrm.civicrm.Civicrm") +@patch("process.globals") +@patch("audit.paypal.paypal_api.PaypalApiClassic") +def test_recurring_charge_without_subscription(MockPaypalApi, MockGlobals, MockCivicrm, MockRedis): + ''' + Regression test for T143903 + ''' + row = get_recurring_row() + row["Transaction ID"] = "" + row["PayPal Reference ID"] = "" + + MockCivicrm().transaction_exists.return_value = False + MockPaypalApi().fetch_donor_name.return_value = ("Malcolm", "3X") + + parser = audit.paypal.TrrFile.TrrFile("dummy_path") + with nose.tools.assert_raises(Exception) as cm: + parser.parse_line(row) + + # Should have failed with a specific missing field error. + # FIXME: Annoyingly, this masks any other, unexpected exception. + assert cm.exception.message == "Missing field subscr_id" + + # Make sure we didn't try to send anything to the queue. + MockRedis().send.assert_has_calls([]) @patch("queue.redis_wrap.Redis") @@ -174,7 +146,7 @@ @patch("process.globals") def test_refund_duplicate(MockGlobals, MockCivicrm, MockRedis): ''' - Test that we send a refund for a donation that isn't yet refunded + Test that we do not send a refund for a donation that is refunded ''' row = get_refund_row() MockCivicrm().transaction_refunded.return_value = True @@ -185,3 +157,23 @@ # Did we send it? MockRedis().send.assert_has_calls([]) + + +@patch("queue.redis_wrap.Redis") +@patch("process.globals") +def test_recurring(MockGlobals, MockRedis): + ''' + Test that we send a normalized message for recurring donations + ''' + row = get_recurring_row() + parser = audit.paypal.TrrFile.TrrFile("dummy_path") + + parser.parse_line(row) + + # Did we send it? + args = MockRedis().send.call_args + assert args[0][0] == 'recurring' + expected = sorted({'last_name': 'Man', 'thankyou_date': 0, 'city': '', 'payment_method': '', 'gateway_status': 'S', 'currency': 'USD', 'postal_code': '', 'date': '1474736101', 'subscr_id': '3GJH3GJ3334214812', 'gateway': 'paypal', 'state_province': '', 'gross': 0.1, 'first_name': 'Banana', 'fee': 0.55, 'gateway_txn_id': 'AS7D98AS7D9A8S7D9AS', 'country': '', 'payment_submethod': '', 'note': '', 'supplemental_address_1': '', 'settled_date': '1474736101', 'email': 'pranks...@anonymous.net', 'street_address': ''}) + actual = sorted(args[0][1]) + assert actual == expected + -- To view, visit https://gerrit.wikimedia.org/r/342693 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6b0c881a16a4d5ab6f60dfe401aea576ccbf6f03 Gerrit-PatchSet: 1 Gerrit-Project: wikimedia/fundraising/tools Gerrit-Branch: master Gerrit-Owner: Ejegg <eeggles...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits