the support pages (bug 686808)
This commit is contained in:
Родитель
613ea4a983
Коммит
11e4158a2e
|
@ -147,7 +147,8 @@ def create_addon_purchase(sender, instance, **kw):
|
|||
if instance.type == amo.CONTRIB_PURCHASE:
|
||||
log.debug('Creating addon purchase: addon %s, user %s'
|
||||
% (instance.addon.pk, instance.user.pk))
|
||||
AddonPurchase.objects.create(addon=instance.addon, user=instance.user)
|
||||
AddonPurchase.objects.get_or_create(addon=instance.addon,
|
||||
user=instance.user)
|
||||
|
||||
elif instance.type in [amo.CONTRIB_REFUND, amo.CONTRIB_CHARGEBACK]:
|
||||
purchases = AddonPurchase.objects.filter(addon=instance.addon,
|
||||
|
|
|
@ -408,3 +408,13 @@ class BlacklistedEmailDomainAddForm(forms.Form):
|
|||
self._errors['domains'] = ErrorList([msg])
|
||||
|
||||
return data
|
||||
|
||||
|
||||
class ContactForm(happyforms.Form):
|
||||
text = forms.CharField(widget=forms.Textarea(), required=True)
|
||||
|
||||
|
||||
class RemoveForm(happyforms.Form):
|
||||
remove = forms.BooleanField(required=True,
|
||||
label=_('I have removed this add-on from '
|
||||
'all of my devices.'))
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
{{ impala_addon_listing_header(url_base, filter.opts, sorting, filter.extras) }}
|
||||
{% endif %}
|
||||
<div class="items">
|
||||
{% for addon in purchases.object_list %}
|
||||
{% for contribution in purchases.object_list %}
|
||||
{% with addon=contribution.addon %}
|
||||
<div class="item addon ignore-compatibility">
|
||||
<div class="info">
|
||||
<h3>
|
||||
|
@ -24,12 +25,13 @@
|
|||
</h3>
|
||||
<p class="desc">{{ addon.description|truncate(250)|nl2br }}</p>
|
||||
<div class="vitals c">
|
||||
{% trans date=addon.created, amt=prices[addon.pk][1], url='' %}
|
||||
{% trans date=addon.created, amt=contribution.get_amount_locale(), url=url('users.support', contribution.pk) %}
|
||||
<div>Purchased {{ date }} for {{ amt }} - <a href="{{ url }}">Request Support</a></div>
|
||||
{% endtrans %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<p>You have no purchases.</p>
|
||||
{% endfor %}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<h1>{{ _('Support Request Sent') }}</h1>
|
||||
<p>{% trans %}You support request has been sent.{% endtrans %}</p>
|
||||
<p><a href="{{ url('users.purchases') }}" class="button">Close</a></p>
|
|
@ -0,0 +1,13 @@
|
|||
<h1>{{ _('Contact the Author') }}</h1>
|
||||
<form method="POST">
|
||||
{{ csrf() }}
|
||||
<p>{% trans %}For support questions regarding this add-on's functionality,
|
||||
please contact the author using the form below.{% endtrans %}</p>
|
||||
<p><strong>{% trans name=addon.name %}To: {{ name }}{% endtrans %}</strong></p>
|
||||
<p><strong>{% trans %}Please describe the issue:{% endtrans %}</strong></p>
|
||||
{{ form.text.errors }}
|
||||
{{ form.text }}
|
||||
<p>{% trans %}Your email address will be made available to the
|
||||
add-on author for replies.{% endtrans %}</p>
|
||||
<button type="submit">{{ _('Send Request') }}</button>
|
||||
</form>
|
|
@ -0,0 +1,9 @@
|
|||
Your add-on, {{ addon.name }}, has received a new refund request:
|
||||
User: {{ user.display_name or user.username }}
|
||||
Purchased on {{ contribution.date|datetime }}
|
||||
Price: {{ contribution.get_amount_locale() }}
|
||||
|
||||
Reason given:
|
||||
{{ form.cleaned_data.text }}
|
||||
|
||||
To approve or deny this request, click here: ...
|
|
@ -0,0 +1,12 @@
|
|||
Add-on, {{ addon.name }}, has received a new support request:
|
||||
User: {{ user.display_name or user.username }}
|
||||
Email: {{ user.email }}
|
||||
Purchased on {{ contribution.date|datetime }}
|
||||
|
||||
Details:
|
||||
|
||||
{{ form.cleaned_data.text }}
|
||||
|
||||
{{ request.HTTP_USER_AGENT }}
|
||||
|
||||
Please reply to this email to respond to the user’s request.
|
|
@ -0,0 +1,14 @@
|
|||
<h1>{{ _('Contact Mozilla') }}</h1>
|
||||
<form method="POST">
|
||||
{{ csrf() }}
|
||||
<p>{% trans %}Please use this form <strong>only for issues with the Mozilla
|
||||
Marketplace</strong>. For other suport and question, please visit
|
||||
<a href="{{ sumo }}">support.mozilla.com</a>. We are unable to respond
|
||||
to misdirected support requests through this form
|
||||
{% endtrans %}</p>
|
||||
<p><strong>{% trans %}To: Mozilla Marketplace Support{% endtrans %}</strong></p>
|
||||
<p><strong>{% trans %}Please describe the issue:{% endtrans %}</strong></p>
|
||||
{{ form.text.errors }}
|
||||
{{ form.text }}
|
||||
<button type="submit">{{ _('Send Request') }}</button>
|
||||
</form>
|
|
@ -0,0 +1,5 @@
|
|||
<h1>{{ _('Request Refund') }}</h1>
|
||||
<p>{% trans name=addon.name %}Your request for a refund of {{ name }} has been
|
||||
submitted. You will receive an email when the author of this add-on has
|
||||
responded.{% endtrans %}</p>
|
||||
<p><a href="{{ url('users.purchases') }}" class="button">Close</a></p>
|
|
@ -0,0 +1,8 @@
|
|||
<h1>{{ _('Request Refund') }}</h1>
|
||||
<form method="POST">
|
||||
{{ csrf() }}
|
||||
<p>{% trans %} Please tell us why you are requesting a refund.{% endtrans %}</p>
|
||||
{{ form.text.errors }}
|
||||
{{ form.text }}
|
||||
<button type="submit">{{ _('Request Refund') }}</button>
|
||||
</form>
|
|
@ -0,0 +1,17 @@
|
|||
<h1>{{ _('Request Refund') }}</h1>
|
||||
<form method="POST">
|
||||
{{ csrf() }}
|
||||
<p>{% trans url=url('users.support', contribution.pk, 'author') %}
|
||||
If you are unsatisfied with your purchase, you may request
|
||||
a refund from the developer for up to 60 days. Requests within 30 minutes
|
||||
after purchase are automatically granted. If you are having difficulty
|
||||
using the add-on, we encourage you to <a href="{{ url }}">ask the developer for
|
||||
support</a> before requesting a refund.{% endtrans %}</p>
|
||||
<p>{% trans name=addon.name %}In order to continue with the refund
|
||||
process, <b>you must completely
|
||||
remove the add-on from all of your devices</b>. Open Add-ons Manager,
|
||||
select Remove next to {{ name }} and restart Firefox.{% endtrans %}</p>
|
||||
{{ form.remove.errors }}
|
||||
<p>{{ form.remove }} {{ form.remove.label }}</p>
|
||||
<button type="submit">{{ _('Continue') }}</button>
|
||||
</form>
|
|
@ -0,0 +1,8 @@
|
|||
<h1>{{ _('Helpful Resources') }}</h1>
|
||||
<p>{% trans %}Please use the articles below to find answers to some of the
|
||||
most common questions and issues encountered in the Marketplace.
|
||||
{% endtrans %}</p>
|
||||
<p>{% trans url=url('users.support', contribution.pk, 'mozilla') %}
|
||||
If you looked through the above resources and still have a
|
||||
question, please <a href="{{ url }}">contact us</a>
|
||||
{% endtrans %}.</p>
|
|
@ -0,0 +1,10 @@
|
|||
<h1>{{ _('Add-on Support') }}</h1>
|
||||
<p>{% trans %}For support questions regarding this add-on's functionality,
|
||||
please visit the add-on author's support website to search for
|
||||
a solution:{% endtrans %}</p>
|
||||
<h2><a href="{{ addon.support_url }}">{{ addon.name }}</a></h2>
|
||||
<p>{% trans url=url('users.support', contribution.pk, 'author') %}
|
||||
If you are unable to find the answer to your question at the
|
||||
above support website, please <a href="{{ url }}">contact the author</a>.
|
||||
{% endtrans %}</p>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<h1>{{ _('What do you need help with?') }}</h1>
|
||||
<p><a href="{% with step='site' if addon.support_url else 'author' %}{{ url('users.support', contribution.pk, step) }}{% endwith %}">{{ _("This add-on isn't working as expected »") }}</a></p>
|
||||
<p><a href="{{ url('users.support', contribution.pk, 'resources') }}">{{ _("I can't install my purchase »") }}</a></p>
|
||||
<p><a href="{{ url('users.support', contribution.pk, 'resources') }}">{{ _('I have billing or payment concerns »') }}</a></p>
|
||||
<p><a href="{{ url('users.support', contribution.pk, 'request') }}">{{ _('I want to request a refund »') }}</a></p>
|
|
@ -0,0 +1,9 @@
|
|||
{% extends "impala/base.html" %}
|
||||
|
||||
{% block title %}{{ page_title(wizard.title) }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="primary">
|
||||
{% include content %}
|
||||
</section>
|
||||
{% endblock %}
|
|
@ -1,3 +1,4 @@
|
|||
from datetime import datetime, timedelta
|
||||
import json
|
||||
|
||||
from django.conf import settings
|
||||
|
@ -704,9 +705,13 @@ class TestPurchases(amo.tests.TestCase):
|
|||
for x in range(1, 5):
|
||||
addon = Addon.objects.create(type=amo.ADDON_EXTENSION,
|
||||
name='t%s' % x)
|
||||
Contribution.objects.create(user=self.user.get_profile(),
|
||||
addon=addon, amount='%s.00' % x,
|
||||
type=amo.CONTRIB_PURCHASE)
|
||||
con = Contribution.objects.create(user=self.user.get_profile(),
|
||||
addon=addon, amount='%s.00' % x,
|
||||
type=amo.CONTRIB_PURCHASE)
|
||||
con.created = datetime.now() - timedelta(days=10 - x)
|
||||
con.save()
|
||||
|
||||
self.con = con
|
||||
self.addon = addon
|
||||
|
||||
def test_in_menu(self):
|
||||
|
@ -734,7 +739,8 @@ class TestPurchases(amo.tests.TestCase):
|
|||
|
||||
def get_order(self, order):
|
||||
res = self.client.get('%s?sort=%s' % (self.url, order))
|
||||
return [str(a.name) for a in res.context['purchases'].object_list]
|
||||
return [str(c.addon.name) for c in
|
||||
res.context['purchases'].object_list]
|
||||
|
||||
def test_ordering(self):
|
||||
eq_(self.get_order('name'), ['t1', 't2', 't3', 't4'])
|
||||
|
@ -774,3 +780,112 @@ class TestPurchases(amo.tests.TestCase):
|
|||
self.user.get_profile().addonpurchase_set.all().delete()
|
||||
doc = pq(self.client.get(self.url).content)
|
||||
eq_(doc('body').attr('data-purchases'), '')
|
||||
|
||||
def test_refund_link(self):
|
||||
doc = pq(self.client.get(self.url).content)
|
||||
url = reverse('users.support', args=[self.con.pk])
|
||||
eq_(doc('div.vitals a').eq(0).attr('href'), url)
|
||||
|
||||
def get_url(self, *args):
|
||||
return reverse('users.support', args=[self.con.pk] + list(args))
|
||||
|
||||
def test_support_not_logged_in(self):
|
||||
self.client.logout()
|
||||
eq_(self.client.get(self.get_url()).status_code, 302)
|
||||
|
||||
def test_support_not_mine(self):
|
||||
self.client.login(username='admin@mozilla.com', password='password')
|
||||
eq_(self.client.get(self.get_url()).status_code, 404)
|
||||
|
||||
def test_support_page(self):
|
||||
doc = pq(self.client.get(self.get_url()).content)
|
||||
eq_(doc('section.primary a').attr('href'), self.get_url('author'))
|
||||
|
||||
def test_support_page_other(self):
|
||||
self.addon.support_url = 'http://cbc.ca'
|
||||
self.addon.save()
|
||||
|
||||
doc = pq(self.client.get(self.get_url()).content)
|
||||
eq_(doc('section.primary a').attr('href'), self.get_url('site'))
|
||||
|
||||
def test_support_site(self):
|
||||
self.addon.support_url = 'http://cbc.ca'
|
||||
self.addon.save()
|
||||
|
||||
doc = pq(self.client.get(self.get_url('site')).content)
|
||||
eq_(doc('section.primary a').attr('href'), self.addon.support_url)
|
||||
|
||||
def test_contact(self):
|
||||
data = {'text': 'Lorem ipsum dolor sit amet, consectetur'}
|
||||
res = self.client.post(self.get_url('author'), data)
|
||||
eq_(res.status_code, 302)
|
||||
|
||||
def test_contact_mails(self):
|
||||
self.addon.support_email = 'a@a.com'
|
||||
self.addon.save()
|
||||
|
||||
data = {'text': 'Lorem ipsum dolor sit amet, consectetur'}
|
||||
self.client.post(self.get_url('author'), data)
|
||||
eq_(len(mail.outbox), 1)
|
||||
email = mail.outbox[0]
|
||||
eq_(email.to, ['a@a.com'])
|
||||
eq_(email.from_email, 'regular@mozilla.com')
|
||||
|
||||
def test_contact_fails(self):
|
||||
res = self.client.post(self.get_url('author'), {'b': 'c'})
|
||||
assert 'text' in res.context['form'].errors
|
||||
|
||||
def test_contact_mozilla(self):
|
||||
data = {'text': 'Lorem ipsum dolor sit amet, consectetur'}
|
||||
res = self.client.post(self.get_url('mozilla'), data)
|
||||
eq_(res.status_code, 302)
|
||||
|
||||
def test_contact_mozilla_mails(self):
|
||||
data = {'text': 'Lorem ipsum dolor sit amet, consectetur'}
|
||||
self.client.post(self.get_url('mozilla'), data)
|
||||
eq_(len(mail.outbox), 1)
|
||||
email = mail.outbox[0]
|
||||
eq_(email.to, [settings.FLIGTAR])
|
||||
eq_(email.from_email, 'regular@mozilla.com')
|
||||
assert 'Lorem' in email.body
|
||||
|
||||
def test_contact_mozilla_fails(self):
|
||||
res = self.client.post(self.get_url('mozilla'), {'b': 'c'})
|
||||
assert 'text' in res.context['form'].errors
|
||||
|
||||
def test_refund_remove(self):
|
||||
res = self.client.post(self.get_url('request'), {'remove': 1})
|
||||
eq_(res.status_code, 302)
|
||||
|
||||
def test_refund_remove_fails(self):
|
||||
res = self.client.post(self.get_url('request'), {})
|
||||
eq_(res.status_code, 200)
|
||||
|
||||
def test_skip_fails(self):
|
||||
res = self.client.post(self.get_url('reason'), {})
|
||||
self.assertRedirects(res, self.get_url('request'))
|
||||
|
||||
def test_request(self):
|
||||
self.client.post(self.get_url('request'), {'remove': 1})
|
||||
res = self.client.post(self.get_url('reason'), {'text': 'something'})
|
||||
eq_(res.status_code, 302)
|
||||
|
||||
def test_request_mails(self):
|
||||
self.addon.support_email = 'a@a.com'
|
||||
self.addon.save()
|
||||
|
||||
self.client.post(self.get_url('request'), {'remove': 1})
|
||||
self.client.post(self.get_url('reason'), {'text': 'something'})
|
||||
eq_(len(mail.outbox), 1)
|
||||
email = mail.outbox[0]
|
||||
eq_(email.to, ['a@a.com'])
|
||||
eq_(email.from_email, 'regular@mozilla.com')
|
||||
assert '$4.00' in email.body
|
||||
|
||||
def test_request_fails(self):
|
||||
self.addon.support_email = 'a@a.com'
|
||||
self.addon.save()
|
||||
|
||||
self.client.post(self.get_url('request'), {'remove': 1})
|
||||
res = self.client.post(self.get_url('reason'), {})
|
||||
eq_(res.status_code, 200)
|
||||
|
|
|
@ -60,6 +60,9 @@ users_patterns = patterns('',
|
|||
url(r'purchases/$', views.purchases, name='users.purchases'),
|
||||
url(r'purchases/%s$' % ADDON_ID, views.purchases,
|
||||
name='users.purchases.receipt'),
|
||||
url(r'support/(?P<contribution_id>\d+)(?:/(?P<step>[\w-]+))?$',
|
||||
views.SupportWizard.as_view(),
|
||||
name='users.support')
|
||||
)
|
||||
|
||||
urlpatterns = patterns('',
|
||||
|
|
|
@ -6,12 +6,16 @@ from django.db import IntegrityError
|
|||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.contrib import auth
|
||||
from django.template import Context, loader
|
||||
from django.utils.datastructures import SortedDict
|
||||
from django.views.decorators.cache import never_cache
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.encoding import smart_str
|
||||
from django.utils.http import base36_to_int
|
||||
from django.contrib.auth.tokens import default_token_generator
|
||||
|
||||
import commonware.log
|
||||
import jingo
|
||||
from radagast.wizard import Wizard
|
||||
from ratelimit.decorators import ratelimit
|
||||
from tower import ugettext as _, ugettext_lazy as _lazy
|
||||
from session_csrf import anonymous_csrf, anonymous_csrf_exempt
|
||||
|
@ -28,10 +32,10 @@ from amo.utils import send_mail
|
|||
from abuse.models import send_abuse_report
|
||||
from addons.models import Addon
|
||||
from addons.views import BaseFilter
|
||||
from addons.decorators import addon_view
|
||||
from access import acl
|
||||
from bandwagon.models import Collection
|
||||
from stats.models import Contribution
|
||||
from translations.query import order_by_translation
|
||||
from users.models import UserNotification
|
||||
import users.notifications as notifications
|
||||
|
||||
|
@ -612,20 +616,14 @@ class ContributionsFilter(BaseFilter):
|
|||
('price', _lazy(u'Price')),
|
||||
('name', _lazy(u'Name')))
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
self.prices = kw.pop('prices')
|
||||
super(ContributionsFilter, self).__init__(*args, **kw)
|
||||
|
||||
def filter(self, field):
|
||||
qs = self.base_queryset
|
||||
if field == 'date':
|
||||
return qs.order_by('-created')
|
||||
elif field == 'price':
|
||||
# TODO(andym): If someone has a large number of purchases,
|
||||
# this will get expensive.
|
||||
return sorted(list(qs), key=lambda x: self.prices[x.pk][0])
|
||||
return qs.order_by('amount')
|
||||
elif field == 'name':
|
||||
return order_by_translation(qs, 'name')
|
||||
return qs.order_by('addon__name')
|
||||
|
||||
|
||||
@login_required
|
||||
|
@ -634,21 +632,144 @@ def purchases(request, addon_id=None):
|
|||
if not waffle.switch_is_active('marketplace'):
|
||||
raise http.Http404
|
||||
|
||||
# TODO(ashort): this is where we'll need to get cunning about refunds.
|
||||
cs = Contribution.objects.filter(user=request.amo_user,
|
||||
type=amo.CONTRIB_PURCHASE)
|
||||
if addon_id:
|
||||
cs = cs.filter(addon=addon_id)
|
||||
prices = dict((p.addon_id, (p.amount, p.get_amount_locale())) for p in cs)
|
||||
if addon_id and not prices:
|
||||
|
||||
filter = ContributionsFilter(request, cs, key='sort', default='date')
|
||||
purchases = amo.utils.paginate(request, filter.qs)
|
||||
|
||||
if addon_id and not purchases.object_list:
|
||||
# User has requested a receipt for an addon they don't have.
|
||||
raise http.Http404
|
||||
|
||||
base = Addon.objects.filter(id__in=prices.keys())
|
||||
filter = ContributionsFilter(request, base, key='sort',
|
||||
default='date', prices=prices)
|
||||
|
||||
purchases = amo.utils.paginate(request, filter.qs, count=len(prices))
|
||||
return jingo.render(request, 'users/purchases.html',
|
||||
{'purchases': purchases, 'filter': filter,
|
||||
'url_base': reverse('users.purchases'),
|
||||
'prices': prices, 'single': bool(addon_id)})
|
||||
'single': bool(addon_id)})
|
||||
|
||||
|
||||
# Start of the Support wizard all of these are accessed through the
|
||||
# SupportWizard below.
|
||||
def plain(request, contribution, wizard):
|
||||
# Simple view that just shows a template matching the step.
|
||||
tpl = wizard.tpl('%s.html' % wizard.step)
|
||||
return wizard.render(request, tpl, {'addon': contribution.addon,
|
||||
'contribution': contribution})
|
||||
|
||||
|
||||
def support_author(request, contribution, wizard):
|
||||
addon = contribution.addon
|
||||
form = forms.ContactForm(request.POST)
|
||||
if request.method == 'POST':
|
||||
if form.is_valid():
|
||||
template = jingo.render_to_string(request,
|
||||
wizard.tpl('emails/support-request.txt'),
|
||||
context={'contribution': contribution,
|
||||
'addon': addon, 'form': form,
|
||||
'user': request.amo_user})
|
||||
log.info('Support request to dev. by user: %s for addon: %s' %
|
||||
(request.amo_user.pk, addon.pk))
|
||||
# L10n: %s is the addon name.
|
||||
send_mail(_(u'New Support Request for %s' % addon.name),
|
||||
template, request.amo_user.email,
|
||||
[smart_str(addon.support_email)])
|
||||
return redirect(reverse('users.support',
|
||||
args=[contribution.pk, 'author-sent']))
|
||||
|
||||
return wizard.render(request, wizard.tpl('author.html'),
|
||||
{'addon': addon, 'form': form})
|
||||
|
||||
|
||||
def support_mozilla(request, contribution, wizard):
|
||||
addon = contribution.addon
|
||||
form = forms.ContactForm(request.POST)
|
||||
if request.method == 'POST':
|
||||
if form.is_valid():
|
||||
template = jingo.render_to_string(request,
|
||||
wizard.tpl('emails/support-request.txt'),
|
||||
context={'addon': addon, 'form': form,
|
||||
'contribution': contribution,
|
||||
'user': request.amo_user})
|
||||
log.info('Support request to mozilla by user: %s for addon: %s' %
|
||||
(request.amo_user.pk, addon.pk))
|
||||
# L10n: %s is the addon name.
|
||||
send_mail(_(u'New Support Request for %s' % addon.name),
|
||||
template, request.amo_user.email, [settings.FLIGTAR])
|
||||
return redirect(reverse('users.support',
|
||||
args=[contribution.pk, 'mozilla-sent']))
|
||||
|
||||
return wizard.render(request, wizard.tpl('mozilla.html'),
|
||||
{'addon': addon, 'form': form})
|
||||
|
||||
|
||||
def refund_request(request, contribution, wizard):
|
||||
addon = contribution.addon
|
||||
form = forms.RemoveForm(request.POST or None)
|
||||
if request.method == 'POST':
|
||||
if form.is_valid():
|
||||
return redirect(reverse('users.support',
|
||||
args=[contribution.pk, 'reason']))
|
||||
|
||||
return wizard.render(request, wizard.tpl('request.html'),
|
||||
{'addon': addon, 'form': form,
|
||||
'contribution': contribution})
|
||||
|
||||
|
||||
def refund_reason(request, contribution, wizard):
|
||||
addon = contribution.addon
|
||||
if not 'request' in wizard.get_progress():
|
||||
return redirect(reverse('users.support',
|
||||
args=[contribution.pk, 'request']))
|
||||
|
||||
form = forms.ContactForm(request.POST or None)
|
||||
if request.method == 'POST':
|
||||
if form.is_valid():
|
||||
# if under 30 minutes, refund
|
||||
# TODO(ashort): add in the logic for under 30 minutes.
|
||||
template = jingo.render_to_string(request,
|
||||
wizard.tpl('emails/refund-request.txt'),
|
||||
context={'addon': addon, 'form': form,
|
||||
'user': request.amo_user,
|
||||
'contribution': contribution})
|
||||
log.info('Refund request sent by user: %s for addon: %s' %
|
||||
(request.amo_user.pk, addon.pk))
|
||||
# L10n: %s is the addon name.
|
||||
send_mail(_(u'New Refund Request for %s' % addon.name),
|
||||
template, request.amo_user.email,
|
||||
[smart_str(addon.support_email)])
|
||||
return redirect(reverse('users.support',
|
||||
args=[contribution.pk, 'refund-sent']))
|
||||
|
||||
return wizard.render(request, wizard.tpl('refund.html'),
|
||||
{'contribut': addon, 'form': form})
|
||||
|
||||
|
||||
class SupportWizard(Wizard):
|
||||
title = _lazy('Support')
|
||||
steps = SortedDict((('start', plain),
|
||||
('site', plain),
|
||||
('resources', plain),
|
||||
('mozilla', support_mozilla),
|
||||
('mozilla-sent', plain),
|
||||
('author', support_author),
|
||||
('author-sent', plain),
|
||||
('request', refund_request),
|
||||
('reason', refund_reason),
|
||||
('refund-sent', plain)))
|
||||
|
||||
def tpl(self, x):
|
||||
return 'users/support/%s' % x
|
||||
|
||||
@property
|
||||
def wrapper(self):
|
||||
return self.tpl('wrapper.html')
|
||||
|
||||
@method_decorator(login_required)
|
||||
def dispatch(self, request, contribution_id, step='', *args, **kw):
|
||||
contribution = get_object_or_404(Contribution, pk=contribution_id)
|
||||
if contribution.user.pk != request.amo_user.pk:
|
||||
raise http.Http404
|
||||
args = [contribution] + list(args)
|
||||
return super(SupportWizard, self).dispatch(request, step, *args, **kw)
|
||||
|
|
|
@ -373,6 +373,7 @@ INSTALLED_APPS = (
|
|||
|
||||
# Has to load after auth
|
||||
'django_browserid',
|
||||
'radagast',
|
||||
)
|
||||
|
||||
# These apps will be removed from INSTALLED_APPS in a production environment.
|
||||
|
|
Загрузка…
Ссылка в новой задаче