Private
Public Access
1
0
This commit is contained in:
Sander Roosendaal
2022-02-15 08:05:12 +01:00
parent 5b3d7fcf2c
commit 8af7ac8af4
71 changed files with 19992 additions and 19476 deletions

View File

@@ -1,4 +1,25 @@
from __future__ import absolute_import
from rowers.models import Rower, PaidPlan, CoachingGroup
from rowers.utils import ProcessorCustomerError
from rowsandall_app.settings import (
BRAINTREE_MERCHANT_ID, BRAINTREE_PUBLIC_KEY, BRAINTREE_PRIVATE_KEY,
BRAINTREE_SANDBOX_MERCHANT_ID, BRAINTREE_SANDBOX_PUBLIC_KEY,
BRAINTREE_SANDBOX_PRIVATE_KEY, BRAINTREE_MERCHANT_ACCOUNT_ID
)
import pandas as pd
from rowers.utils import dologging
from rowers import credits
from rowers.tasks import (
handle_send_email_transaction,
handle_send_email_subscription_update,
handle_send_email_subscription_create,
handle_send_email_failed_cancel,
# handle_send_email_transaction_notification,
)
from rowers.utils import myqueue
import rowers.fakturoid as fakturoid
from braintree.exceptions.invalid_signature_error import InvalidSignatureError
import time
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
@@ -13,32 +34,8 @@ queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low')
queuehigh = django_rq.get_queue('low')
import time
from braintree.exceptions.invalid_signature_error import InvalidSignatureError
import rowers.fakturoid as fakturoid
from rowers.utils import myqueue
from rowers.tasks import (
handle_send_email_transaction,
handle_send_email_subscription_update,
handle_send_email_subscription_create,
handle_send_email_failed_cancel,
#handle_send_email_transaction_notification,
)
from rowers import credits
from rowers.utils import dologging
import pandas as pd
from rowsandall_app.settings import (
BRAINTREE_MERCHANT_ID,BRAINTREE_PUBLIC_KEY,BRAINTREE_PRIVATE_KEY,
BRAINTREE_SANDBOX_MERCHANT_ID,BRAINTREE_SANDBOX_PUBLIC_KEY,
BRAINTREE_SANDBOX_PRIVATE_KEY, BRAINTREE_MERCHANT_ACCOUNT_ID
)
if settings.DEBUG or 'dev' in settings.SITE_URL: # pragma: no cover
if settings.DEBUG or 'dev' in settings.SITE_URL: # pragma: no cover
gateway = braintree.BraintreeGateway(
braintree.Configuration(
braintree.Environment.Sandbox,
@@ -58,12 +55,9 @@ else:
)
from rowers.models import Rower,PaidPlan, CoachingGroup
from rowers.utils import ProcessorCustomerError
def process_webhook(notification):
if not settings.TESTING: # pragma: no cover
with open('braintreewebhooks.log','a') as f:
if not settings.TESTING: # pragma: no cover
with open('braintreewebhooks.log', 'a') as f:
t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
try:
@@ -73,8 +67,8 @@ def process_webhook(notification):
if notification.kind == 'subscription_charged_successfully':
subscription = notification.subscription
rs = Rower.objects.filter(subscription_id=subscription.id)
if rs.count() == 0: # pragma: no cover
dologging('braintreewebhooks.log','Could not find rowers with subscription ID {id}'.format(
if rs.count() == 0: # pragma: no cover
dologging('braintreewebhooks.log', 'Could not find rowers with subscription ID {id}'.format(
id=subscription.id
))
else:
@@ -82,57 +76,61 @@ def process_webhook(notification):
transactions = subscription.transactions
if transactions:
amount = int(transactions[0].amount)
eurocredits = credits.upgrade(amount,r)
eurocredits = credits.upgrade(amount,r)
eurocredits = credits.upgrade(amount, r)
eurocredits = credits.upgrade(amount, r)
return send_invoice(notification.subscription)
if notification.kind == 'subscription_canceled':
subscription = notification.subscription
rs = Rower.objects.filter(subscription_id=subscription.id)
if rs.count() == 0: # pragma: no cover
with open('braintreewebhooks.log','a') as f:
f.write('Could not find rowers with subscription ID '+subscription.id+'\n')
if rs.count() == 0: # pragma: no cover
with open('braintreewebhooks.log', 'a') as f:
f.write('Could not find rowers with subscription ID ' +
subscription.id+'\n')
return 0
r = rs[0]
result,mesg,errormsg = cancel_subscription(r,subscription.id)
result, mesg, errormsg = cancel_subscription(r, subscription.id)
if result:
with open('braintreewebhooks.log','a') as f:
with open('braintreewebhooks.log', 'a') as f:
f.write('Subscription canceled: '+str(subscription.id)+'\n')
return subscription.id
with open('braintreewebhooks.log','a') as f: # pragma: no cover
f.write('Could not cancel Subscription: '+str(subscription.id)+'\n')
return 0 # pragma: no cover
with open('braintreewebhooks.log', 'a') as f: # pragma: no cover
f.write('Could not cancel Subscription: ' +
str(subscription.id)+'\n')
return 0 # pragma: no cover
return 0
def send_invoice(subscription):
with open('braintreewebhooks.log','a') as f:
with open('braintreewebhooks.log', 'a') as f:
t = time.localtime()
timestamp = time.strftime('%b-%d-%Y_%H%M', t)
f.write('Subscription ID '+str(subscription.id)+'\n')
subscription_id = subscription.id
rs = Rower.objects.filter(subscription_id=subscription_id)
if rs.count() == 0: # pragma: no cover
if rs.count() == 0: # pragma: no cover
return 0
else:
r = rs[0]
with open('braintreewebhooks.log','a') as f:
with open('braintreewebhooks.log', 'a') as f:
f.write('Rower '+str(r)+'\n')
fakturoid_contact_id = fakturoid.get_contacts(r)
with open('braintreewebhooks.log','a') as f:
with open('braintreewebhooks.log', 'a') as f:
f.write('Fakturoid Contact ID '+str(fakturoid_contact_id)+'\n')
if not fakturoid_contact_id: # pragma: no cover
if not fakturoid_contact_id: # pragma: no cover
fakturoid_contact_id = fakturoid.create_contact(r)
with open('braintreewebhooks.log','a') as f:
f.write('Created Fakturoid Contact ID '+str(fakturoid_contact_id)+'\n')
with open('braintreewebhooks.log', 'a') as f:
f.write('Created Fakturoid Contact ID ' +
str(fakturoid_contact_id)+'\n')
transactions = subscription.transactions
if transactions:
amount = transactions[0].amount
with open('braintreewebhooks.log','a') as f:
with open('braintreewebhooks.log', 'a') as f:
f.write('Transaction amount '+str(amount)+'\n')
id = fakturoid.create_invoice(r,amount,subscription_id,dosend=True,
id = fakturoid.create_invoice(r, amount, subscription_id, dosend=True,
contact_id=fakturoid_contact_id)
return id
return 0 # pragma: no cover
return 0 # pragma: no cover
def webhook(request):
@@ -140,41 +138,40 @@ def webhook(request):
webhook_notification = gateway.webhook_notification.parse(
str(request.POST['bt_signature']),
request.POST['bt_payload'])
except InvalidSignatureError: # pragma: no cover
except InvalidSignatureError: # pragma: no cover
return 4
result = process_webhook(webhook_notification)
return result
def create_customer(rower,force=False):
def create_customer(rower, force=False):
if not rower.customer_id or force:
result = gateway.customer.create(
{
'first_name':rower.user.first_name,
'last_name':rower.user.last_name,
'email':rower.user.email,
})
if not result.is_success: # pragma: no cover
'first_name': rower.user.first_name,
'last_name': rower.user.last_name,
'email': rower.user.email,
})
if not result.is_success: # pragma: no cover
raise ProcessorCustomerError
else:
rower.customer_id = result.customer.id
rower.paymentprocessor = 'braintree'
rower.save()
return rower.customer_id
else: # pragma: no cover
else: # pragma: no cover
return rower.customer_id
def get_client_token(rower):
try:
client_token = gateway.client_token.generate({
"customer_id":rower.customer_id,
"customer_id": rower.customer_id,
})
except ValueError: # pragma: no cover
customer_id = create_customer(rower,force=True)
except ValueError: # pragma: no cover
customer_id = create_customer(rower, force=True)
client_token = gateway.client_token.generate({
"customer_id": customer_id,
@@ -182,7 +179,8 @@ def get_client_token(rower):
return client_token
def get_plans_costs(): # pragma: no cover
def get_plans_costs(): # pragma: no cover
plans = gateway.plan.all()
localplans = PaidPlan.object.filter(paymentprocessor='braintree')
@@ -195,21 +193,23 @@ def get_plans_costs(): # pragma: no cover
return plans
def make_payment(rower,data):
def make_payment(rower, data):
nonce_from_the_client = data['payment_method_nonce']
nonce = gateway.payment_method_nonce.find(nonce_from_the_client)
info = nonce.three_d_secure_info
if nonce.type.lower() == 'creditcard': # pragma: no cover
if nonce.type.lower() == 'creditcard': # pragma: no cover
if info is None or not info.liability_shifted:
return False,0
return False, 0
amount = data['amount']
amount = '{amount}'.format(amount=amount)
if 'plan' in data:
theplan = data['plan']
additional_text = 'Rowsandall Purchase Plan nr {theplan}'.format(theplan=theplan)
else: # pragma: no cover
additional_text = 'Rowsandall Purchase Plan nr {theplan}'.format(
theplan=theplan)
else: # pragma: no cover
additional_text = 'Rowsandall Purchase'
result = gateway.transaction.sale({
@@ -223,54 +223,53 @@ def make_payment(rower,data):
transaction = result.transaction
amount = transaction.amount
name = '{f} {l}'.format(
f = rower.user.first_name,
l = rower.user.last_name,
)
f=rower.user.first_name,
l=rower.user.last_name,
)
fakturoid_contact_id = fakturoid.get_contacts(rower)
if not fakturoid_contact_id:
fakturoid_contact_id = fakturoid.create_contact(rower)
id = fakturoid.create_invoice(rower,amount,transaction.id,dosend=True,contact_id=fakturoid_contact_id,
id = fakturoid.create_invoice(rower, amount, transaction.id, dosend=True, contact_id=fakturoid_contact_id,
name=additional_text)
try:
job = myqueue(queuehigh,handle_send_email_transaction,
name, rower.user.email, amount)
job = myqueue(queuehigh,handle_send_email_transation_notification,
job = myqueue(queuehigh, handle_send_email_transaction,
name, rower.user.email, amount)
job = myqueue(queuehigh, handle_send_email_transation_notification,
name.rower.user.email, amount, additional_text)
except: # pragma: no cover
except: # pragma: no cover
pass
return amount,True
else: # pragma: no cover
return 0,False
return amount, True
else: # pragma: no cover
return 0, False
def update_subscription(rower,data,method='up'):
def update_subscription(rower, data, method='up'):
planid = data['plan']
plan = PaidPlan.objects.get(id=planid)
nonce_from_the_client = data['payment_method_nonce']
nonce = gateway.payment_method_nonce.find(nonce_from_the_client)
info = nonce.three_d_secure_info
if nonce.type.lower() == 'creditcard': # pragma: no cover
if nonce.type.lower() == 'creditcard': # pragma: no cover
if info is None or not info.liability_shifted:
return False,0
return False, 0
amount = data['amount']
amount = '{amount:.2f}'.format(amount=amount)
gatewaydata = {
"price": amount,
"plan_id": plan.external_id,
"payment_method_nonce": nonce_from_the_client,
"options": {
"prorate_charges":True,
},
}
"price": amount,
"plan_id": plan.external_id,
"payment_method_nonce": nonce_from_the_client,
"options": {
"prorate_charges": True,
},
}
if plan.paymenttype == 'single':
gatewaydata['number_of_billing_cycles'] = 1
else: # pragma: no cover
else: # pragma: no cover
gatewaydata['never_expires'] = True
try:
@@ -278,14 +277,14 @@ def update_subscription(rower,data,method='up'):
rower.subscription_id,
gatewaydata
)
except: # pragma: no cover
return False,0
except: # pragma: no cover
return False, 0
if result.is_success:
yesterday = (timezone.now()-datetime.timedelta(days=1)).date()
rower.paidplan = plan
amount_int = int(float(amount))
eurocredits = credits.upgrade(amount_int,rower)
eurocredits = credits.upgrade(amount_int, rower)
rower.planexpires = result.subscription.billing_period_end_date
rower.teamplanexpires = result.subscription.billing_period_end_date
rower.clubsize = plan.clubsize
@@ -296,21 +295,22 @@ def update_subscription(rower,data,method='up'):
rower.plantrialexpires = yesterday
rower.save()
name = '{f} {l}'.format(
f = rower.user.first_name,
l = rower.user.last_name,
)
f=rower.user.first_name,
l=rower.user.last_name,
)
if rower.paidplan != 'coach':
try:
coachgroup = rower.mycoachgroup
except CoachingGroup.DoesNotExist: # pragma: no cover
except CoachingGroup.DoesNotExist: # pragma: no cover
coachgroup = CoachingGroup()
coachgroup.save()
rower.mycoachgroup = coachgroup
rower.save()
athletes = Rower.objects.filter(coachinggroups__in=[rower.mycoachgroup]).distinct()
for athlete in athletes: # pragma: no cover
athletes = Rower.objects.filter(
coachinggroups__in=[rower.mycoachgroup]).distinct()
for athlete in athletes: # pragma: no cover
athlete.coachinggroups.remove(rower.mycoachgroup)
if method == 'up':
@@ -318,12 +318,11 @@ def update_subscription(rower,data,method='up'):
if transactions:
amount = transactions[0].amount
else: # pragma: no cover
else: # pragma: no cover
amount = 0
else: # pragma: no cover
else: # pragma: no cover
amount = 0
job = myqueue(queuehigh,
handle_send_email_subscription_update,
name, rower.user.email,
@@ -331,60 +330,58 @@ def update_subscription(rower,data,method='up'):
plan.paymenttype,
plan.price,
amount,
result.subscription.billing_period_end_date.strftime('%Y-%m-%d'),
result.subscription.billing_period_end_date.strftime(
'%Y-%m-%d'),
method)
return True,amount
else: # pragma: no cover
return True, amount
else: # pragma: no cover
errors = result.errors.for_object("subscription")
codes = [str(e.code) for e in errors]
create_new = False
proceed_codes = ['81901','81910']
proceed_codes = ['81901', '81910']
for c in codes:
if c in proceed_codes:
create_new = True
if create_new:
return create_subscription(rower,data)
return create_subscription(rower, data)
return False,0
return False, 0
return False,0 # pragma: no cover
return False, 0 # pragma: no cover
def create_subscription(rower,data):
def create_subscription(rower, data):
nonce_from_the_client = data['payment_method_nonce']
nonce = gateway.payment_method_nonce.find(nonce_from_the_client)
info = nonce.three_d_secure_info
paymenttype = nonce.type
if nonce.type != 'PayPalAccount': # pragma: no cover
if info is None or not info.liability_shifted:
return False,0
if nonce.type != 'PayPalAccount': # pragma: no cover
if info is None or not info.liability_shifted:
return False, 0
amount = data['amount']
planid = data['plan']
plan = PaidPlan.objects.get(id=planid)
# create or find payment method
result = gateway.payment_method.create({
"customer_id": rower.customer_id,
"payment_method_nonce": nonce_from_the_client
})
})
if result.is_success:
payment_method_token = result.payment_method.token
else: # pragma: no cover
return False,0
else: # pragma: no cover
return False, 0
result = gateway.subscription.create({
"payment_method_token": payment_method_token,
"plan_id": plan.external_id,
# "merchant_account_id": BRAINTREE_MERCHANT_ACCOUNT_ID,
})
# "merchant_account_id": BRAINTREE_MERCHANT_ACCOUNT_ID,
})
if result.is_success:
yesterday = (timezone.now()-datetime.timedelta(days=1)).date()
@@ -400,10 +397,9 @@ def create_subscription(rower,data):
rower.save()
name = '{f} {l}'.format(
f = rower.user.first_name,
l = rower.user.last_name,
)
f=rower.user.first_name,
l=rower.user.last_name,
)
recurring = plan.paymenttype
@@ -417,33 +413,33 @@ def create_subscription(rower,data):
plan.price,
result.subscription.billing_period_end_date.strftime('%Y-%m-%d')
)
return True,plan.price
else: # pragma: no cover
return False,0
return True, plan.price
else: # pragma: no cover
return False, 0
return False, 0 # pragma: no cover
return False,0 # pragma: no cover
def cancel_subscription(rower,id):
def cancel_subscription(rower, id):
themessages = []
errormessages = []
try:
result = gateway.subscription.cancel(id)
result = gateway.subscription.cancel(id)
themessages.append("Subscription canceled")
except: # pragma: no cover
errormessages.append("We could not find the subscription record in our customer database. We have notified the site owner, who will contact you.")
name = '{f} {l}'.format(f = rower.user.first_name, l = rower.user.last_name)
except: # pragma: no cover
errormessages.append(
"We could not find the subscription record in our customer database. We have notified the site owner, who will contact you.")
name = '{f} {l}'.format(f=rower.user.first_name,
l=rower.user.last_name)
job = myqueue(queuehigh,
handle_send_email_failed_cancel,
name, rower.user.email,rower.user.username,id)
name, rower.user.email, rower.user.username, id)
return False, themessages, errormessages
basicplans = PaidPlan.objects.filter(price=0,paymentprocessor='braintree')
basicplans = PaidPlan.objects.filter(price=0, paymentprocessor='braintree')
rower.paidplan = basicplans[0]
rower.teamplanexpires = timezone.now()
rower.planexpires = timezone.now()
@@ -453,35 +449,36 @@ def cancel_subscription(rower,id):
rower.save()
themessages.append("Your plan was reset to basic")
return True, themessages,errormessages
return True, themessages, errormessages
def find_subscriptions(rower):
try:
result = gateway.customer.find(rower.customer_id)
except: # pragma: no cover
raise ProcessorCustomerError("We could not find the customer in the database")
except: # pragma: no cover
raise ProcessorCustomerError(
"We could not find the customer in the database")
active_subscriptions = []
cards = result.credit_cards
for card in cards: # pragma: no cover
for card in cards: # pragma: no cover
for subscription in card.subscriptions:
if subscription.status == 'Active':
active_subscriptions.append(subscription)
try:
paypal_accounts = result.paypal_accounts
for account in paypal_accounts: # pragma: no cover
for account in paypal_accounts: # pragma: no cover
for subscription in account.subscriptions:
if subscription.status == 'Active':
active_subscriptions.append(subscription)
except AttributeError: # pragma: no cover
except AttributeError: # pragma: no cover
pass
result = []
for subscription in active_subscriptions: # pragma: no cover
for subscription in active_subscriptions: # pragma: no cover
plan = PaidPlan.objects.filter(paymentprocessor="braintree",
external_id=subscription.plan_id)[0]
@@ -493,19 +490,20 @@ def find_subscriptions(rower):
'id': subscription.id,
'plan': plan.name,
'never_expires': subscription.never_expires
}
}
result.append(thedict)
return result
def get_transactions(start_date,end_date): # pragma: no cover
def get_transactions(start_date, end_date): # pragma: no cover
results = gateway.transaction.search(
braintree.TransactionSearch.created_at.between(
start_date,
end_date,
)
)
)
amounts = []
countries = []
@@ -534,9 +532,9 @@ def get_transactions(start_date,end_date): # pragma: no cover
r = rs[0]
countries.append(r.country)
addresses.append('{street}, {city}, {postal_code}'.format(
street = r.street_address,
city = r.city,
postal_code = r.postal_code))
street=r.street_address,
city=r.city,
postal_code=r.postal_code))
ownids.append(r.id)
usernames.append(r.user.username)
@@ -547,11 +545,10 @@ def get_transactions(start_date,end_date): # pragma: no cover
usernames.append('unknown')
addresses.append('')
emails.append(transaction.customer_details.email)
names.append('{f} {l}'.format(
f = transaction.customer['first_name'],
l = transaction.customer['last_name']
f=transaction.customer['first_name'],
l=transaction.customer['last_name']
)
)
customerids.append(transaction.customer['id'])
@@ -564,27 +561,26 @@ def get_transactions(start_date,end_date): # pragma: no cover
transaction.credit_card_details.country_of_issuance)
statuses.append(transaction.status)
df = pd.DataFrame({
'name':names,
'email':emails,
'date':dates,
'amount':amounts,
'currency':currencies,
'country':countries,
'card_country':card_countries,
'status':statuses,
'username':usernames,
'user_id':ownids,
'customer_id':customerids,
'transaction_id':transactionids,
'subscription_id':subscriptionids,
'address':addresses
'name': names,
'email': emails,
'date': dates,
'amount': amounts,
'currency': currencies,
'country': countries,
'card_country': card_countries,
'status': statuses,
'username': usernames,
'user_id': ownids,
'customer_id': customerids,
'transaction_id': transactionids,
'subscription_id': subscriptionids,
'address': addresses
}
)
return df
def mocktest(rower): # pragma: no cover
def mocktest(rower): # pragma: no cover
return '5'