alter purchases to cope with multiple purchases, add in free and remove date paid sorting for now (bug 696509)
This commit is contained in:
Родитель
ff656a8be9
Коммит
8f2403e5a5
|
@ -15,8 +15,7 @@
|
||||||
{{ impala_addon_listing_header(url_base, filter.opts, sorting, filter.extras) }}
|
{{ impala_addon_listing_header(url_base, filter.opts, sorting, filter.extras) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="items">
|
<div class="items">
|
||||||
{% for contribution in purchases.object_list %}
|
{% for addon in addons.object_list %}
|
||||||
{% with addon=contribution.addon %}
|
|
||||||
<div class="item addon ignore-compatibility">
|
<div class="item addon ignore-compatibility">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h3>
|
<h3>
|
||||||
|
@ -25,13 +24,17 @@
|
||||||
</h3>
|
</h3>
|
||||||
<p class="desc">{{ addon.description|truncate(250)|nl2br }}</p>
|
<p class="desc">{{ addon.description|truncate(250)|nl2br }}</p>
|
||||||
<div class="vitals c">
|
<div class="vitals c">
|
||||||
{% trans date=addon.created, amt=contribution.get_amount_locale(), url=url('users.support', contribution.pk) %}
|
{% for contribution in contributions.get(addon.pk, []) %}
|
||||||
<div>Purchased {{ date }} for {{ amt }} - <a href="{{ url }}">Request Support</a></div>
|
<div class="purchase-byline">
|
||||||
|
{% trans date=addon.created, amt=contribution.get_amount_locale() %}
|
||||||
|
Purchased {{ date }} for {{ amt }}
|
||||||
{% endtrans %}
|
{% endtrans %}
|
||||||
|
· <a href="{{ url('users.support', contribution.pk) }}">{{ _('Request Support') }}</a>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endwith %}
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>You have no purchases.</p>
|
<p>You have no purchases.</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -31,6 +31,7 @@ from stats.models import Contribution
|
||||||
from users.models import BlacklistedPassword, UserProfile, UserNotification
|
from users.models import BlacklistedPassword, UserProfile, UserNotification
|
||||||
import users.notifications as email
|
import users.notifications as email
|
||||||
from users.utils import EmailResetCode, UnsubscribeCode
|
from users.utils import EmailResetCode, UnsubscribeCode
|
||||||
|
from webapps.models import Installed
|
||||||
|
|
||||||
|
|
||||||
class UserViewBase(amo.tests.TestCase):
|
class UserViewBase(amo.tests.TestCase):
|
||||||
|
@ -879,6 +880,7 @@ class TestPurchases(amo.tests.TestCase):
|
||||||
self.client.login(username='regular@mozilla.com', password='password')
|
self.client.login(username='regular@mozilla.com', password='password')
|
||||||
self.user = User.objects.get(email='regular@mozilla.com')
|
self.user = User.objects.get(email='regular@mozilla.com')
|
||||||
|
|
||||||
|
self.addon, self.con = None, None
|
||||||
for x in range(1, 5):
|
for x in range(1, 5):
|
||||||
addon = Addon.objects.create(type=amo.ADDON_EXTENSION,
|
addon = Addon.objects.create(type=amo.ADDON_EXTENSION,
|
||||||
name='t%s' % x)
|
name='t%s' % x)
|
||||||
|
@ -887,9 +889,8 @@ class TestPurchases(amo.tests.TestCase):
|
||||||
type=amo.CONTRIB_PURCHASE)
|
type=amo.CONTRIB_PURCHASE)
|
||||||
con.created = datetime.now() - timedelta(days=10 - x)
|
con.created = datetime.now() - timedelta(days=10 - x)
|
||||||
con.save()
|
con.save()
|
||||||
|
if not self.addon and not self.con:
|
||||||
self.con = con
|
self.addon, self.con = addon, con
|
||||||
self.addon = addon
|
|
||||||
|
|
||||||
def test_in_menu(self):
|
def test_in_menu(self):
|
||||||
doc = pq(self.client.get(self.url).content)
|
doc = pq(self.client.get(self.url).content)
|
||||||
|
@ -912,31 +913,30 @@ class TestPurchases(amo.tests.TestCase):
|
||||||
def test_purchase_list(self):
|
def test_purchase_list(self):
|
||||||
res = self.client.get(self.url)
|
res = self.client.get(self.url)
|
||||||
eq_(res.status_code, 200)
|
eq_(res.status_code, 200)
|
||||||
eq_(len(res.context['purchases'].object_list), 4)
|
eq_(len(res.context['addons'].object_list), 4)
|
||||||
|
|
||||||
def get_order(self, order):
|
def get_order(self, order):
|
||||||
res = self.client.get('%s?sort=%s' % (self.url, order))
|
res = self.client.get('%s?sort=%s' % (self.url, order))
|
||||||
return [str(c.addon.name) for c in
|
return [str(c.name) for c in
|
||||||
res.context['purchases'].object_list]
|
res.context['addons'].object_list]
|
||||||
|
|
||||||
def test_ordering(self):
|
def test_ordering(self):
|
||||||
eq_(self.get_order('name'), ['t1', 't2', 't3', 't4'])
|
eq_(self.get_order('name'), ['t1', 't2', 't3', 't4'])
|
||||||
eq_(self.get_order('price'), ['t1', 't2', 't3', 't4'])
|
eq_(self.get_order('price'), ['t1', 't2', 't3', 't4'])
|
||||||
eq_(self.get_order('date'), ['t4', 't3', 't2', 't1'])
|
|
||||||
|
|
||||||
def test_price(self):
|
def test_price(self):
|
||||||
res = self.client.get(self.url)
|
res = self.client.get(self.url)
|
||||||
assert '$4.00' in pq(res.content)('div.vitals').eq(0).text()
|
assert '$1.00' in pq(res.content)('div.vitals').eq(0).text()
|
||||||
|
|
||||||
def test_price_locale(self):
|
def test_price_locale(self):
|
||||||
res = self.client.get(self.url.replace('/en-US', '/fr'))
|
res = self.client.get(self.url.replace('/en-US', '/fr'))
|
||||||
assert u'4,00' in pq(res.content)('div.vitals').eq(0).text()
|
assert u'1,00' in pq(res.content)('div.vitals').eq(0).text()
|
||||||
|
|
||||||
def test_receipt(self):
|
def test_receipt(self):
|
||||||
res = self.client.get(reverse('users.purchases.receipt',
|
res = self.client.get(reverse('users.purchases.receipt',
|
||||||
args=[self.addon.pk]))
|
args=[self.addon.pk]))
|
||||||
eq_(len(res.context['purchases'].object_list), 1)
|
eq_(len(res.context['addons'].object_list), 1)
|
||||||
eq_(res.context['purchases'].object_list[0].addon.pk, self.addon.pk)
|
eq_(res.context['addons'].object_list[0].pk, self.addon.pk)
|
||||||
|
|
||||||
def test_receipt_404(self):
|
def test_receipt_404(self):
|
||||||
url = reverse('users.purchases.receipt', args=[545])
|
url = reverse('users.purchases.receipt', args=[545])
|
||||||
|
@ -1057,7 +1057,7 @@ class TestPurchases(amo.tests.TestCase):
|
||||||
email = mail.outbox[0]
|
email = mail.outbox[0]
|
||||||
eq_(email.to, ['a@a.com'])
|
eq_(email.to, ['a@a.com'])
|
||||||
eq_(email.from_email, 'regular@mozilla.com')
|
eq_(email.from_email, 'regular@mozilla.com')
|
||||||
assert '$4.00' in email.body
|
assert '$1.00' in email.body
|
||||||
|
|
||||||
def test_request_fails(self):
|
def test_request_fails(self):
|
||||||
self.addon.support_email = 'a@a.com'
|
self.addon.support_email = 'a@a.com'
|
||||||
|
@ -1066,3 +1066,23 @@ class TestPurchases(amo.tests.TestCase):
|
||||||
self.client.post(self.get_url('request'), {'remove': 1})
|
self.client.post(self.get_url('request'), {'remove': 1})
|
||||||
res = self.client.post(self.get_url('reason'), {})
|
res = self.client.post(self.get_url('reason'), {})
|
||||||
eq_(res.status_code, 200)
|
eq_(res.status_code, 200)
|
||||||
|
|
||||||
|
def test_free_shows_up(self):
|
||||||
|
Contribution.objects.all().delete()
|
||||||
|
res = self.client.get(self.url)
|
||||||
|
eq_(res.context['addons'][0].pk, self.addon.pk)
|
||||||
|
|
||||||
|
def test_others_free_dont(self):
|
||||||
|
Contribution.objects.all().delete()
|
||||||
|
other = UserProfile.objects.get(pk=10482)
|
||||||
|
Installed.objects.all()[0].update(user=other)
|
||||||
|
res = self.client.get(self.url)
|
||||||
|
eq_(len(res.context['addons']), 3)
|
||||||
|
|
||||||
|
def test_purchase_multiple(self):
|
||||||
|
Contribution.objects.create(user=self.user.get_profile(),
|
||||||
|
addon=self.addon, amount='1.00',
|
||||||
|
type=amo.CONTRIB_PURCHASE)
|
||||||
|
res = self.client.get(self.url)
|
||||||
|
addon_vitals = pq(res.content)('div.vitals').eq(0)
|
||||||
|
eq_(len(addon_vitals('div.purchase-byline')), 2)
|
||||||
|
|
|
@ -569,19 +569,16 @@ def unsubscribe(request, hash=None, token=None, perm_setting=None):
|
||||||
{'unsubscribed': unsubscribed, 'perm_settings': perm_settings})
|
{'unsubscribed': unsubscribed, 'perm_settings': perm_settings})
|
||||||
|
|
||||||
|
|
||||||
class ContributionsFilter(BaseFilter):
|
class AddonsFilter(BaseFilter):
|
||||||
opts = (('date', _lazy(u'Purchase Date')),
|
opts = (('price', _lazy(u'Price')),
|
||||||
('price', _lazy(u'Price')),
|
|
||||||
('name', _lazy(u'Name')))
|
('name', _lazy(u'Name')))
|
||||||
|
|
||||||
def filter(self, field):
|
def filter(self, field):
|
||||||
qs = self.base_queryset
|
qs = self.base_queryset
|
||||||
if field == 'date':
|
if field == 'price':
|
||||||
return qs.order_by('-created')
|
return qs.order_by('addonpremium__price')
|
||||||
elif field == 'price':
|
|
||||||
return qs.order_by('amount')
|
|
||||||
elif field == 'name':
|
elif field == 'name':
|
||||||
return qs.order_by('addon__name')
|
return qs.order_by('name')
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
|
@ -590,21 +587,39 @@ def purchases(request, addon_id=None):
|
||||||
if not waffle.switch_is_active('marketplace'):
|
if not waffle.switch_is_active('marketplace'):
|
||||||
raise http.Http404
|
raise http.Http404
|
||||||
|
|
||||||
|
# First get all the contributions.
|
||||||
# TODO(ashort): this is where we'll need to get cunning about refunds.
|
# TODO(ashort): this is where we'll need to get cunning about refunds.
|
||||||
cs = Contribution.objects.filter(user=request.amo_user,
|
cs = Contribution.objects.filter(user=request.amo_user,
|
||||||
type=amo.CONTRIB_PURCHASE)
|
type=amo.CONTRIB_PURCHASE)
|
||||||
if addon_id:
|
if addon_id:
|
||||||
cs = cs.filter(addon=addon_id)
|
cs = cs.filter(addon=addon_id)
|
||||||
|
|
||||||
filter = ContributionsFilter(request, cs, key='sort', default='date')
|
contributions = {}
|
||||||
purchases = amo.utils.paginate(request, filter.qs)
|
for c in cs:
|
||||||
|
contributions.setdefault(c.addon_id, []).append(c)
|
||||||
|
|
||||||
if addon_id and not purchases.object_list:
|
# If you are asking for a receipt for just one item, only show that.
|
||||||
|
# Otherwise, we'll show all addons that have a contribution or are free.
|
||||||
|
if addon_id:
|
||||||
|
ids = [addon_id]
|
||||||
|
else:
|
||||||
|
free = (request.amo_user.installed_set
|
||||||
|
.exclude(addon__in=contributions.keys())
|
||||||
|
.values_list('addon_id', flat=True))
|
||||||
|
ids = contributions.keys() + list(free)
|
||||||
|
|
||||||
|
filter = AddonsFilter(request, Addon.objects.filter(id__in=ids),
|
||||||
|
key='sort', default='name')
|
||||||
|
|
||||||
|
if addon_id and not filter.qs:
|
||||||
# User has requested a receipt for an addon they don't have.
|
# User has requested a receipt for an addon they don't have.
|
||||||
raise http.Http404
|
raise http.Http404
|
||||||
|
|
||||||
return jingo.render(request, 'users/purchases.html',
|
return jingo.render(request, 'users/purchases.html',
|
||||||
{'purchases': purchases, 'filter': filter,
|
{'addons': amo.utils.paginate(request, filter.qs),
|
||||||
|
'filter': filter,
|
||||||
'url_base': reverse('users.purchases'),
|
'url_base': reverse('users.purchases'),
|
||||||
|
'contributions': contributions,
|
||||||
'single': bool(addon_id)})
|
'single': bool(addon_id)})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,9 @@
|
||||||
color: @note-gray;
|
color: @note-gray;
|
||||||
content: '\00B7';
|
content: '\00B7';
|
||||||
}
|
}
|
||||||
|
&.purchase-byline {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
span.price {
|
span.price {
|
||||||
color: @green;
|
color: @green;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче