Skip to content
This repository was archived by the owner on Mar 15, 2018. It is now read-only.

Commit a02cb78

Browse files
committed
prettify refund page (bug 704961, bug 705871)
1 parent 68d6c10 commit a02cb78

File tree

9 files changed

+134
-110
lines changed

9 files changed

+134
-110
lines changed
Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,49 @@
1-
{% extends "devhub/base.html" %}
1+
{% extends 'devhub/base_impala.html' %}
22

3-
{% block title %}{{ dev_page_title(_('Issue Refund')) }}{% endblock %}
3+
{% set title = _('Issue Refund') %}
4+
{% block title %}{{ dev_page_title(title) }}{% endblock %}
5+
6+
{# TODO(apps): Finalize copy. #}
47

58
{% block content %}
69
<header>
7-
<h1>{{ _('Issue Refund') }}</h1>
10+
{{ dev_breadcrumbs(addon) }}
11+
<h1>{{ title }}</h1>
812
</header>
9-
<form method="post" id="issue-refund" class="item" action="">
10-
{% if transaction_id %}
11-
{{ csrf() }}
12-
<p>
13-
{% trans %}
14-
A refund was requested by {{ user }} for {{ addon_name }}.
15-
{% endtrans %}
16-
</p><p>
17-
{% trans %}
18-
Price: {{ price }}
19-
{% endtrans %}
20-
</p><p>
21-
{% trans %}
22-
Purchase date: {{ purchase_date }}
23-
{% endtrans %}
24-
</p><p>
25-
<button type="submit" name="issue">
26-
{{ _('Issue Refund') }}
27-
</button>
28-
<button type="submit" name="decline">
29-
{{ _('Decline Refund') }}
30-
</button>
31-
<input type="hidden" name="transaction_id" value="{{ transaction_id }}">
32-
{% else %}
33-
<p>{{ _('No refundable transaction found.') }}</p>
34-
{% endif %}
13+
<form method="post" action="" id="issue-refund" class="primary island full c">
14+
{% if transaction_id %}
15+
{{ csrf() }}
16+
<p>
17+
{% with user=contribution.user.display_name,
18+
user_url=contribution.user.get_url_path(),
19+
addon_url=addon.get_url_path(),
20+
addon_name=addon.name %}
21+
A refund was requested by
22+
<a href="{{ user_url }}" target="_blank">{{ user }}</a> for
23+
<a href="{{ addon_url }}" target="_blank">{{ addon_name }}</a>.
24+
{% endwith %}
25+
</p>
26+
<p>
27+
{% with price=contribution.get_amount_locale() %}
28+
<b>Price:</b> {{ price }}
29+
{% endwith %}
30+
</p>
31+
<p>
32+
{% with purchase_date=contribution.created|datetime %}
33+
<b>Purchase date:</b> {{ purchase_date }}
34+
{% endwith %}
35+
</p>
36+
<p>
37+
<button type="submit" class="good" name="issue">
38+
{{ _('Issue Refund') }}
39+
</button>
40+
<button type="submit" class="bad" name="decline">
41+
{{ _('Decline Refund') }}
42+
</button>
43+
<input type="hidden" name="transaction_id" value="{{ transaction_id }}">
44+
</p>
45+
{% else %}
46+
<p>{{ loc('No refundable transaction found.') }}</p>
47+
{% endif %}
3548
</form>
36-
{% endblock content %}
49+
{% endblock %}

apps/devhub/tests/test_views.py

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,60 +1260,71 @@ def setUp(self):
12601260
self.paykey = u'fake-paykey'
12611261
self.client.login(username='del@icio.us', password='password')
12621262
self.user = UserProfile.objects.get(username='clouserw')
1263-
self.url = reverse('devhub.issue_refund', args=[self.addon.slug])
1263+
self.url = self.addon.get_dev_url('issue_refund')
12641264

1265-
def makePurchase(self, uuid='123456', type=amo.CONTRIB_PURCHASE):
1265+
def make_purchase(self, uuid='123456', type=amo.CONTRIB_PURCHASE):
12661266
return Contribution.objects.create(uuid=uuid, addon=self.addon,
12671267
transaction_id=self.transaction_id,
12681268
user=self.user, paykey=self.paykey,
12691269
amount=Decimal('10'), type=type)
12701270

12711271
def test_request_issue(self):
1272-
c = self.makePurchase()
1273-
r = self.client.get(self.url,
1274-
data={'transaction_id': c.transaction_id})
1272+
c = self.make_purchase()
1273+
r = self.client.get(self.url, {'transaction_id': c.transaction_id})
12751274
doc = pq(r.content)
1276-
eq_(doc('#issue-refund button')[0].text.strip(), 'Issue Refund')
1277-
eq_(doc('#issue-refund button')[1].text.strip(), 'Decline Refund')
1275+
eq_(doc('#issue-refund button').length, 2)
12781276
eq_(doc('#issue-refund input[name=transaction_id]').val(),
12791277
self.transaction_id)
12801278

12811279
def test_nonexistent_txn(self):
1282-
r = self.client.get(self.url, data={'transaction_id': 'none'})
1280+
r = self.client.get(self.url, {'transaction_id': 'none'})
12831281
eq_(r.status_code, 404)
12841282

12851283
def test_nonexistent_txn_no_really(self):
12861284
r = self.client.get(self.url)
12871285
eq_(r.status_code, 404)
12881286

1289-
@mock.patch('paypal.refund')
1290-
def test_issue(self, refund):
1291-
c = self.makePurchase()
1292-
r = self.client.post(self.url,
1293-
data={'transaction_id': c.transaction_id,
1294-
'issue': '1'})
1295-
eq_(r.status_code, 302)
1287+
def _test_issue(self, refund, destination):
1288+
c = self.make_purchase()
1289+
r = self.client.post(self.url, {'transaction_id': c.transaction_id,
1290+
'issue': '1'})
1291+
self.assertRedirects(r, reverse(destination), 302)
12961292
refund.assert_called_with(self.transaction_id, self.paykey)
12971293
eq_(len(mail.outbox), 1)
12981294
assert 'approved' in mail.outbox[0].subject
12991295

13001296
@mock.patch('paypal.refund')
1301-
def test_decline(self, refund):
1302-
c = self.makePurchase()
1303-
r = self.client.post(self.url,
1304-
data={'transaction_id': c.transaction_id,
1305-
'decline': ''})
1306-
eq_(r.status_code, 302)
1297+
def test_addons_issue(self, refund):
1298+
self._test_issue(refund, 'devhub.addons')
1299+
1300+
@mock.patch('paypal.refund')
1301+
def test_apps_issue(self, refund):
1302+
self.addon.update(type=amo.ADDON_WEBAPP)
1303+
self._test_issue(refund, 'devhub.apps')
1304+
1305+
def _test_decline(self, refund, destination):
1306+
c = self.make_purchase()
1307+
r = self.client.post(self.url, {'transaction_id': c.transaction_id,
1308+
'decline': ''})
1309+
self.assertRedirects(r, reverse(destination), 302)
13071310
assert not refund.called
13081311
eq_(len(mail.outbox), 1)
13091312
assert 'declined' in mail.outbox[0].subject
13101313

1314+
@mock.patch('paypal.refund')
1315+
def test_addons_decline(self, refund):
1316+
self._test_decline(refund, 'devhub.addons')
1317+
1318+
@mock.patch('paypal.refund')
1319+
def test_apps_decline(self, refund):
1320+
self.addon.update(type=amo.ADDON_WEBAPP)
1321+
self._test_decline(refund, 'devhub.apps')
1322+
13111323
@mock.patch('paypal.refund')
13121324
def test_non_refundable_txn(self, refund):
1313-
c = self.makePurchase('56789', amo.CONTRIB_VOLUNTARY)
1314-
r = self.client.post(self.url,
1315-
data={'transaction_id': c.transaction_id,
1316-
'issue': ''})
1325+
c = self.make_purchase('56789', amo.CONTRIB_VOLUNTARY)
1326+
r = self.client.post(self.url, {'transaction_id': c.transaction_id,
1327+
'issue': ''})
13171328
eq_(r.status_code, 404)
13181329
assert not refund.called
13191330

apps/devhub/urls.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ def marketplace_patterns(prefix):
6161
url('^profile$', views.profile, name='devhub.apps.profile'),
6262
url('^profile/remove$', views.remove_profile,
6363
name='devhub.apps.profile.remove'),
64+
url('^issue_refund$', views.issue_refund, name='devhub.apps.issue_refund'),
6465
)
6566

6667
# These will all start with /addon/<addon_id>/
@@ -81,7 +82,8 @@ def marketplace_patterns(prefix):
8182
url('^payments/permission/refund$', views.acquire_refund_permission,
8283
name='devhub.addons.acquire_refund_permission'),
8384
url('^payments/', include(marketplace_patterns('addons'))),
84-
url('^issue_refund$', views.issue_refund, name='devhub.issue_refund'),
85+
url('^issue_refund$', views.issue_refund,
86+
name='devhub.addons.issue_refund'),
8587
url('^profile$', views.profile, name='devhub.addons.profile'),
8688
url('^profile/remove$', views.remove_profile,
8789
name='devhub.addons.profile.remove'),

apps/devhub/views.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -492,23 +492,19 @@ def issue_refund(request, addon_id, addon, webapp=False):
492492
if 'issue' in request.POST:
493493
paypal.refund(txn_id, contribution.paykey)
494494
contribution.mail_approved()
495-
paypal_log.error('Refund issued for transaction %r' % (txn_id,))
495+
paypal_log.error('Refund issued for transaction %r' % txn_id)
496496
messages.success(request, 'Refund issued.')
497-
return redirect('devhub.addons')
498497
else:
499498
contribution.mail_declined()
500-
paypal_log.error('Refund declined for transaction %r' % (txn_id,))
499+
paypal_log.error('Refund declined for transaction %r' % txn_id)
501500
messages.success(request, 'Refund declined.')
502-
return redirect('devhub.addons')
501+
return redirect('devhub.%s' % ('apps' if webapp else 'addons'))
503502
else:
504503
return jingo.render(request, 'devhub/payments/issue-refund.html',
505-
{'refund_issued': False,
506-
'user': contribution.user.display_name,
507-
'addon_name': addon.name,
504+
{'contribution': contribution,
505+
'addon': addon,
508506
'webapp': webapp,
509-
'price': contribution.amount,
510-
'transaction_id': txn_id,
511-
'purchase_date': contribution.created})
507+
'transaction_id': txn_id})
512508

513509

514510
@dev_required
@@ -1028,7 +1024,6 @@ def addons_section(request, addon_id, addon, section, editable=False,
10281024
else:
10291025
form = False
10301026

1031-
#import pdb; pdb.set_trace()
10321027
data = {'addon': addon,
10331028
'webapp': webapp,
10341029
'form': form,

apps/users/views.py

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,6 @@ def profile(request, user_id):
467467
.filter(following__user=user)
468468
.order_by('-following__created'))[:10]
469469

470-
471470
edit_any_user = acl.action_allowed(request, 'Admin', 'EditAnyUser')
472471
own_profile = (request.user.is_authenticated() and
473472
request.amo_user.id == user.id)
@@ -760,11 +759,8 @@ def support_mozilla(request, contribution, wizard):
760759
def refund_request(request, contribution, wizard):
761760
addon = contribution.addon
762761
form = forms.RemoveForm(request.POST or None)
763-
if request.method == 'POST':
764-
if form.is_valid():
765-
return redirect(reverse('users.support',
766-
args=[contribution.pk, 'reason']))
767-
762+
if request.method == 'POST' and form.is_valid():
763+
return redirect('users.support', contribution.pk, 'reason')
768764
return wizard.render(request, wizard.tpl('request.html'),
769765
{'addon': addon, 'webapp': addon.is_webapp(),
770766
'form': form, 'contribution': contribution})
@@ -773,35 +769,30 @@ def refund_request(request, contribution, wizard):
773769
def refund_reason(request, contribution, wizard):
774770
addon = contribution.addon
775771
if not 'request' in wizard.get_progress():
776-
return redirect(reverse('users.support',
777-
args=[contribution.pk, 'request']))
772+
return redirect('users.support', contribution.pk, 'request')
778773

779774
form = forms.ContactForm(request.POST or None)
780-
if request.method == 'POST':
781-
if form.is_valid():
782-
# if under 30 minutes, refund
783-
# TODO(ashort): add in the logic for under 30 minutes
784-
refund_url = absolutify(urlparams(
785-
reverse('devhub.issue_refund', args=[addon.slug]),
786-
transaction_id=contribution.transaction_id))
787-
788-
template = jingo.render_to_string(request,
789-
wizard.tpl('emails/refund-request.txt'),
790-
context={'addon': addon, 'form': form,
791-
'user': request.amo_user,
792-
'contribution': contribution,
793-
'refund_url': refund_url})
794-
log.info('Refund request sent by user: %s for addon: %s' %
795-
(request.amo_user.pk, addon.pk))
796-
# L10n: %s is the addon name.
797-
send_mail(_(u'New Refund Request for %s' % addon.name),
798-
template, request.amo_user.email,
799-
[smart_str(addon.support_email)])
800-
return redirect(reverse('users.support',
801-
args=[contribution.pk, 'refund-sent']))
775+
if request.method == 'POST' and form.is_valid():
776+
# TODO(ashort): Reject refund if purchase was more than 30 minutes ago.
777+
url = absolutify(urlparams(addon.get_dev_url('issue_refund'),
778+
transaction_id=contribution.transaction_id))
779+
template = jingo.render_to_string(request,
780+
wizard.tpl('emails/refund-request.txt'),
781+
context={'addon': addon,
782+
'form': form,
783+
'user': request.amo_user,
784+
'contribution': contribution,
785+
'refund_url': url})
786+
log.info('Refund request sent by user: %s for addon: %s' %
787+
(request.amo_user.pk, addon.pk))
788+
# L10n: %s is the addon name.
789+
send_mail(_(u'New Refund Request for %s' % addon.name),
790+
template, request.amo_user.email,
791+
[smart_str(addon.support_email)])
792+
return redirect(reverse('users.support',
793+
args=[contribution.pk, 'refund-sent']))
802794

803-
return wizard.render(request, wizard.tpl('refund.html'),
804-
{'contribut': addon, 'form': form})
795+
return wizard.render(request, wizard.tpl('refund.html'), {'form': form})
805796

806797

807798
class SupportWizard(Wizard):
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import 'lib';
1+
@import '../impala/lib';
22

33
.devhub-form .tip,
44
.addon-submission-process .tip,
@@ -92,3 +92,7 @@ a.remove:hover {
9292
.html-rtl .undo {
9393
float: left;
9494
}
95+
96+
#issue-refund {
97+
font-size: 14px;
98+
}

media/css/impala/buttons.less

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@
1515
.box-shadow(0 1px rgba(0, 0, 0, 0.1), 0 -2px rgba(0, 0, 0, 0.1) inset);
1616
border: 0;
1717
}
18+
19+
button.good, .button.add { // Green
20+
background: #489615;
21+
.gradient-two-color(#84C63C, #489615);
22+
}
23+
24+
button.bad, .button.developer, .button.scary { // Red
25+
background: #bc2b1a;
26+
.gradient-two-color(#f84b4e, #bc2b1a);
27+
}
28+
1829
.button {
1930
display: inline-block;
2031
&.prominent {
@@ -23,9 +34,6 @@
2334
.box-shadow(0 3px rgba(0, 0, 0, 0.1), 0 -4px rgba(0, 0, 0, 0.1) inset);
2435
}
2536
&.add { // Green
26-
background: #489615;
27-
.gradient-two-color(#84C63C, #489615);
28-
color: #fff;
2937
span {
3038
padding-left: 16px;
3139
background: url(../../img/impala/button-icons.png) no-repeat 0 3px;
@@ -93,9 +101,6 @@
93101
}
94102
}
95103
&.developer, &.scary { // Red
96-
background: #bc2b1a;
97-
.gradient-two-color(#f84b4e, #bc2b1a);
98-
color: #fff;
99104
span {
100105
margin-left: -4px;
101106
padding-left: 24px;
@@ -106,7 +111,6 @@
106111
&.watch:not(.watching) { // Orange
107112
background: #ea0;
108113
.gradient-two-color(#ea0, darken(#ea0, 10%));
109-
color: #fff;
110114
}
111115
&.platform {
112116
display: none;

media/css/impala/forms.less

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ p.req {
3232
margin: 0 0 1em;
3333
}
3434

35+
/* CSRF token */
36+
form div[style]:first-child + p {
37+
margin-top: 0;
38+
}
39+
3540
.optional {
3641
color: @note-gray;
3742
font-size: 11px;
@@ -380,4 +385,3 @@ button.loading-submit:after {
380385
top: 0;
381386
width: 16px;
382387
}
383-

0 commit comments

Comments
 (0)