add Bango Terms of Agreement to payments enrollment flow (bug 831139)

This commit is contained in:
Andy McKay 2013-01-24 17:43:35 -08:00 коммит произвёл Chris Van
Родитель 2cfed8300e
Коммит c2e9844ecc
10 изменённых файлов: 195 добавлений и 11 удалений

Просмотреть файл

@ -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)