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

Commit d710672

Browse files
author
Andy McKay
committed
mail out pending refunds status (bug 719210)
1 parent 8d0736d commit d710672

File tree

4 files changed

+125
-5
lines changed

4 files changed

+125
-5
lines changed

apps/market/cron.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
from datetime import datetime, timedelta
22

3-
import amo
43
import commonware.log
54
import cronjobs
6-
from market.models import AddonPremium
5+
from jingo import env
6+
7+
from django.conf import settings
8+
from django.db.models import Count
9+
10+
from addons.models import Addon, AddonUser
11+
import amo
12+
from amo.utils import send_mail
13+
from market.models import AddonPremium, Refund
714

815
log = commonware.log.getLogger('z.cron')
916

@@ -22,3 +29,37 @@ def clean_out_addonpremium(days=DAYS_OLD):
2229
(obj.addon_id, obj.created))
2330
obj.delete()
2431

32+
33+
@cronjobs.register
34+
def mail_pending_refunds():
35+
# First find all the pending refunds and the addons for them.
36+
pending = dict((Refund.objects.filter(status=amo.REFUND_PENDING)
37+
.values_list('contribution__addon_id')
38+
.annotate(Count('id'))))
39+
if not pending:
40+
log.info('No refunds to email')
41+
return
42+
log.info('Mailing pending refunds: %s refunds found' % len(pending))
43+
44+
# Find all owners of those addons.
45+
users = (AddonUser.objects.filter(role=amo.AUTHOR_ROLE_OWNER,
46+
addon__in=pending.keys())
47+
.values_list('addon_id', 'user__email'))
48+
49+
# Group up the owners. An owner could have more than one addon and each
50+
# addon can have more than one owner.
51+
owners = {}
52+
for addon_id, email in users:
53+
owners.setdefault(email, [])
54+
owners[email].append(addon_id)
55+
56+
# Send the emails out.
57+
for owner, addon_ids in owners.items():
58+
log.info('Sending refund emails to: %s about %s' %
59+
(email, ', '.join([str(i) for i in addon_ids])))
60+
addons = Addon.objects.filter(pk__in=addon_ids)
61+
ctx = {'addons': addons, 'refunds': pending}
62+
send_mail('Pending refund requests at the Mozilla Marketplace',
63+
env.get_template('market/emails/refund-nag.txt').render(ctx),
64+
from_email=settings.NOBODY_EMAIL,
65+
recipient_list=[owner])
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
You have products at the Mozilla Marketplace that have pending refund requests and require your attention. Please visit the URLs below to respond to these requests:
2+
3+
{% for addon in addons %}
4+
{{ addon.name }} ({{ ngettext('{0} request', '{0} requests', refunds[addon.pk])|f(refunds[addon.pk]) }})
5+
{{ addon.get_dev_url('refunds')|absolutify }}
6+
{% endfor %}
7+
8+
Thanks for your prompt response. Your customers will appreciate it!
9+
10+
- the Mozilla Marketplace Team

apps/market/tests/test_cron.py

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
from datetime import datetime, timedelta
22

3+
from django.core import mail
4+
35
from nose.tools import eq_
46

57
import amo
68
import amo.tests
7-
from addons.models import Addon
8-
from market.models import AddonPremium
9-
from market.cron import clean_out_addonpremium
9+
from addons.models import Addon, AddonUser
10+
from market.cron import clean_out_addonpremium, mail_pending_refunds
11+
from market.models import AddonPremium, Refund
12+
from stats.models import Contribution
13+
from users.models import UserProfile
1014

1115

1216
class TestCronDeletes(amo.tests.TestCase):
@@ -30,3 +34,67 @@ def test_doesnt_delete(self):
3034
clean_out_addonpremium(days=1)
3135
eq_(AddonPremium.objects.count(), 3)
3236

37+
38+
class TestPendingRefunds(amo.tests.TestCase):
39+
fixtures = ['webapps/337141-steamcube', 'base/users']
40+
41+
def create_refund(self, webapp=None):
42+
webapp = webapp if webapp else self.webapp
43+
contribution = Contribution.objects.create(addon=webapp)
44+
return Refund.objects.create(contribution=contribution)
45+
46+
def setUp(self):
47+
self.webapp = Addon.objects.get(pk=337141)
48+
self.author = self.webapp.authors.all()[0]
49+
self.refund = self.create_refund()
50+
51+
def test_none(self):
52+
self.refund.delete()
53+
mail_pending_refunds()
54+
eq_(len(mail.outbox), 0)
55+
56+
def test_not_pending(self):
57+
for status in [amo.REFUND_APPROVED, amo.REFUND_APPROVED_INSTANT,
58+
amo.REFUND_DECLINED]:
59+
self.refund.update(status=status)
60+
mail_pending_refunds()
61+
eq_(len(mail.outbox), 0)
62+
63+
def test_single(self):
64+
mail_pending_refunds()
65+
eq_(len(mail.outbox), 1)
66+
assert str(self.webapp.name) in mail.outbox[0].body
67+
assert '1 request' in mail.outbox[0].body
68+
assert mail.outbox[0].to == [self.author.email]
69+
70+
def test_plural(self):
71+
self.create_refund()
72+
mail_pending_refunds()
73+
eq_(len(mail.outbox), 1)
74+
assert '2 requests' in mail.outbox[0].body
75+
76+
def test_two_owners(self):
77+
user = UserProfile.objects.exclude(pk=self.author.pk)[0]
78+
AddonUser.objects.create(user=user, addon=self.webapp)
79+
mail_pending_refunds()
80+
eq_(len(mail.outbox), 2)
81+
emails = set([m.to[0] for m in mail.outbox])
82+
eq_(set([self.author.email, user.email]), emails)
83+
84+
def test_one_owner_one_other(self):
85+
user = UserProfile.objects.exclude(pk=self.author.pk)[0]
86+
AddonUser.objects.create(user=user, addon=self.webapp,
87+
role=amo.AUTHOR_ROLE_VIEWER)
88+
mail_pending_refunds()
89+
eq_(len(mail.outbox), 1)
90+
assert mail.outbox[0].to == [self.author.email]
91+
92+
def test_two_addons(self):
93+
other = Addon.objects.create(app_slug='something-else',
94+
name='cthulhu', type=amo.ADDON_WEBAPP)
95+
AddonUser.objects.create(user=self.author, addon=other,
96+
role=amo.AUTHOR_ROLE_OWNER)
97+
self.create_refund(other)
98+
mail_pending_refunds()
99+
eq_(len(mail.outbox), 1)
100+
eq_(mail.outbox[0].body.count('1 request'), 2)

scripts/crontab/crontab.tpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ HOME=/tmp
4242
30 1 * * * {{ z_cron }} update_user_ratings
4343
40 1 * * * {{ z_cron }} update_weekly_downloads
4444
50 1 * * * {{ z_cron }} gc
45+
30 2 * * * {{ z_cron }} mail_pending_refunds
4546
30 3 * * * {{ django }} cleanup
4647
30 4 * * * {{ z_cron }} cleanup_synced_collections
4748
30 5 * * * {{ z_cron }} expired_resetcode

0 commit comments

Comments
 (0)