Awight has uploaded a new change for review.
https://gerrit.wikimedia.org/r/314509
Change subject: WIP Regression test for T143903
......................................................................
WIP Regression test for T143903
Bug: T143903
Change-Id: I866b1771f77989085e840a4eb2d320c5fb1a2f89
---
A audit/__init__.py
M audit/paypal/TrrFile.py
M audit/paypal/paypal_api.py
A audit/paypal/tests/test_trr_file.py
M process/globals.py
5 files changed, 113 insertions(+), 20 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/wikimedia/fundraising/tools
refs/changes/09/314509/1
diff --git a/audit/__init__.py b/audit/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/audit/__init__.py
diff --git a/audit/paypal/TrrFile.py b/audit/paypal/TrrFile.py
index 1bbed11..b68e465 100644
--- a/audit/paypal/TrrFile.py
+++ b/audit/paypal/TrrFile.py
@@ -6,12 +6,12 @@
import re
from process.logging import Logger as log
-from process.globals import config
-from queue.redis_wrap import Redis
+import process.globals
+import queue.redis_wrap
import ppreport
-from civicrm.civicrm import Civicrm
-from paypal_api import PaypalApiClassic
+import civicrm.civicrm
+import paypal_api
class TrrFile(object):
@@ -83,7 +83,8 @@
def __init__(self, path):
self.path = path
- self.crm = Civicrm(config.civicrm_db)
+ self.config = process.globals.get_config()
+ self.crm = civicrm.civicrm.Civicrm(self.config.civicrm_db)
def parse(self):
# FIXME: encapsulation issues
@@ -180,19 +181,19 @@
return
if 'last_name' not in out and queue != 'refund':
- out['first_name'], out['last_name'] =
self.fetch_donor_name(out['gateway_txn_id'])
+ out['first_name'], out['last_name'] =
paypal_api.PaypalApiClassic().fetch_donor_name(out['gateway_txn_id'])
- if config.no_thankyou:
+ if self.config.no_thankyou:
out['thankyou_date'] = 0
log.info("+Sending\t{id}\t{date}\t{type}".format(id=out['gateway_txn_id'],
date=row['Transaction Initiation Date'], type=queue))
self.send(queue, out)
- def send(self, queue, msg):
+ def send(self, queue_name, msg):
if not self.redis:
- self.redis = Redis()
+ self.redis = queue.redis_wrap.Redis()
- self.redis.send(queue, msg)
+ self.redis.send(queue_name, msg)
def normalize_recurring(self, msg):
'Synthesize a raw PayPal message'
@@ -200,6 +201,14 @@
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',
@@ -219,10 +228,3 @@
}
return out
-
- def fetch_donor_name(self, txn_id):
- api = PaypalApiClassic()
- response = api.call('GetTransactionDetails', TRANSACTIONID=txn_id)
- if 'FIRSTNAME' not in response:
- raise RuntimeError("Failed to get transaction details for {id},
repsonse: {response}".format(id=txn_id, response=response))
- return (response['FIRSTNAME'][0], response['LASTNAME'][0])
diff --git a/audit/paypal/paypal_api.py b/audit/paypal/paypal_api.py
index 327d7b6..a4f2599 100644
--- a/audit/paypal/paypal_api.py
+++ b/audit/paypal/paypal_api.py
@@ -1,9 +1,9 @@
-from process.globals import config
-
import httplib
import urllib
import urllib2
import urlparse
+
+import process.globals
class PaypalApiClassic(object):
@@ -11,6 +11,7 @@
VERSION = '124.0'
def call(self, cmd, **kw):
+ config = process.globals.get_config()
params = {
'PWD': config.api.password,
'USER': config.api.username,
@@ -44,6 +45,12 @@
return result
+ def fetch_donor_name(self, txn_id):
+ response = self.call('GetTransactionDetails', TRANSACTIONID=txn_id)
+ if 'FIRSTNAME' not in response:
+ raise RuntimeError("Failed to get transaction details for {id},
repsonse: {response}".format(id=txn_id, response=response))
+ return (response['FIRSTNAME'][0], response['LASTNAME'][0])
+
# from
http://stackoverflow.com/questions/1875052/using-paired-certificates-with-urllib2
class HTTPSClientAuthHandler(urllib2.HTTPSHandler):
diff --git a/audit/paypal/tests/test_trr_file.py
b/audit/paypal/tests/test_trr_file.py
new file mode 100644
index 0000000..54f5dab
--- /dev/null
+++ b/audit/paypal/tests/test_trr_file.py
@@ -0,0 +1,83 @@
+from mock import patch
+import nose.tools
+
+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",
+ "Transaction Initiation Date": "",
+ "Transaction Completion Date": "",
+ "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.
+ 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([])
diff --git a/process/globals.py b/process/globals.py
index 4b7825b..5173fd0 100644
--- a/process/globals.py
+++ b/process/globals.py
@@ -3,7 +3,8 @@
from process.logging import Logger as log
-# n.b. Careful not to import `config` by value
+# n.b. Careful not to import `config` by value. TODO: rename to _config to
+# break external usages.
config = dict()
--
To view, visit https://gerrit.wikimedia.org/r/314509
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I866b1771f77989085e840a4eb2d320c5fb1a2f89
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/fundraising/tools
Gerrit-Branch: master
Gerrit-Owner: Awight <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits