Cleanup, and better handling in the cancellation flow more work to come
This commit is contained in:
parent
2e9a428761
commit
c1ed938b04
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
python manage.py migrate
|
||||
python manage.py runserver_plus 0.0.0.0:8000
|
||||
while true; do python manage.py runserver_plus 0.0.0.0:8000; sleep 2; done
|
||||
|
|
|
@ -99,5 +99,50 @@ CAPTCHA = {
|
|||
WHITENOISE_AUTOREFRESH = True
|
||||
WHITENOISE_USE_FINDERS = True
|
||||
|
||||
LOGGING = {
|
||||
'version': 1,
|
||||
'disable_existing_loggers': False,
|
||||
'filters': {
|
||||
'require_debug_false': {
|
||||
'()': 'django.utils.log.RequireDebugFalse'
|
||||
}
|
||||
},
|
||||
'formatters': {
|
||||
'verbose': {
|
||||
'format': '%(levelname)s %(asctime)s %(module)s '
|
||||
'%(process)d %(thread)d %(message)s'
|
||||
},
|
||||
},
|
||||
'handlers': {
|
||||
'mail_admins': {
|
||||
'level': 'DEBUG',
|
||||
'filters': ['require_debug_false'],
|
||||
'class': 'django.utils.log.AdminEmailHandler'
|
||||
},
|
||||
'console': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.StreamHandler',
|
||||
'formatter': 'verbose',
|
||||
},
|
||||
'logfile': {
|
||||
'level':'DEBUG',
|
||||
'class':'logging.FileHandler',
|
||||
'filename': "%s/django.log" % ROOT_DIR,
|
||||
},
|
||||
},
|
||||
'loggers': {
|
||||
'django.request': {
|
||||
'handlers': ['mail_admins', 'logfile'],
|
||||
'level': 'ERROR',
|
||||
'propagate': True
|
||||
},
|
||||
'django.security.DisallowedHost': {
|
||||
'level': 'ERROR',
|
||||
'handlers': ['logfile', 'console', 'mail_admins'],
|
||||
'propagate': True
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PAYMENT_PROVIDERS['gocardless']['redirect_url'] = 'http://127.0.0.1:8180'
|
||||
TEMPLATE_DEBUG = False
|
||||
|
|
|
@ -67,5 +67,8 @@ TEMPLATES[0]['OPTIONS']['loaders'] = [
|
|||
]
|
||||
|
||||
DATABASES = {
|
||||
'default': {'ENGINE': 'django.db.backends.sqlite3'}
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(str(ROOT_DIR), 'cache/test_database.db'),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,8 @@ def download_remote_images():
|
|||
render_variations(result[0], image_variations, replace=True)
|
||||
article.save()
|
||||
except:
|
||||
logger.exception(result)
|
||||
logger.exception(result[0])
|
||||
logger.exception('Unable to download remote image for %s' % article.original_image)
|
||||
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
from django.contrib.auth.models import Group
|
||||
from django.utils.dateparse import parse_datetime
|
||||
from mhackspace.users.models import Membership
|
||||
from mhackspace.users.models import MEMBERSHIP_CANCELLED
|
||||
|
||||
|
||||
def create_or_update_membership(user, signup_details, complete=False):
|
||||
|
@ -34,3 +35,13 @@ def create_or_update_membership(user, signup_details, complete=False):
|
|||
group = Group.objects.get(name='members')
|
||||
user.groups.add(group)
|
||||
return True # Sign up finished
|
||||
|
||||
|
||||
def cancel_membership(user):
|
||||
member = Membership.objects.get(user=user)
|
||||
member.status = MEMBERSHIP_CANCELLED
|
||||
member.save()
|
||||
|
||||
group = Group.objects.get(name='members')
|
||||
user.groups.remove(group)
|
||||
return True
|
||||
|
|
|
@ -35,16 +35,6 @@ class gocardless_provider:
|
|||
access_token=payment_providers['gocardless']['credentials']['access_token'],
|
||||
environment=payment_providers['gocardless']['environment'])
|
||||
|
||||
# def subscribe_confirm(self, args):
|
||||
# response = gocardless_pro.client.confirm_resource(args)
|
||||
# subscription = gocardless_pro.client.subscription(args.get('resource_id'))
|
||||
# return {
|
||||
# 'amount': subscription.amount,
|
||||
# 'start_date': subscription.created_at,
|
||||
# 'reference': subscription.id,
|
||||
# 'success': response.success
|
||||
# }
|
||||
|
||||
def fetch_customers(self):
|
||||
"""Fetch list of customers payments"""
|
||||
for customer in self.client.customers.list().records:
|
||||
|
@ -80,11 +70,18 @@ class gocardless_provider:
|
|||
def get_token(self):
|
||||
return 'N/A'
|
||||
|
||||
def cancel_subscription(self, reference):
|
||||
def cancel_subscription(self, user, reference):
|
||||
try:
|
||||
subscription = gocardless_pro.client.subscription(reference)
|
||||
response = subscription.cancel()
|
||||
except gocardless_pro.exceptions.ClientError:
|
||||
subscription = self.client.subscriptions.get(reference)
|
||||
response = self.client.subscriptions.cancel(reference)
|
||||
except gocardless_pro.errors.InvalidApiUsageError as e:
|
||||
if e.code is 404:
|
||||
logger.info('Cancel subscription failed user not found %s %s' % (e.code, e))
|
||||
return {
|
||||
'success': False
|
||||
}
|
||||
except Exception as e:
|
||||
logger.info('Cancel subscription failed unknown reason code %s %s' % (e.code, e))
|
||||
return {
|
||||
'success': False
|
||||
}
|
||||
|
@ -92,7 +89,7 @@ class gocardless_provider:
|
|||
'amount': subscription.amount,
|
||||
'start_date': subscription.created_at,
|
||||
'reference': subscription.id,
|
||||
'success': response.get('success', False)
|
||||
'success': True if response.get('status_code') is '200' else False
|
||||
}
|
||||
|
||||
def create_subscription(self, user, session, amount,
|
||||
|
|
|
@ -35,14 +35,15 @@ class gocardlessMocks(TestCase):
|
|||
return self.provider
|
||||
|
||||
def mock_success_responses(self):
|
||||
|
||||
mock_list = MagicMock()
|
||||
mock_list_records = MagicMock(side_effect=[Mock(
|
||||
id='01',
|
||||
subscription_properties = Mock(
|
||||
id='02',
|
||||
status='active',
|
||||
amount=20.00,
|
||||
created_at='date'
|
||||
)])
|
||||
)
|
||||
|
||||
mock_list = MagicMock()
|
||||
mock_list_records = MagicMock(side_effect=[subscription_properties])
|
||||
mock_list.records.return_value = mock_list_records
|
||||
|
||||
self.provider.client.subscriptions.list = mock_list
|
||||
|
@ -54,3 +55,10 @@ class gocardlessMocks(TestCase):
|
|||
created_at=self.date_now,
|
||||
api_response=ApiResponseStatus(status_code='200'))
|
||||
)
|
||||
|
||||
self.provider.client.subscriptions.get = Mock(
|
||||
return_value=subscription_properties)
|
||||
|
||||
self.provider.client.subscriptions.cancel = PropertyMock(
|
||||
return_value={'status_code': '200'})
|
||||
|
||||
|
|
|
@ -14,39 +14,19 @@ class TestPaymentGatewaysGocardless(gocardlessMocks):
|
|||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
# self.date_now = django.utils.timezone.now()
|
||||
# self.user = self.make_user()
|
||||
# member = Membership()
|
||||
# member.user = self.user
|
||||
# member.payment = '20.00'
|
||||
# member.date = self.date_now
|
||||
# member.save()
|
||||
# self.auth_gocardless()
|
||||
|
||||
|
||||
@skip("Need to implement")
|
||||
@patch('mhackspace.subscriptions.payments.gocardless_pro.Client.subscription', autospec=True)
|
||||
def test_unsubscribe(self, mock_subscription):
|
||||
def test_unsubscribe(self):
|
||||
self.mock_success_responses()
|
||||
# self.auth_gocardless()
|
||||
mock_subscription.return_value = Mock(success='success')
|
||||
mock_subscription.cancel.return_value = Mock(
|
||||
id='01',
|
||||
status='active',
|
||||
amount=20.00,
|
||||
created_at='date'
|
||||
)
|
||||
result = self.provider.cancel_subscription(reference='M01')
|
||||
|
||||
result = self.provider.cancel_subscription(user=self.user, reference='M01')
|
||||
|
||||
self.assertEqual(result.get('amount'), 20.00)
|
||||
self.assertEqual(result.get('reference'), '02')
|
||||
self.assertEqual(result.get('success'), 'success')
|
||||
self.assertEqual(result.get('success'), True)
|
||||
|
||||
def test_confirm_subscription_callback(self):
|
||||
self.mock_success_responses()
|
||||
membership = self.create_membership_record()
|
||||
# self.auth_gocardless()
|
||||
# mock_confirm.return_value = Mock(success='success')
|
||||
|
||||
request_params = {
|
||||
'resource_uri': 'http://gocardless/resource/url/01',
|
||||
|
@ -73,6 +53,6 @@ class TestPaymentGatewaysGocardless(gocardlessMocks):
|
|||
for item in self.provider.fetch_subscriptions():
|
||||
self.assertEqual(item.get('status'), 'active')
|
||||
self.assertEqual(item.get('email'), 'test@test.com')
|
||||
self.assertEqual(item.get('reference'), '01')
|
||||
self.assertEqual(item.get('reference'), '02')
|
||||
self.assertEqual(item.get('amount'), 20.00)
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ from mhackspace.users.models import User, Membership
|
|||
from mhackspace.users.models import MEMBERSHIP_CANCELLED
|
||||
from mhackspace.users.forms import MembershipJoinForm
|
||||
from mhackspace.subscriptions.payments import select_provider
|
||||
from mhackspace.subscriptions.helper import create_or_update_membership
|
||||
from mhackspace.subscriptions.helper import create_or_update_membership, cancel_membership
|
||||
|
||||
|
||||
class MembershipCancelView(LoginRequiredMixin, RedirectView):
|
||||
|
@ -28,17 +28,12 @@ class MembershipCancelView(LoginRequiredMixin, RedirectView):
|
|||
member = Membership.objects.filter(user=self.request.user).first()
|
||||
|
||||
result = provider.cancel_subscription(
|
||||
user=self.request.user,
|
||||
reference=member.reference
|
||||
)
|
||||
if result.get('success') is True:
|
||||
# set membership to cancelled on success
|
||||
member.status = MEMBERSHIP_CANCELLED
|
||||
member.save()
|
||||
|
||||
|
||||
# remove user from group on success
|
||||
group = Group.objects.get(name='members')
|
||||
self.request.user.groups.remove(group)
|
||||
# if result.get('success') is True:
|
||||
cancel_membership(user=self.request.user)
|
||||
messages.add_message(
|
||||
self.request,
|
||||
messages.SUCCESS,
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{% if membership.get_status %}
|
||||
{% if membership.is_active %}
|
||||
<div id="membercard" class="registered">
|
||||
<div class="date">Joined {{membership.date}}</div>
|
||||
<div class="container">
|
||||
|
|
|
@ -45,27 +45,28 @@ class Blurb(models.Model):
|
|||
skills = models.CharField(max_length=255)
|
||||
description = models.TextField()
|
||||
|
||||
MEMBERSHIP_CANCELLED = 0
|
||||
MEMBERSHIP_ACTIVE = 4
|
||||
MEMBERSHIP_CANCELLED = 4
|
||||
|
||||
MEMBERSHIP_STATUS_CHOICES = (
|
||||
(0, 'Guest user'),
|
||||
(1, 'Active membership'),
|
||||
(MEMBERSHIP_ACTIVE, 'Active membership'),
|
||||
(3, 'Membership Expired'),
|
||||
(4, 'Membership Cancelled')
|
||||
(MEMBERSHIP_CANCELLED, 'Membership Cancelled')
|
||||
)
|
||||
|
||||
MEMBERSHIP_STRING = {
|
||||
0: 'Guest user',
|
||||
1: 'Active membership',
|
||||
MEMBERSHIP_ACTIVE: 'Active membership',
|
||||
3: 'Membership Expired',
|
||||
4: 'Membership Cancelled'
|
||||
MEMBERSHIP_CANCELLED: 'Membership Cancelled'
|
||||
}
|
||||
|
||||
MEMBERSHIP_STATUS = {
|
||||
'signup': 0, # This means the user has not completed signup
|
||||
'active': 1,
|
||||
'active': MEMBERSHIP_ACTIVE,
|
||||
'expired': 3,
|
||||
'cancelled': 4
|
||||
'cancelled': MEMBERSHIP_CANCELLED
|
||||
}
|
||||
|
||||
|
||||
|
@ -87,6 +88,11 @@ class Membership(models.Model):
|
|||
def get_status(self):
|
||||
return MEMBERSHIP_STRING[self.status]
|
||||
|
||||
def is_active(self):
|
||||
if self.status is MEMBERSHIP_ACTIVE:
|
||||
return True
|
||||
return False
|
||||
|
||||
def lookup_status(name):
|
||||
if not name:
|
||||
return 0
|
||||
|
|
Loading…
Reference in New Issue