From e78bbe83f94ddd3b1094ce6b9e8e060d63672ce5 Mon Sep 17 00:00:00 2001 From: Stuart Colville Date: Wed, 19 Jun 2013 13:47:43 +0000 Subject: [PATCH] Require in-app payment for free paid (bug 884680) --- media/js/devreg/payments.js | 13 +++++++++++ mkt/developers/forms_payments.py | 10 +++++++-- .../developers/payments/premium.html | 7 +++--- mkt/developers/tests/test_forms_payments.py | 14 ++++++++++++ mkt/developers/tests/test_views_payments.py | 22 ++++++++++++++----- mkt/developers/views_payments.py | 8 +++++++ 6 files changed, 63 insertions(+), 11 deletions(-) diff --git a/media/js/devreg/payments.js b/media/js/devreg/payments.js index 7caed57e94c..2e21807690d 100644 --- a/media/js/devreg/payments.js +++ b/media/js/devreg/payments.js @@ -78,11 +78,24 @@ define('payments', [], function() { var selectedPrice = $this.val() || ''; var apiUrl = format(pricesApiEndpoint, parseInt(selectedPrice, 10)); var disabledRegions = $regions.data('disabledRegions'); + var freeWithInAppId = $regions.data('freeWithInappId'); if (currentPrice == selectedPrice) { return; } + // If free with in-app is selected then make the 'No' radio disabled + // and hide it and make the allow_inapp a hidden field. + if (selectedPrice == freeWithInAppId) { + $('input[name=allow_inapp][value=True]').attr('type', 'hidden'); + $('input[name=allow_inapp][value=False]').prop('disabled', true) + .parent('label').hide(); + } else { + $('input[name=allow_inapp][value=True]').attr('type', 'radio'); + $('input[name=allow_inapp][value=False]').prop('disabled', false) + .parent('label').show(); + } + // Clear out existing price data. $regions.find('.local-retail').text(''); diff --git a/mkt/developers/forms_payments.py b/mkt/developers/forms_payments.py index 29e64f57ba4..16b3e9be0b7 100644 --- a/mkt/developers/forms_payments.py +++ b/mkt/developers/forms_payments.py @@ -108,7 +108,8 @@ def group_tier_choices(self): choice = (price.pk, unicode(price)) # Special case zero priced tier. if price.price == Decimal('0.00'): - price_choices.append((price.pk, _lazy('Free'))) + price_choices.append((price.pk, + _lazy('Free with in-app payments'))) # Tiers that can only be operator billed. elif price.method == PAYMENT_METHOD_OPERATOR: operator_billed.append(choice) @@ -128,7 +129,7 @@ def group_tier_choices(self): card_billed)) if card_and_operator_billed: price_choices.append( - (_lazy('Supports carrier billing and credit cards'), + (_lazy('Supports all billing methods'), card_and_operator_billed)) return price_choices @@ -200,6 +201,11 @@ def clean_price(self): raise ValidationError( self.fields['price'].error_messages['invalid_choice']) + if (price and price.price == Decimal('0.00') + and self.cleaned_data.get('allow_inapp') != 'True'): + raise ValidationError(_('If app is Free, ' + 'in-app payments must be enabled')) + return price def save(self): diff --git a/mkt/developers/templates/developers/payments/premium.html b/mkt/developers/templates/developers/payments/premium.html index 0205fbfec69..9619440b4a5 100644 --- a/mkt/developers/templates/developers/payments/premium.html +++ b/mkt/developers/templates/developers/payments/premium.html @@ -175,7 +175,8 @@

{{ _('Prices and countries') }}

+ data-pricelist-api-url="{{ api_pricelist_url }}" + data-free-with-inapp-id="{{ free_with_in_app_id }}"> {{ region_form.regions.errors }} @@ -189,8 +190,8 @@

{{ _('Prices and countries') }}

diff --git a/mkt/developers/tests/test_forms_payments.py b/mkt/developers/tests/test_forms_payments.py index aa590b12d75..cff7f6a18cf 100644 --- a/mkt/developers/tests/test_forms_payments.py +++ b/mkt/developers/tests/test_forms_payments.py @@ -61,6 +61,20 @@ def test_free_to_premium_pending(self): form.save() eq_(RereviewQueue.objects.count(), 0) + def test_free_with_in_app_requires_in_app(self): + self.make_premium(self.addon) + price = Price.objects.create(price='0.00') + self.platforms.update(price=price.pk, allow_inapp='False') + form = forms_payments.PremiumForm(self.platforms, **self.kwargs) + assert not form.is_valid() + + def test_paid_free_with_in_app(self): + self.make_premium(self.addon) + price = Price.objects.create(price='0.00') + self.platforms.update(price=price.pk, allow_inapp='True') + form = forms_payments.PremiumForm(self.platforms, **self.kwargs) + assert form.is_valid() + def test_premium_to_free(self): # Premium to Free is ok for public apps. self.make_premium(self.addon) diff --git a/mkt/developers/tests/test_views_payments.py b/mkt/developers/tests/test_views_payments.py index a31b4190b02..f3250528735 100644 --- a/mkt/developers/tests/test_views_payments.py +++ b/mkt/developers/tests/test_views_payments.py @@ -281,15 +281,25 @@ def test_check_api_url_in_context(self): def test_regions_display_free(self): self.webapp.update(premium_type=amo.ADDON_FREE) - r = self.client.get(self.url) - eq_(len(pq(r.content)('#regions-island')), 1), - eq_(len(pq(r.content)('#paid-regions-island')), 0), + res = self.client.get(self.url) + pqr = pq(res.content) + eq_(len(pqr('#regions-island')), 1), + eq_(len(pqr('#paid-regions-island')), 0), def test_regions_display_premium(self): self.webapp.update(premium_type=amo.ADDON_PREMIUM) - r = self.client.get(self.url) - eq_(len(pq(r.content)('#regions-island')), 0), - eq_(len(pq(r.content)('#paid-regions-island')), 1), + res = self.client.get(self.url) + pqr = pq(res.content) + eq_(len(pqr('#regions-island')), 0), + eq_(len(pqr('#paid-regions-island')), 1), + + def test_free_with_in_app_tier_id_in_context(self): + free_tier = Price.objects.create(price='0.00') + self.webapp.update(premium_type=amo.ADDON_PREMIUM) + res = self.client.get(self.url) + pqr = pq(res.content) + eq_(len(pqr('.regions[data-free-with-inapp-id]')), 1), + eq_(int(pqr('.regions').attr('data-free-with-inapp-id')), free_tier.pk) def test_premium_in_app_passes(self): self.webapp.update(premium_type=amo.ADDON_FREE) diff --git a/mkt/developers/views_payments.py b/mkt/developers/views_payments.py index 9996281a4f2..eb3721fe849 100644 --- a/mkt/developers/views_payments.py +++ b/mkt/developers/views_payments.py @@ -22,6 +22,7 @@ from lib.crypto import generate_key from lib.pay_server import client +from market.models import Price from mkt.constants import DEVICE_LOOKUP from mkt.developers.decorators import dev_required from mkt.developers.models import (AddonPaymentAccount, PaymentAccount, @@ -118,10 +119,17 @@ def payments(request, addon_id, addon, webapp=False): [('android-mobile', True), ('android-tablet', True), ('desktop', True), ('firefoxos', False)])) + try: + free_with_in_app_id = Price.objects.get(price='0.00', + active=True).pk + except Price.DoesNotExist: + free_with_in_app_id = '' + return jingo.render( request, 'developers/payments/premium.html', {'addon': addon, 'webapp': webapp, 'premium': addon.premium, 'form': premium_form, 'upsell_form': upsell_form, + 'free_with_in_app_id': free_with_in_app_id, 'region_form': region_form, 'DEVICE_LOOKUP': DEVICE_LOOKUP, 'is_paid': addon.premium_type in amo.ADDON_PREMIUMS,
+ {%- if value in region_form.initial.regions %} checked {% endif -%} + name="regions" value="{{ value }}">{{ text }}