Permalink
Browse files

add in currency per addon (bug 741467)

  • Loading branch information...
1 parent b0ccd4e commit 9fe93a72a037e3db58f48b5d71bbf3be5dd46f72 @andymckay andymckay committed Apr 3, 2012
View
@@ -496,7 +496,7 @@ def purchase(request, addon):
amount, currency = addon.premium.get_price(), 'USD'
# If tier is specified, then let's look it up.
- form = PriceCurrencyForm(data=request.POST, price=addon.premium.price)
+ form = PriceCurrencyForm(data=request.POST, addon=addon)
if form.is_valid():
tier = form.get_tier()
if tier:
View
@@ -6,10 +6,9 @@
class PriceCurrencyForm(happyforms.Form):
currency = forms.ChoiceField(choices=(), required=False)
- def __init__(self, price=None, *args, **kw):
- self.price = price
+ def __init__(self, addon=None, *args, **kw):
super(PriceCurrencyForm, self).__init__(*args, **kw)
- self.fields['currency'].choices = self.price.currencies()
+ self.fields['currency'].choices = addon.premium.supported_currencies()
def get_tier(self):
for k, v in self.fields['currency'].choices:
View
@@ -14,6 +14,7 @@
from babel import Locale, numbers
import commonware.log
from jinja2.filters import do_dictsort
+import json_field
import paypal
log = commonware.log.getLogger('z.market')
@@ -83,7 +84,7 @@ def currencies(self):
if not hasattr(self, '_currencies'):
Price.transformer([])
- currencies = [('', self)] # This is USD, which is the default.
+ currencies = [('USD', self)]
currencies.extend([(c.currency, c)
for c in self._currencies.values()
if c.tier_id == self.pk])
@@ -171,6 +172,7 @@ class AddonPremium(amo.models.ModelBase):
addon = models.OneToOneField('addons.Addon')
price = models.ForeignKey(Price, blank=True, null=True)
paypal_permissions_token = models.CharField(max_length=255, blank=True)
+ currencies = json_field.JSONField(default={})
class Meta:
db_table = 'addons_premium'
@@ -208,6 +210,18 @@ def has_valid_permissions_token(self):
return paypal.check_permission(self.paypal_permissions_token,
['REFUND'])
+ def supported_currencies(self):
+ """
+ Return a list of the supported currencies for this app.
+ You get a list of tuples of currency name and the price currency
+ object.
+
+ USD will always be present since that is the default.
+ """
+ currencies = self.currencies or {}
+ return [c for c in self.price.currencies()
+ if c[0] in currencies or c[0] == 'USD']
+
class PreApprovalUser(amo.models.ModelBase):
@@ -1,30 +1,30 @@
-from decimal import Decimal
-import json
-
-
-import mock
from nose.tools import eq_
-from addons.models import Addon
import amo
import amo.tests
-from amo.urlresolvers import reverse
-from market.models import AddonPremium, PreApprovalUser, Price, PriceCurrency
-from stats.models import Contribution
-from users.models import UserProfile
-
-from django.utils import translation
+from addons.models import Addon
+from market.models import AddonPremium, Price
from market.forms import PriceCurrencyForm
class TestForm(amo.tests.TestCase):
- fixtures = ['prices.json']
+ fixtures = ['prices', 'base/addon_3615']
def setUp(self):
self.tier_one = Price.objects.get(pk=1)
+ self.addon = Addon.objects.get(pk=3615)
+ self.addon_premium = AddonPremium.objects.create(addon=self.addon,
+ price=self.tier_one)
+
+ def test_form_fails(self):
+ for currency, valid in (['EUR', False], ['CAD', False]):
+ form = PriceCurrencyForm(data={'currency': currency},
+ addon=self.addon)
+ eq_(bool(form.is_valid()), valid, 'Currency: %s' % currency)
- def test_form(self):
- for currency, valid in (['EUR', True], ['CAD', True], ['BRL', False]):
+ def test_form_passes(self):
+ self.addon_premium.update(currencies=['EUR', 'CAD'])
+ for currency, valid in (['EUR', True], ['BRL', False], ['CAD', True]):
form = PriceCurrencyForm(data={'currency': currency},
- price=self.tier_one)
- eq_(bool(form.is_valid()), valid)
+ addon=self.addon)
+ eq_(bool(form.is_valid()), valid, 'Currency: %s' % currency)
@@ -60,6 +60,19 @@ def test_has_valid_permissions_token_ignore(self):
ap.paypal_permissions_token = 'asd'
assert ap.has_valid_permissions_token()
+ def test_currencies(self):
+ ap = AddonPremium.objects.create(addon=self.addon, price=self.tier_one)
+ print type(ap.currencies)
+ assert self.tier_one.currencies()
+ eq_(len(ap.supported_currencies()), 1)
+ eq_(ap.supported_currencies()[0][0], 'USD')
+
+ def test_add_currency(self):
+ ap = AddonPremium.objects.create(addon=self.addon, price=self.tier_one)
+ ap.update(currencies=['CAD'])
+ eq_(len(ap.supported_currencies()), 2)
+ eq_(ap.supported_currencies()[1][0], 'CAD')
+
class TestPrice(amo.tests.TestCase):
fixtures = ['prices.json']
@@ -113,7 +126,7 @@ def test_get_tier_price(self):
def test_currencies(self):
currencies = Price.objects.get(pk=1).currencies()
eq_(len(currencies), 3)
- eq_(currencies[0][0], '') # This is USD.
+ eq_(currencies[0][0], 'USD')
eq_(currencies[1][1].currency, 'CAD')
View
@@ -99,9 +99,9 @@ def check_currencies(self):
if not price:
tiers = [('USD', '1.00')]
else:
- tiers = [('USD', price.price)]
- tiers += [(t.currency, t.price)
- for t in price._currencies.values()]
+ tiers = [(name, obj.price) for name, obj
+ in self.addon.premium.supported_currencies()]
+
else:
tiers = (('USD', '0.99'),)
@@ -110,6 +110,7 @@ def check_currencies(self):
self.test_paykey({'currency': currency,
'amount': amount,
'email': self.paypal_id})
+ log.info('Get paykey passed in %s' % currency)
except paypal.PaypalError:
msg = loc('Failed to make a test transaction '
'in %s.' % (currency))
@@ -17,9 +17,13 @@ def setUp(self):
self.addon.premium.paypal_permission_token = 'foo'
self.addon.premium.price.price = Decimal('1.00')
self.addon.premium.price._currencies = {}
+ self.usd = Mock()
+ self.usd.price = Decimal('1.0')
self.currency = Mock()
self.currency.currency = 'EUR'
self.currency.price = Decimal('0.5')
+ self.addon.premium.supported_currencies.return_value = (
+ ['USD', self.usd], ['EUR', self.currency])
self.check = Check(addon=self.addon)
def test_uses_addon(self):
@@ -70,7 +74,8 @@ def test_check_refund_no_premium(self):
@patch('paypal.get_paykey')
def test_check_paykey(self, get_paykey):
self.check.check_currencies()
- eq_(get_paykey.call_args[0][0]['currency'], 'USD')
+ eq_(get_paykey.call_args_list[0][0][0]['currency'], 'USD')
+ eq_(get_paykey.call_args_list[1][0][0]['currency'], 'EUR')
assert self.check.passed, self.check.state
@patch('paypal.get_paykey')
@@ -82,9 +87,6 @@ def test_check_paykey_no_premium(self, get_paykey):
@patch('paypal.get_paykey')
def test_check_paykey_currencies(self, get_paykey):
- self.addon.premium.price._currencies = {(u'EUR',
- self.addon.premium.price.id):
- self.currency}
self.check.check_currencies()
eq_(len(get_paykey.call_args_list), 2)
eq_([c[0][0]['currency'] for c in get_paykey.call_args_list],
@@ -100,7 +102,12 @@ def test_check_price_none(self, get_paykey):
@patch('paypal.get_paykey')
def test_check_paykey_fails(self, get_paykey):
- get_paykey.side_effect = PaypalError()
- self.check.check_currencies()
- assert not self.check.passed, self.check.state
- eq_(self.check.errors, ['Failed to make a test transaction in USD.'])
+ premium = self.addon.premium
+ for cr in ['USD', 'NaN']:
+ self.check = Check(addon=self.addon)
+ premium.supported_currencies.return_value = ([cr, self.usd],)
+ get_paykey.side_effect = PaypalError()
+ self.check.check_currencies()
+ assert not self.check.passed, self.check.state
+ eq_(self.check.errors,
+ ['Failed to make a test transaction in %s.' % cr])
@@ -21,7 +21,7 @@ exports.email_setup = function() {
$('#paypal-change-address-form').show();
});
// If you've submitted the form and there was an error, show the form.
- if ($('ul.errorlist').length) {
+ if ($('#paypal-change-address-form ul.errorlist').length) {
$('#paypal-change-address-form').show();
}
};
@@ -0,0 +1 @@
+ALTER TABLE addons_premium ADD COLUMN `currencies` longtext NOT NULL;
View
@@ -19,7 +19,7 @@
Preview)
from amo.utils import raise_required, remove_icons
from files.models import FileUpload
-from market.models import AddonPremium, Price, AddonPaymentData
+from market.models import AddonPaymentData, AddonPremium, Price, PriceCurrency
from mkt.site.forms import AddonChoiceField, APP_UPSELL_CHOICES
from mkt.inapp_pay.models import InappConfig
import paypal
@@ -548,3 +548,16 @@ def save(self, addon, commit=True):
(i.get_satisfaction_company,
i.get_satisfaction_product) = addons.forms.get_satisfaction(url)
return super(AppFormSupport, self).save(commit)
+
+
+class CurrencyForm(happyforms.Form):
+ currencies = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,
+ required=False,
+ label=_('Other currencies'))
+
+ def __init__(self, *args, **kw):
+ super(CurrencyForm, self).__init__(*args, **kw)
+ choices = (PriceCurrency.objects.values_list('currency', flat=True)
+ .distinct())
+ self.fields['currencies'].choices = [(k, amo.PAYPAL_CURRENCIES[k])
+ for k in choices]
@@ -16,26 +16,36 @@
<section class="primary payments devhub-form" role="main">
{% if addon.paypal_id %}
<div class="island">
- <p><strong>{{ loc('PayPal email address for this app.') }}</strong></p>
- <p class="indent">{{ addon.paypal_id }}
- <footer class="listing-footer">
- <a class="button" href="#" id="paypal-change-address">{{ loc('Change PayPal email') }}</a>
- <a class="button" href="{{ addon.get_dev_url('paypal_setup_details') }}">{{ loc('Manage contact details') }}</a>
- </footer>
+ <form method="post">
+ <p><strong>{{ loc('PayPal email address for this app') }}</strong></p>
+ <p class="indent">{{ addon.paypal_id }}
+ <a href="#paypal-account" id="paypal-change-address">Change</a></p>
+ {{ csrf() }}
+ <div class="brform paypal-inline paypal devhub-form">
+ {{ form_field(currency_form.currencies) }}
+ <span class="hint">{{ loc('The default is U.S. Dollar and support for this is required.
+ For each currency you would like to support for your price
+ tier, you must maintain a balance in PayPal.') }}</span>
+ </div>
+ <footer class="listing-footer">
+ <button type="submit" name="form" value="currency">{{ _('Change') }}</button>
+ <a class="button" href="{{ addon.get_dev_url('paypal_setup_details') }}">{{ loc('Manage contact details') }}</a>
+ </footer>
+ </form>
</div>
<div class="island js-hidden" id="paypal-change-address-form">
- <h2>Change your PayPal account</h2>
+ <h2><a name="paypal-account"></a>Change your PayPal account</h2>
<p>{{ loc('Changing your PayPal account will mean setting up permissions
tokens again on the Marketplace and updating your data.') }}</p>
<form method="post">
{{ csrf() }}
<div class="brform paypal-inline paypal devhub-form">
- {{ form_field(form.business_account) }}
- {{ form_field(form.email) }}
+ {{ form_field(paypal_form.business_account) }}
+ {{ form_field(paypal_form.email) }}
</div>
<footer class="listing-footer">
- <button type="submit">{{ _('Change') }}</button>
+ <button type="submit" name="form" value="paypal">{{ _('Change') }}</button>
</footer>
</form>
</div>
@@ -65,8 +75,8 @@
<p>{{ loc('Do you already have a PayPal Premier or business-level account?
If not we will redirect you to PayPal to create an account.
Return here when done to complete your setup.') }}</p>
- {{ form_field(form.business_account) }}
- {{ form_field(form.email) }}
+ {{ form_field(paypal_form.business_account) }}
+ {{ form_field(paypal_form.email) }}
<p>{{ loc('Learn about <a href="{0}">different PayPal account types</a>.')|f("https://www.paypal.com/cgi-bin/webscr?cmd=xpt/Marketing/general/PayPalAccountTypes-outside")|xssafe }}</p>
</div>
<footer class="listing-footer">
@@ -1,11 +1,13 @@
+from decimal import Decimal
+
from nose.tools import eq_
from pyquery import PyQuery as pq
from addons.models import Addon
import amo
import amo.tests
from amo.urlresolvers import reverse
-from market.models import Price, AddonPaymentData
+from market.models import AddonPaymentData, AddonPremium, Price, PriceCurrency
from users.models import UserProfile
@@ -92,6 +94,7 @@ def setUp(self):
self.client.login(username='admin@mozilla.com', password='password')
self.price = Price.objects.all()[0]
+ AddonPremium.objects.create(addon=self.webapp)
def get_webapp(self):
return Addon.objects.get(pk=337141)
@@ -108,6 +111,22 @@ def test_partial_submit(self):
res = self.client.get(self.url, follow=True)
self.assertRedirects(res, reverse('submit.app.terms'))
+ def test_currencies_fails(self):
+ self.webapp.update(premium_type=amo.ADDON_PREMIUM)
+ res = self.client.post(self.url, {'currencies': ['GBP', 'EUR'],
+ 'form': 'currency'})
+ eq_(res.status_code, 200)
+ self.assertFormError(res, 'currency_form', 'currencies',
+ [u'Select a valid choice. '
+ 'GBP is not one of the available choices.'])
+
+ def test_currencies_passes(self):
+ self.webapp.update(premium_type=amo.ADDON_PREMIUM)
+ res = self.client.post(self.url, {'currencies': ['EUR', 'BRL'],
+ 'form': 'currency'})
+ eq_(res.status_code, 302)
+ eq_(self.webapp.premium.currencies, ['EUR', 'BRL'])
+
class TestPaypalResponse(amo.tests.TestCase):
fixtures = ['base/apps', 'base/users', 'webapps/337141-steamcube']
Oops, something went wrong.

0 comments on commit 9fe93a7

Please sign in to comment.