alter purchases to cope with multiple purchases, add in free and remove date paid sorting for now (bug 696509)

This commit is contained in:
Andy McKay 2011-10-27 16:03:55 -07:00
Родитель ff656a8be9
Коммит 8f2403e5a5
4 изменённых файлов: 72 добавлений и 31 удалений

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

@ -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 %}
&middot; <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;