add Bango Terms of Agreement to payments enrollment flow (bug 831139)
This commit is contained in:
Родитель
2cfed8300e
Коммит
c2e9844ecc
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
if ($overlay.length) {
|
||||
$overlay.removeClass('show');
|
||||
z.body.removeClass('overlayed');
|
||||
$(window).trigger('overlay_dismissed');
|
||||
$overlay.trigger('overlay_dismissed');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<script type="text/template" id="show-agreement-template"
|
||||
data-url="{{ url('mkt.developers.bango.agreement', '0')|replace('0', '{0}') }}">
|
||||
<section class="show-agreement">
|
||||
<header>
|
||||
<h2>{{ _('Bango Terms of Agreement') }}</h2>
|
||||
</header>
|
||||
<form action="{{ url('mkt.developers.bango.add_payment_account') }}" method="post">
|
||||
<p class="agreement-valid">
|
||||
{# L10n: {date} is a YYYY-MM-DD timestamp. #}
|
||||
{% trans %}
|
||||
This agreement will be valid on <time datetime="{date}">{date}</time>.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
<div class="agreement-text island"></div>
|
||||
<p class="listing-footer">
|
||||
<button type="submit">{{ _('Agree to the Terms') }}</button>
|
||||
{# L10n: This 'or' goes between two choices in a dialog. #}
|
||||
{{ _('or') }}
|
||||
<a href="#" class="close">{{ _('Cancel') }}</a>
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
</script>
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
<table>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>{{ _('Account Name') }}</th>
|
||||
<th>{{ _('Modify') }}</th>
|
||||
<th>{{ _('Delete') }}</th>
|
||||
|
@ -29,6 +30,7 @@
|
|||
<tr data-account="{id}"
|
||||
data-delete-url="{delete-url}"
|
||||
data-account-url="{account-url}">
|
||||
<td><div class="terms-accepted {agreement}"></div></td>
|
||||
<td>{name}</td>
|
||||
<td><a href="#" class="modify-account">{{ _('Modify') }}</a></td>
|
||||
<td><a href="#" class="delete-account">{{ _('Delete') }}</a></td>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -30,6 +30,9 @@ def bango_patterns(prefix):
|
|||
url('^accounts/(?P<id>\d+)$',
|
||||
views_payments.payments_account,
|
||||
name='mkt.developers.%s.payment_account' % prefix),
|
||||
|
||||
url('^accounts/(?P<id>\d+)/agreement/$', views_payments.agreement,
|
||||
name='mkt.developers.%s.agreement' % prefix)
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче