diff --git a/media/css/devreg/payments.less b/media/css/devreg/payments.less index bbcc6d2288..2c40da7b03 100644 --- a/media/css/devreg/payments.less +++ b/media/css/devreg/payments.less @@ -374,3 +374,45 @@ background: orangered; color: white; } + +.overlay > .show-agreement { + max-width: 650px; + min-width: 650px; +} + +.agreement-valid, +.agreement-text { + margin-bottom: 15px; +} + +.agreement-valid time { + font-weight: bold; +} + +.agreement-text { + max-height: 400px; + overflow: auto; +} + +.show-agreement { + p { + padding-top: 10px; + } + .listing-footer { + padding: 10px 10px 6px; + } +} + +.terms-accepted { + color: orangered; + font-family: monospace; + &:before { + content: "\2717"; + } + &.accepted { + color: green; + &:before { + content: "\2713"; + } + } +} diff --git a/media/js/devreg/payments-manage.js b/media/js/devreg/payments-manage.js index d0601fd3ea..51e33e8450 100644 --- a/media/js/devreg/payments-manage.js +++ b/media/js/devreg/payments-manage.js @@ -8,7 +8,61 @@ define('payments-manage', ['payments'], function(payments) { function newBangoPaymentAccount(e) { var $overlay = payments.getOverlay('add-bango-account'); - payments.setupPaymentAccountOverlay( $overlay, function() { + payments.setupPaymentAccountOverlay($overlay, showAgreement); + } + + function agreementSuccess(pk) { + $('.account-list [data-account=' + pk + '] .terms-accepted').removeClass('rejected').addClass('accepted'); + } + + function agreementError(pk) { + $('.account-list [data-account=' + pk + '] .terms-accepted').removeClass('accepted').addClass('rejected'); + } + + var agreementUrl = $('#show-agreement-template').data('url'); + + function setupAgreementOverlay(data, $overlay, onsubmit) { + var url = format(agreementUrl, data.pk); + + // TODO: Do something with waiting overlays. This is slow. + $.getJSON(url, function(data) { + // Plop in date of agreement. + var msg = $('.agreement-valid'); + msg.html(format(msg.html(), {date: data.valid})); + + // Plop in text of agreement. + $('.agreement-text').text(data.text); + }); + + $overlay.on('submit', 'form', _pd(function(e) { + var $form = $(this); + + // Assume the POST below was a success, and close the modal. + $overlay.detach(); + z.body.removeClass('overlayed'); + onsubmit.apply($form, data); + + // If the POST failed, we show an error message. + $.post(url, $form.serialize(), function(response) { + if (response.accepted) { + agreementSuccess(data.pk); + } else { + agreementError(); + } + }, 'json').error(function() { + agreementError(data.pk); + }); + })).on('overlay_dismissed', function() { + // If it wasn't already marked as successful, then the user cancelled. + if (!$('.account-list [data-account=' + data.pk + '] .terms-accepted.success')) { + agreementError(data.pk); + } + }); + } + + function showAgreement(data) { + var $overlay = payments.getOverlay('show-agreement'); + setupAgreementOverlay(data, $overlay, function() { refreshAccountForm(); $('#no-payment-providers').addClass('js-hidden'); }); @@ -24,13 +78,16 @@ define('payments-manage', ['payments'], function(payments) { // Start the loading screen while we get the account data. return function(e) { var $waiting_overlay = payments.getOverlay('bango-waiting'); - $.getJSON( account_url, function(data) { + $.getJSON(account_url, function(data) { $waiting_overlay.remove(); z.body.removeClass('overlayed'); paymentAccountSetup(); for (var field in data) { $('#id_' + field).val(data[field]); } + }).fail(function() { + $waiting_overlay.find('h2').text(gettext('Error')); + $waiting_overlay.find('p').text(gettext('There was a problem contacting the payment server.')); }); }; } @@ -53,7 +110,6 @@ define('payments-manage', ['payments'], function(payments) { // Post to the delete URL, then refresh the account form. $.post($tr.data('delete-url')).then(refreshAccountForm); - })).on('click', 'a.modify-account', _pd(function() { // Get the account URL from the table row and pass it to // the function to handle the Edit overlay. diff --git a/media/js/devreg/payments.js b/media/js/devreg/payments.js index f97790b1dc..0c9de8f9c5 100644 --- a/media/js/devreg/payments.js +++ b/media/js/devreg/payments.js @@ -9,6 +9,7 @@ define('payments', [], function() { .addClass('show') .on('click', '.close', _pd(function() { // TODO: Generalize this with the event listeners in overlay.js. + overlay.trigger('overlay_dismissed'); z.body.removeClass('overlayed'); overlay.remove(); })); @@ -51,11 +52,8 @@ define('payments', [], function() { $old_overlay.find('#bango-account-errors') .html(error_data.responseText); } - ).fail(function() { - $waiting_overlay.find('h2').text(gettext('Error')); - $waiting_overlay.find('p').text(gettext('There was a problem contacting the payment server.')); }); - }; + })); } function init() { diff --git a/media/js/mkt/overlay.js b/media/js/mkt/overlay.js index f5a1da9b96..aa36ce7da4 100644 --- a/media/js/mkt/overlay.js +++ b/media/js/mkt/overlay.js @@ -9,7 +9,7 @@ if ($overlay.length) { $overlay.removeClass('show'); z.body.removeClass('overlayed'); - $(window).trigger('overlay_dismissed'); + $overlay.trigger('overlay_dismissed'); } } diff --git a/mkt/developers/templates/developers/payments/includes/accept_terms.html b/mkt/developers/templates/developers/payments/includes/accept_terms.html new file mode 100644 index 0000000000..6e95e315d8 --- /dev/null +++ b/mkt/developers/templates/developers/payments/includes/accept_terms.html @@ -0,0 +1,23 @@ + diff --git a/mkt/developers/templates/developers/payments/includes/account_list.html b/mkt/developers/templates/developers/payments/includes/account_list.html index 47e84dd107..5c6894d479 100644 --- a/mkt/developers/templates/developers/payments/includes/account_list.html +++ b/mkt/developers/templates/developers/payments/includes/account_list.html @@ -8,6 +8,7 @@ + @@ -29,6 +30,7 @@ + diff --git a/mkt/developers/templates/developers/payments/premium.html b/mkt/developers/templates/developers/payments/premium.html index 18f6759320..a8e15a611e 100644 --- a/mkt/developers/templates/developers/payments/premium.html +++ b/mkt/developers/templates/developers/payments/premium.html @@ -229,4 +229,5 @@ {% include 'developers/payments/includes/account_list.html' %} {% include 'developers/payments/includes/add_payment_account_bango.html' %} {% include 'developers/payments/includes/edit_payment_account_bango.html' %} + {% include 'developers/payments/includes/accept_terms.html' %} {% endblock %} diff --git a/mkt/developers/tests/test_views_payments.py b/mkt/developers/tests/test_views_payments.py index b93f94a8c9..2fc0e363c9 100644 --- a/mkt/developers/tests/test_views_payments.py +++ b/mkt/developers/tests/test_views_payments.py @@ -427,6 +427,37 @@ class TestPaymentAccount(PaymentsBase): eq_(output['vendorName'], 'testval') +class TestPaymentAgreement(PaymentsBase): + + def setUp(self): + super(TestPaymentAgreement, self).setUp() + self.url = reverse('mkt.developers.bango.agreement', + args=[self.account.pk]) + + def test_anon(self): + self.client.logout() + self.assertLoginRequired(self.client.get(self.url)) + + @mock.patch('mkt.developers.views_payments.client.api') + def test_get(self, api): + api.bango.sbi.agreement.get_object.return_value = { + 'text': 'blah', 'valid': '2010-08-31T00:00:00'} + res = self.client.get(self.url) + eq_(res.status_code, 200) + data = json.loads(res.content) + eq_(data['text'], 'blah') + + @mock.patch('mkt.developers.views_payments.client.api') + def test_set(self, api): + api.bango.sbi.agreement.post.return_value = { + 'expires': '2014-08-31T00:00:00', + 'valid': '2014-08-31T00:00:00'} + res = self.client.post(self.url) + eq_(res.status_code, 200) + data = json.loads(res.content) + eq_(data['valid'], '2014-08-31T00:00:00') + + class TestPaymentAccountsForm(PaymentsBase): def setUp(self): diff --git a/mkt/developers/urls.py b/mkt/developers/urls.py index 505b79736a..cc8c5789a8 100644 --- a/mkt/developers/urls.py +++ b/mkt/developers/urls.py @@ -30,6 +30,9 @@ def bango_patterns(prefix): url('^accounts/(?P\d+)$', views_payments.payments_account, name='mkt.developers.%s.payment_account' % prefix), + + url('^accounts/(?P\d+)/agreement/$', views_payments.agreement, + name='mkt.developers.%s.agreement' % prefix) ) diff --git a/mkt/developers/views_payments.py b/mkt/developers/views_payments.py index e5b07afa9d..aed4644baf 100644 --- a/mkt/developers/views_payments.py +++ b/mkt/developers/views_payments.py @@ -139,7 +139,7 @@ def payment_accounts(request): user=request.amo_user, inactive=False) def account(acc): - return { + data = { 'id': acc.pk, 'name': jinja2.escape(unicode(acc)), 'account-url': @@ -148,6 +148,13 @@ def payment_accounts(request): reverse('mkt.developers.bango.delete_payment_account', args=[acc.pk]) } + data['agreement'] = 'rejected' + try: + if _agreement(request, acc.pk)['accepted']: + data['agreement'] = 'accepted' + except KeyError: + pass + return data return map(account, accounts) @@ -164,20 +171,21 @@ def payment_accounts_form(request): @write @post_required @login_required +@json_view def payments_accounts_add(request): form = forms_payments.BangoPaymentAccountForm(request.POST) if not form.is_valid(): return http.HttpResponse(json.dumps(form.errors), status=400) try: - models.PaymentAccount.create_bango( + obj = models.PaymentAccount.create_bango( request.amo_user, form.cleaned_data) except client.Error as e: log.error('Error creating Bango payment account; %s' % e) raise # We want to see these exceptions! return http.HttpResponse( _(u'Could not connect to payment server.'), status=400) - return redirect('mkt.developers.bango.payment_accounts_form') + return {'pk': obj.pk} @write @@ -263,3 +271,23 @@ def get_seller_product(account): return (client.api.generic .product(account.uri_to_pk(bango_product['seller_product'])) .get_object_or_404()) + + +def _agreement(request, id): + account = get_object_or_404(models.PaymentAccount, pk=id, + user=request.user) + # It's a shame we have to do another get to find this out. + package = client.api.bango.package(account.uri).get_object_or_404() + if request.method == 'POST': + # Set the agreement. + return (client.api.bango.sbi.post( + data={'seller_bango': package['resource_uri']})) + return (client.api.bango.sbi.agreement + .get_object(data={'seller_bango': package['resource_uri']})) + + +# TODO: move these into a tastypie API. +@login_required +@json_view +def agreement(request, id): + return _agreement(request, id)
{{ _('Account Name') }} {{ _('Modify') }} {{ _('Delete') }}
{name}