Merge pull request #1095 from muffinresearch/remove-region-restriction-paid
Don't restrict regions for paid (bug 904157)
This commit is contained in:
Коммит
1bb5a3816b
|
@ -437,7 +437,7 @@ label.disabled {
|
|||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.regions {
|
||||
.devhub-form table .regions {
|
||||
.region-heading {
|
||||
display: block;
|
||||
hidetext();
|
||||
|
@ -449,4 +449,25 @@ label.disabled {
|
|||
td .local-retail {
|
||||
display: block;
|
||||
}
|
||||
table td {
|
||||
line-height: 1.5em;
|
||||
min-height: 1.5em;
|
||||
padding: 1em 0;
|
||||
}
|
||||
}
|
||||
|
||||
.paid-regions {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
body > label {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.note p:only-child {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.region-choices li {
|
||||
min-height: 19px;
|
||||
}
|
||||
|
|
|
@ -5,16 +5,18 @@ define('payments', [], function() {
|
|||
var $regions = $('#region-list');
|
||||
var $regionsIsland = $('#regions');
|
||||
var $regionCheckboxes = $regions.find('input[type=checkbox]');
|
||||
var $regionsChangedWarning = $('#regions-changed');
|
||||
var $regionsInappropriateWarning = $('#regions-inappropriate');
|
||||
var $before = $regions.find('input[type=checkbox]:disabled');
|
||||
|
||||
var apiErrorMsg = $regions.data('apiErrorMsg');
|
||||
var disabledGeneralRegions = $regions.data('disabledGeneralRegions');
|
||||
var tierZeroId = $regions.data('tierZeroId');
|
||||
var notApplicableMsg = $regions.data('notApplicableMsg');
|
||||
var paymentMethods = $regions.data('paymentMethods') || {};
|
||||
var pricesApiEndpoint = $regions.data('pricelistApiUrl') + '{0}/';
|
||||
var regionsData = $regions.data();
|
||||
|
||||
var allPaidRegionIds = regionsData.allPaidRegionIds;
|
||||
var apiErrorMsg = regionsData.apiErrorMsg;
|
||||
var disabledRegions = regionsData.disabledRegions;
|
||||
var tierZeroId = regionsData.tierZeroId;
|
||||
var notApplicableMsg = regionsData.notApplicableMsg;
|
||||
var paymentMethods = regionsData.paymentMethods || {};
|
||||
var pricesApiEndpoint = regionsData.pricelistApiUrl + '{0}/';
|
||||
var $tdNodes = $('<td class="cb"></td><td class="lp"></td><td class="lm"></td>');
|
||||
var $paidRegionTableTbody = $('#paid-regions tbody');
|
||||
|
||||
function getOverlay(opts) {
|
||||
var id = opts;
|
||||
|
@ -83,6 +85,42 @@ define('payments', [], function() {
|
|||
}));
|
||||
}
|
||||
|
||||
function moveAnimate(element, newParent, $elmToRemove, zIndex) {
|
||||
zIndex = zIndex || 100;
|
||||
var $element = $(element);
|
||||
var $newParent = $(newParent);
|
||||
var oldOffset = $element.offset();
|
||||
|
||||
$element.appendTo($newParent);
|
||||
var newOffset = $element.offset();
|
||||
var $temp = $element.clone().appendTo('body');
|
||||
$temp.css({'position': 'absolute',
|
||||
'left': oldOffset.left,
|
||||
'top': oldOffset.top,
|
||||
'zIndex': zIndex});
|
||||
|
||||
element.hide();
|
||||
$temp.animate({'top': parseInt(newOffset.top, 10), 'left': parseInt(newOffset.left, 10) }, 'slow', function(){
|
||||
$temp.remove();
|
||||
$element.show();
|
||||
if ($elmToRemove) {
|
||||
$elmToRemove.hide(500, function() { this.remove(); });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createTableRow(checkBox, ident, localPriceText, localMethodText) {
|
||||
var $tds = $tdNodes.clone();
|
||||
var $tr = $paidRegionTableTbody.find('tr[data-region="' + ident + '"]');
|
||||
var $checkBoxContainer = $($tds[0]);
|
||||
var $localPriceContainer = $($tds[1]);
|
||||
var $localMethodContainer = $($tds[2]);
|
||||
$localMethodContainer.text(localMethodText);
|
||||
$localPriceContainer.text(localPriceText);
|
||||
$tr.append($tds);
|
||||
return $tr;
|
||||
}
|
||||
|
||||
function disableCheckbox() {
|
||||
/*jshint validthis:true */
|
||||
var $this = $(this);
|
||||
|
@ -94,57 +132,14 @@ define('payments', [], function() {
|
|||
$this.closest('tr').find('.local-retail, .local-method').text('');
|
||||
}
|
||||
|
||||
function compareDisabledCheckboxes($before) {
|
||||
var hasChanged = false;
|
||||
var $after = $regions.find('input[type=checkbox]:disabled');
|
||||
|
||||
if ($before.length && $after.length && $before.length === $after.length) {
|
||||
$after.each(function() {
|
||||
// If current element isn't in $before the state has changed and we can
|
||||
// exit the each.
|
||||
var beforeIndex = $.inArray(this, $before);
|
||||
if (beforeIndex === -1) {
|
||||
hasChanged = true;
|
||||
return false;
|
||||
// As soon as a disabled prop doesn't match flag the change and exit each.
|
||||
} else if ($(this).prop('disabled') !== $($before[beforeIndex]).prop('disabled')) {
|
||||
hasChanged = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else if (($before.length || $after.length) && $before.length !== $after.length) {
|
||||
hasChanged = true;
|
||||
}
|
||||
if (hasChanged) {
|
||||
$regionsChangedWarning.removeClass('hidden');
|
||||
} else {
|
||||
$regionsChangedWarning.addClass('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function updatePrices(checkForChanges) {
|
||||
function updatePrices() {
|
||||
|
||||
/*jshint validthis:true */
|
||||
var $this = $(this);
|
||||
var selectedPrice = $this.val();
|
||||
|
||||
checkForChanges = checkForChanges === false ? checkForChanges : true;
|
||||
|
||||
// Check for NaN which will be caused by selectedPrice being ''.
|
||||
if (selectedPrice != 'free') {
|
||||
selectedPrice = parseInt(selectedPrice, 10);
|
||||
selectedPrice = isNaN(selectedPrice) ? false : selectedPrice;
|
||||
}
|
||||
|
||||
// No-op if nothing has changed.
|
||||
if (currentPrice === selectedPrice) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle the 'Please select a price' case.
|
||||
if (selectedPrice === false) {
|
||||
$regionCheckboxes.each(disableCheckbox);
|
||||
currentPrice = selectedPrice;
|
||||
if (!selectedPrice) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -154,73 +149,80 @@ define('payments', [], function() {
|
|||
$('input[name=allow_inapp][value=True]').prop('checked', true);
|
||||
$('input[name=allow_inapp][value=False]').prop('disabled', true)
|
||||
.parent('label').hide();
|
||||
|
||||
// Enable all the checkboxes save for those that should be disabled.
|
||||
// e.g. unrated games in Brazil.
|
||||
$regionCheckboxes.each(function() {
|
||||
$this = $(this);
|
||||
if (disabledGeneralRegions.indexOf(parseInt($this.prop('value'), 10)) === -1) {
|
||||
$this.prop('disabled', false).closest('label').removeClass('disabled')
|
||||
.closest('tr').find('.local-method, .local-retail')
|
||||
.text(notApplicableMsg);
|
||||
} else {
|
||||
disableCheckbox.call(this);
|
||||
}
|
||||
});
|
||||
$('#paid-upsell-island').hide();
|
||||
currentPrice = selectedPrice;
|
||||
|
||||
if (checkForChanges) {
|
||||
compareDisabledCheckboxes($before);
|
||||
}
|
||||
return;
|
||||
// For free apps we are using the same data for tier zero apps
|
||||
// to populate the region list.
|
||||
selectedPrice = tierZeroId;
|
||||
} else {
|
||||
$('#paid-upsell-island').show();
|
||||
$('input[name=allow_inapp][value=False]').prop('disabled', false)
|
||||
.parent('label').show();
|
||||
}
|
||||
|
||||
// From here on numbers should be used.
|
||||
selectedPrice = parseInt(selectedPrice, 10);
|
||||
|
||||
// No-op if nothing else has changed.
|
||||
if (currentPrice === selectedPrice) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: format(pricesApiEndpoint, selectedPrice),
|
||||
beforeSend: function() {
|
||||
$regionsIsland.addClass('loading');
|
||||
},
|
||||
success: function(data) {
|
||||
var moveQueue = [];
|
||||
var prices = data.prices || [];
|
||||
var tierPrice = data.price;
|
||||
var seen = [];
|
||||
var tierPrice = data.price;
|
||||
|
||||
// Iterate over the prices for the regions
|
||||
for (var i=0, j=prices.length; i<j; i++) {
|
||||
var price = prices[i];
|
||||
var region = price.region;
|
||||
var regionId = price.region;
|
||||
var billingMethodText = paymentMethods[parseInt(price.method, 10)] || '';
|
||||
var $chkbox = $regions.find('input:checkbox[value=' + region + ']');
|
||||
|
||||
// Skip if over regions that should be disabled e.g an unrated games app in Brazil.
|
||||
if (disabledGeneralRegions.indexOf(region) > -1) {
|
||||
continue;
|
||||
var localPrice = price.price + ' ' + price.currency;
|
||||
var localMethod = selectedPrice === tierZeroId ? notApplicableMsg : billingMethodText;
|
||||
|
||||
// If the checkbox we're interested is already in the table just update it.
|
||||
// Otherwise we need to create a new tableRow and move it into position.
|
||||
var $chkbox = $regions.find('input:checkbox[value=' + regionId + ']');
|
||||
var $row = $('#paid-regions tr[data-region=' + regionId + ']');
|
||||
if ($row.find('td').length) {
|
||||
$row.find('.lp').text(localPrice);
|
||||
$row.find('.lm').text(localMethod);
|
||||
} else {
|
||||
var $tr = createTableRow($chkbox.closest('label'), regionId, localPrice, localMethod);
|
||||
moveQueue.push([$chkbox.closest('label'), $tr.find('.cb')]);
|
||||
$chkbox.closest('li').hide(500);
|
||||
}
|
||||
// Enable checkboxes for those that we have price info for.
|
||||
$chkbox.prop('disabled', false)
|
||||
.closest('label').removeClass('disabled');
|
||||
|
||||
var $tr = $chkbox.closest('tr');
|
||||
|
||||
$tr.find('.local-retail')
|
||||
.text(price.price + ' ' + price.currency);
|
||||
|
||||
$tr.find('.local-method')
|
||||
.text(selectedPrice === tierZeroId ? notApplicableMsg : billingMethodText);
|
||||
|
||||
seen.push($chkbox[0]);
|
||||
|
||||
}
|
||||
// Disable everything else.
|
||||
$regionCheckboxes.not(seen).each(disableCheckbox);
|
||||
|
||||
if (checkForChanges) {
|
||||
compareDisabledCheckboxes($before);
|
||||
for (var k=0, l=moveQueue.length; k<l; k++) {
|
||||
var current = moveQueue[k];
|
||||
moveAnimate(current[0], current[1]);
|
||||
}
|
||||
|
||||
$('#paid-regions input[type=checkbox]').not(seen).each(function() {
|
||||
// If the item we don't want here is in the table then we need to move it back
|
||||
// out of the table and destroy the row contents.
|
||||
var $chkbox = $(this);
|
||||
var region = $chkbox.val();
|
||||
|
||||
// Lookup the location of the original checkbox so we know where to send this back to
|
||||
var $newParent = $('.checkbox-choices li[data-region=' + region + ']');
|
||||
$newParent.show(500);
|
||||
var $label = $chkbox.closest('label');
|
||||
if ($label.length) {
|
||||
var $tds = $chkbox.closest('tr').find('td');
|
||||
moveAnimate($label, $newParent, $tds);
|
||||
}
|
||||
});
|
||||
},
|
||||
dataType: "json"
|
||||
}).fail(function() {
|
||||
|
@ -250,7 +252,7 @@ define('payments', [], function() {
|
|||
// Only update if we can edit. If the user can't edit all fields will be disabled.
|
||||
if (!z.body.hasClass('no-edit')) {
|
||||
$priceSelect.on('change', updatePrices);
|
||||
updatePrices.call($priceSelect[0], false);
|
||||
updatePrices.call($priceSelect[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -200,12 +200,15 @@ REGIONS_CHOICES = (
|
|||
|
||||
BY_SLUG = sorted([v for k, v in DEFINED if v.id and v.weight > -1],
|
||||
key=lambda v: v.slug)
|
||||
|
||||
REGIONS_CHOICES_SLUG = ([('worldwide', WORLDWIDE)] +
|
||||
[(v.slug, v) for v in BY_SLUG])
|
||||
REGIONS_CHOICES_ID = ([(WORLDWIDE.id, WORLDWIDE)] +
|
||||
[(v.id, v) for v in BY_SLUG])
|
||||
REGIONS_CHOICES_NAME = ([(WORLDWIDE.id, WORLDWIDE.name)] +
|
||||
[(v.id, v.name) for v in BY_SLUG])
|
||||
# Worldwide last here so we can display it after all the other regions.
|
||||
REGIONS_CHOICES_NAME = ([(v.id, v.name) for v in BY_SLUG] +
|
||||
[(WORLDWIDE.id, WORLDWIDE.name)])
|
||||
|
||||
|
||||
REGIONS_DICT = dict(REGIONS_CHOICES)
|
||||
REGIONS_CHOICES_ID_DICT = dict(REGIONS_CHOICES_ID)
|
||||
|
@ -214,4 +217,9 @@ ALL_PAID_REGIONS = frozenset(r for r in ALL_REGIONS if r.has_payments)
|
|||
|
||||
ALL_REGION_IDS = sorted(REGIONS_CHOICES_ID_DICT.keys())
|
||||
ALL_PAID_REGION_IDS = sorted(r.id for r in ALL_PAID_REGIONS)
|
||||
ALL_PAID_REGIONS_BY_SLUG = sorted(ALL_PAID_REGIONS,
|
||||
key=lambda x: getattr(x, 'slug', None))
|
||||
ALL_PAID_REGION_IDS_BY_SLUG = [r.id for r in ALL_PAID_REGIONS_BY_SLUG]
|
||||
|
||||
# Regions not including worldwide.
|
||||
REGION_IDS = sorted(REGIONS_CHOICES_ID_DICT.keys())[1:]
|
||||
|
|
|
@ -44,7 +44,6 @@ from mkt.constants import MAX_PACKAGED_APP_SIZE
|
|||
from mkt.constants.ratingsbodies import (ALL_RATINGS, RATINGS_BODIES,
|
||||
RATINGS_BY_NAME)
|
||||
from mkt.site.forms import AddonChoiceField
|
||||
from mkt.regions import ALL_PAID_REGION_IDS, ALL_REGION_IDS
|
||||
from mkt.webapps.models import AddonExcludedRegion, ContentRating, Webapp
|
||||
from mkt.webapps.tasks import index_webapps
|
||||
from mkt.zadmin.models import FeaturedApp
|
||||
|
@ -669,105 +668,44 @@ class AppAppealForm(happyforms.Form):
|
|||
class RegionForm(forms.Form):
|
||||
regions = forms.MultipleChoiceField(required=False,
|
||||
label=_lazy(u'Choose the regions your app will be listed in:'),
|
||||
choices=mkt.regions.REGIONS_CHOICES_NAME[1:],
|
||||
choices=mkt.regions.REGIONS_CHOICES_NAME,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
error_messages={'required':
|
||||
_lazy(u'You must select at least one region.')})
|
||||
other_regions = forms.BooleanField(required=False, initial=True,
|
||||
label=_lazy(u'Other and new regions'))
|
||||
enable_new_regions = forms.BooleanField(required=False,
|
||||
label=_lazy(u'Enable new regions'))
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
self.product = kw.pop('product', None)
|
||||
self.request = kw.pop('request', None)
|
||||
self.price = kw.pop('price', None)
|
||||
self.region_ids = self.product.get_region_ids()
|
||||
self.region_ids = self.product.get_region_ids(worldwide=True)
|
||||
super(RegionForm, self).__init__(*args, **kw)
|
||||
|
||||
# Initialise the price for free_inapp.
|
||||
if not self.price and self.product and self.product.is_free_inapp():
|
||||
self.price = 'free'
|
||||
|
||||
is_paid = self._product_is_paid()
|
||||
|
||||
# If we have excluded regions, uncheck those.
|
||||
# Otherwise, default to everything checked.
|
||||
self.regions_before = self.product.get_region_ids()
|
||||
self.regions_before = self.product.get_region_ids(worldwide=True)
|
||||
|
||||
# If we have future excluded regions, uncheck box.
|
||||
# Note: this is currently only relevant for non-paid apps.
|
||||
self.future_exclusions = self.product.addonexcludedregion.filter(
|
||||
region=mkt.regions.WORLDWIDE.id)
|
||||
self.future_exclusions = self.product.enable_new_regions
|
||||
|
||||
self.initial = {
|
||||
'regions': self.regions_before,
|
||||
'enable_new_regions': self.product.enable_new_regions,
|
||||
}
|
||||
|
||||
# If the app is paid, disable regions that use payments.
|
||||
if is_paid:
|
||||
|
||||
# For paid apps enabling new regions is not based on the worldwide
|
||||
# region it's based on enable_new_regions.
|
||||
self.fields['other_regions'].label = _(u'Enable new regions')
|
||||
self.initial['other_regions'] = self.product.enable_new_regions
|
||||
|
||||
# Premium form was valid.
|
||||
if self.price and self.price != 'free':
|
||||
self.price_region_ids = (self.price.pricecurrency_set
|
||||
.values_list('region', flat=True))
|
||||
# Free app with in-app payments for this we just want to make
|
||||
# sure it's in a region that allows payments.
|
||||
# self.price is intialised above for free_inapp even if
|
||||
# this isn't a post.
|
||||
elif self.price and self.price == 'free':
|
||||
self.price_region_ids = ALL_PAID_REGION_IDS
|
||||
# Premium form wasn't valid and it is a POST. Since we can't
|
||||
# determine what price they wanted, just make sure it isn't a
|
||||
# disabled price.
|
||||
elif self.data:
|
||||
self.price_region_ids = []
|
||||
# Not a post, we can trust the price on the product.
|
||||
else:
|
||||
self.price_region_ids = (self.product
|
||||
.get_possible_price_region_ids())
|
||||
|
||||
else:
|
||||
# Set initial of other_regions for non-paid apps.
|
||||
self.initial['other_regions'] = (not
|
||||
self.future_exclusions.exists())
|
||||
|
||||
# These are split out so we can distinguish regions that are totally
|
||||
# disabled vs those that are disabled based on price.
|
||||
self.disabled_general_regions = sorted(
|
||||
self._disabled_general_regions())
|
||||
self.disabled_regions = sorted(self._disabled_regions())
|
||||
|
||||
def _disabled_regions(self):
|
||||
"""All disabled regions (varys based on current price)."""
|
||||
return self._disabled_general_regions().union(
|
||||
self._disabled_paid_regions())
|
||||
|
||||
def _disabled_general_regions(self):
|
||||
"""Regions that are disabled for general reasons."""
|
||||
disabled_general_regions = set()
|
||||
disabled_regions = set()
|
||||
|
||||
# Games cannot be listed in Brazil without a content rating.
|
||||
games = Webapp.category('games')
|
||||
if (games and
|
||||
self.product.categories.filter(id=games.id).exists() and
|
||||
not self.product.content_ratings_in(mkt.regions.BR)):
|
||||
disabled_general_regions.add(mkt.regions.BR.id)
|
||||
disabled_regions.add(mkt.regions.BR.id)
|
||||
|
||||
return disabled_general_regions
|
||||
|
||||
def _disabled_paid_regions(self):
|
||||
"""Regions disabled based on current price."""
|
||||
dpr = set()
|
||||
if self._product_is_paid():
|
||||
# Ensure price_regions are in ALL_PAID_REGION_IDS.
|
||||
valid_price_regions = (set(self.price_region_ids).intersection(
|
||||
set(ALL_PAID_REGION_IDS)))
|
||||
dpr = set(ALL_REGION_IDS).difference(valid_price_regions)
|
||||
return dpr
|
||||
return disabled_regions
|
||||
|
||||
def is_toggling(self):
|
||||
if not self.request or not hasattr(self.request, 'POST'):
|
||||
|
@ -779,29 +717,11 @@ class RegionForm(forms.Form):
|
|||
return (self.product.premium_type in amo.ADDON_PREMIUMS
|
||||
or self.product.premium_type == amo.ADDON_FREE_INAPP)
|
||||
|
||||
def has_inappropriate_regions(self):
|
||||
"""Returns whether the app is listed in regions that it shouldn't
|
||||
otherwise be registered in."""
|
||||
|
||||
if self._product_is_paid():
|
||||
return set(self.region_ids).intersection(
|
||||
set(self.disabled_regions))
|
||||
|
||||
def clean(self):
|
||||
data = self.cleaned_data
|
||||
if (not data.get('regions') and not data.get('other_regions')
|
||||
and not self.is_toggling()):
|
||||
if (not data.get('regions') and not self.is_toggling()):
|
||||
raise forms.ValidationError(
|
||||
_('You must select at least one region or '
|
||||
'"Other and new regions."'))
|
||||
|
||||
if data.get('regions'):
|
||||
self.region_ids = [int(r) for r in data['regions']]
|
||||
if self.has_inappropriate_regions():
|
||||
raise forms.ValidationError(
|
||||
_('You have selected a region that is not valid for your '
|
||||
'price point.'))
|
||||
|
||||
_('You must select at least one region.'))
|
||||
return data
|
||||
|
||||
def save(self):
|
||||
|
@ -812,10 +732,6 @@ class RegionForm(forms.Form):
|
|||
before = set(self.regions_before)
|
||||
after = set(map(int, self.cleaned_data['regions']))
|
||||
|
||||
# If the app is paid, disable regions that do not use payments.
|
||||
if self._product_is_paid():
|
||||
after &= set(self.price_region_ids)
|
||||
|
||||
# Add new region exclusions.
|
||||
to_add = before - after
|
||||
for r in to_add:
|
||||
|
@ -832,33 +748,14 @@ class RegionForm(forms.Form):
|
|||
log.info(u'[Webapp:%s] No longer exluded from region (%s).'
|
||||
% (self.product, r))
|
||||
|
||||
if self.cleaned_data['other_regions']:
|
||||
|
||||
# For a paid app enable_new_regions is distinct from
|
||||
# the worldwide region.
|
||||
if self._product_is_paid():
|
||||
self.product.update(enable_new_regions=True)
|
||||
log.info(u'[Webapp:%s] will be added to future regions.'
|
||||
% self.product)
|
||||
else:
|
||||
# Developer wants to be visible in future regions, then
|
||||
# delete excluded regions.
|
||||
self.future_exclusions.delete()
|
||||
log.info(u'[Webapp:%s] No longer excluded from future regions.'
|
||||
if self.cleaned_data['enable_new_regions']:
|
||||
self.product.update(enable_new_regions=True)
|
||||
log.info(u'[Webapp:%s] will be added to future regions.'
|
||||
% self.product)
|
||||
else:
|
||||
if self._product_is_paid():
|
||||
self.product.update(enable_new_regions=False)
|
||||
log.info(u'[Webapp:%s] will not be added to future regions.'
|
||||
self.product.update(enable_new_regions=False)
|
||||
log.info(u'[Webapp:%s] will not be added to future regions.'
|
||||
% self.product)
|
||||
else:
|
||||
# Developer does not want future regions, then
|
||||
# exclude all future apps.
|
||||
g, c = AddonExcludedRegion.objects.get_or_create(
|
||||
addon=self.product, region=mkt.regions.WORLDWIDE.id)
|
||||
if c:
|
||||
log.info(u'[Webapp:%s] Excluded from future regions.'
|
||||
% self.product)
|
||||
|
||||
ban_game_in_brazil(self.product)
|
||||
|
||||
|
|
|
@ -104,7 +104,6 @@ class PremiumForm(DeviceTypeForm, happyforms.Form):
|
|||
def group_tier_choices(self):
|
||||
"""Creates tier choices with optgroups based on payment methods"""
|
||||
price_choices = [
|
||||
('', _('Please select a price')),
|
||||
('free', _('Free (with in-app payments)')),
|
||||
]
|
||||
card_billed = []
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
from optparse import make_option
|
||||
|
||||
from django.core.management.base import BaseCommand, CommandError
|
||||
|
||||
import amo
|
||||
from mkt.developers.forms import RegionForm
|
||||
from mkt.regions import ALL_REGION_IDS, REGIONS_CHOICES_ID_DICT
|
||||
from mkt.webapps.models import AddonExcludedRegion as AER, Webapp
|
||||
|
||||
ALL_REGIONS = set(ALL_REGION_IDS)
|
||||
DIVIDER = '-' * 28
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
args = '<app_slug>'
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option('--exclude_region_by_id', action='store',
|
||||
type='int', dest='exclude_region_id',
|
||||
help='Adds an exclusion record for a region by id'),
|
||||
make_option('--include_region_by_id', action='store',
|
||||
type='int', dest='include_region_id',
|
||||
help='Removes an exclusion record for a region by id'),
|
||||
)
|
||||
help = ('Check regions for a given paid app and flag if they have '
|
||||
'incorrect regions.')
|
||||
|
||||
def _region_obj(self, id_):
|
||||
return REGIONS_CHOICES_ID_DICT.get(id_)
|
||||
|
||||
def _region_name(self, id_):
|
||||
region_obj_ = self._region_obj(id_)
|
||||
return unicode(region_obj_.name)
|
||||
|
||||
def write_output(self, value=''):
|
||||
self.stdout.write(value + '\n')
|
||||
|
||||
def write_error(self, value=''):
|
||||
self.stderr.write(value + '\n')
|
||||
|
||||
def get_regions(self, app):
|
||||
region_excludes = (AER.objects.filter(addon=app)
|
||||
.values_list('region', flat=True))
|
||||
return ALL_REGIONS.difference(region_excludes)
|
||||
|
||||
def get_bad_regions(self, app, regions):
|
||||
# Initialise RegionForm so we can get the disabled region data
|
||||
# based on our app.
|
||||
|
||||
if app.premium_type == amo.ADDON_FREE_INAPP:
|
||||
price = 'free'
|
||||
else:
|
||||
price = app.premium.price
|
||||
|
||||
region_form = RegionForm(data={'regions': regions},
|
||||
product=app, price=price)
|
||||
|
||||
# We manually construct bad_regions so we can make sure we catch
|
||||
# worldwide regions (Worldwide is not a valid choice in the form).
|
||||
return regions.intersection(region_form.disabled_regions)
|
||||
|
||||
def exclude_region(self, app, app_slug, exclude_region_id):
|
||||
aer, created = AER.objects.get_or_create(addon=app,
|
||||
region=exclude_region_id)
|
||||
if not created:
|
||||
self.write_error('Could not create exclusion record for '
|
||||
'region_id %s (%s). It already exists' % (
|
||||
exclude_region_id,
|
||||
self._region_name(exclude_region_id)))
|
||||
else:
|
||||
self.write_output('')
|
||||
self.write_output("Excluding from region_id %s (%s) for "
|
||||
"app '%s'" % (exclude_region_id,
|
||||
self._region_name(exclude_region_id),
|
||||
app_slug))
|
||||
self.include_exclude_region = True
|
||||
|
||||
def include_region(self, app, app_slug, include_region_id):
|
||||
self.write_output()
|
||||
self.write_output("Including from region_id %s (%s) for app "
|
||||
"'%s'" % (include_region_id,
|
||||
self._region_name(include_region_id),
|
||||
app_slug))
|
||||
try:
|
||||
aer = AER.objects.get(addon=app, region=include_region_id)
|
||||
aer.delete()
|
||||
self.include_exclude_region = True
|
||||
except AER.DoesNotExist:
|
||||
self.write_error('Could not remove exclusion record for '
|
||||
'region_id %s (%s)' % (include_region_id,
|
||||
self._region_name(include_region_id)))
|
||||
|
||||
def output_regions(self, app, app_slug):
|
||||
regions = self.get_regions(app)
|
||||
bad_regions = self.get_bad_regions(app, regions)
|
||||
|
||||
self.write_output('App Slug: %s' % app_slug)
|
||||
self.write_output('App Status: %s' % unicode(
|
||||
amo.STATUS_CHOICES.get(app.status)))
|
||||
self.write_output('App Id: %s' % app.pk)
|
||||
self.write_output(DIVIDER)
|
||||
self.write_output('id | region.name')
|
||||
self.write_output(DIVIDER)
|
||||
|
||||
has_bad_region = False
|
||||
for region_id in regions:
|
||||
region_name = self._region_name(region_id)
|
||||
asterisk = ''
|
||||
if region_id in bad_regions:
|
||||
has_bad_region = True
|
||||
asterisk = ' *'
|
||||
|
||||
self.write_output('%s | %s%s' % (str(region_id).ljust(2),
|
||||
region_name, asterisk))
|
||||
|
||||
if has_bad_region:
|
||||
self.write_output('* Inappropriate region')
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.include_exclude_region = False
|
||||
|
||||
if not args:
|
||||
raise CommandError('An app_slug is required.')
|
||||
|
||||
if len(args) > 1:
|
||||
raise CommandError('Only a single app_slug is accepted.')
|
||||
|
||||
app_slug = args[0]
|
||||
|
||||
# Look up the app by slug.
|
||||
try:
|
||||
app = Webapp.objects.get(app_slug=app_slug,
|
||||
premium_type__in=amo.ADDON_HAS_PAYMENTS)
|
||||
except Webapp.DoesNotExist:
|
||||
raise CommandError('Paid app with slug %s not '
|
||||
'found.' % app_slug)
|
||||
|
||||
# Bail if the app doesn't have a price.
|
||||
if (app.premium_type != amo.ADDON_FREE_INAPP and
|
||||
not app.has_premium() and
|
||||
not getattr('app.premium', 'price', False)):
|
||||
raise CommandError("App %s doesn't have a price" % app_slug)
|
||||
|
||||
# Outputs the region info.
|
||||
self.output_regions(app, app_slug)
|
||||
|
||||
# Handle including a region by deleting an exlusion record for the app.
|
||||
include_region_id = options.get('include_region_id')
|
||||
if include_region_id:
|
||||
self.include_region(app, app_slug, include_region_id)
|
||||
|
||||
# Handle an exclusions record by adding an exclusion record for
|
||||
# the app.
|
||||
exclude_region_id = options.get('exclude_region_id')
|
||||
if exclude_region_id:
|
||||
self.exclude_region(app, app_slug, exclude_region_id)
|
||||
|
||||
# If we've include/excluded a region show the regions now.
|
||||
if self.include_exclude_region:
|
||||
self.write_output()
|
||||
self.write_output('Regions are now as follows:')
|
||||
self.output_regions(app, app_slug)
|
|
@ -0,0 +1,20 @@
|
|||
{{ region_form.regions.errors }}
|
||||
<div class="checkbox-choices region-choices"{% if not is_paid %} id="region-list" data-disabled-regions="{{ region_form.disabled_regions|json }}"{% endif %}>
|
||||
<ul>
|
||||
{% for value, text in region_form.regions.field.choices %}
|
||||
<li data-region="{{ value }}">
|
||||
<label class="region-cb{% if value in region_form.disabled_regions %} disabled{% endif %}">
|
||||
<input type="checkbox"
|
||||
{% if value in region_form.disabled_regions %}disabled{% endif %}
|
||||
{% if value in region_form.initial.regions %}checked{% endif %}
|
||||
name="regions" value="{{ value }}">{{ text }}</label>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% if region_form.disabled_regions %}
|
||||
{% include 'developers/payments/includes/regions_disabled.html' %}
|
||||
{% endif %}
|
||||
<div class="other-regions">
|
||||
{% include 'developers/payments/includes/regions_other.html' %}
|
||||
</div>
|
|
@ -1,20 +1,10 @@
|
|||
{{ region_form.other_regions }}
|
||||
{{ region_form.other_regions.label_tag() }}
|
||||
{{ region_form.other_regions.errors }}
|
||||
{{ region_form.enable_new_regions }}
|
||||
{{ region_form.enable_new_regions.label_tag() }}
|
||||
{{ region_form.enable_new_regions.errors }}
|
||||
<div class="hint note">
|
||||
{% if region_form._product_is_paid() %}
|
||||
{%- trans %}
|
||||
Your app will be displayed in any regional Marketplace that is
|
||||
added in the future.
|
||||
You will receive an email notification when a new region
|
||||
is added.
|
||||
{% endtrans -%}
|
||||
{% else %}
|
||||
{%- trans %}
|
||||
Your app will be displayed in the worldwide Marketplace and
|
||||
in any regional Marketplace that is added in the future.
|
||||
You will receive an email notification when a new region
|
||||
is added.
|
||||
{% endtrans -%}
|
||||
{% endif %}
|
||||
{{ _('Your app will be displayed in any regional Marketplace that is added in the future.')}}
|
||||
{% if region_form._product_is_paid() %}
|
||||
<em>{{ _('(Subject to payments being available in that region for the selected price point).') }}</em>
|
||||
{% endif %}
|
||||
{{ _('You will receive an email notification when a new region is added.') }}
|
||||
</div>
|
||||
|
|
|
@ -144,17 +144,6 @@
|
|||
<div id="paid-regions-island">
|
||||
<h2>{{ _('Prices and countries') }}</h2>
|
||||
|
||||
{% if region_form.has_inappropriate_regions() %}
|
||||
{% include 'developers/payments/includes/regions_inappropriate.html' %}
|
||||
{% endif %}
|
||||
|
||||
<div class="island info hidden" id="regions-changed">
|
||||
{%- trans %}
|
||||
Based on your chosen price point the available regions have been updated.
|
||||
Please check them prior to saving your changes.
|
||||
{% endtrans -%}
|
||||
</div>
|
||||
|
||||
<section id="regions" class="island">
|
||||
<table>
|
||||
<tbody>
|
||||
|
@ -175,63 +164,57 @@
|
|||
{{ form.allow_inapp }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="2" class="region-toggle">
|
||||
{% include 'developers/payments/includes/regions_toggle.html' %}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2" class="region-container">
|
||||
<div id="region-list" class="checkbox-choices regions"
|
||||
data-api-error-msg="{{ _('A server error occurred. Please try again later.') }}"
|
||||
data-disabled-general-regions="{{ region_form.disabled_general_regions|json }}"
|
||||
data-disabled-regions="{{ region_form.disabled_regions|json }}"
|
||||
data-all-paid-region-ids="{{ all_paid_region_ids_by_slug|json }}"
|
||||
data-not-applicable-msg="{{ _('Not applicable') }}"
|
||||
data-payment-methods="{{ payment_methods|json }}"
|
||||
data-pricelist-api-url="{{ api_pricelist_url }}"
|
||||
data-tier-zero-id="{{ tier_zero_id }}">
|
||||
{{ region_form.regions.errors }}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><span class="region-heading">{{ _('Region') }}</span></th>
|
||||
<th>{{ _('Retail price') }}
|
||||
<span class="local-currency-heading">({{ _('local currency') }})</span></th>
|
||||
<th>{{ _('Billing method') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for value, text in region_form.regions.field.choices %}
|
||||
{% if value|int in mkt.regions.ALL_PAID_REGION_IDS %}
|
||||
|
||||
{% include 'developers/payments/includes/regions_toggle.html' %}
|
||||
|
||||
<div class="paid-regions">
|
||||
<h3>{{ _('Available Regions') }}</h3>
|
||||
<div class="hint note">
|
||||
<p>{{ _('Your app will be available in the following selected regions:') }}</p>
|
||||
</div>
|
||||
<table id="paid-regions">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>
|
||||
<label {% if value in region_form.disabled_regions %} class="disabled"{% endif %}>
|
||||
<input type="checkbox"
|
||||
{% if value in region_form.disabled_regions %}disabled{% endif %}
|
||||
{% if value in region_form.initial.regions %}checked{% endif %}
|
||||
name="regions" value="{{ value }}">{{ text }}</label>
|
||||
</td>
|
||||
<td><span class="local-retail"></span></td>
|
||||
<td><span class="local-method"></span></td>
|
||||
<th><span class="region-heading">{{ _('Region') }}</span></th>
|
||||
<th>{{ _('Retail price') }}
|
||||
<span class="local-currency-heading">({{ _('local currency') }})</span></th>
|
||||
<th>{{ _('Billing method') }}</th>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody class="checkbox-choices">
|
||||
{% for id in all_paid_region_ids_by_slug %}
|
||||
<tr data-region="{{ id }}"></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h3>{{ _("Other regions") }}</h3>
|
||||
<div class="hint note">
|
||||
<p>
|
||||
{% trans %}
|
||||
Your app will be available in the following selected regions in the future when payments are available based on your chosen price point.
|
||||
To exclude your app from appearing in a region please un-check that region before saving.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% include 'developers/payments/includes/region_form.html' %}
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% if region_form.disabled_regions %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% include 'developers/payments/includes/regions_disabled.html' %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{% include 'developers/payments/includes/regions_other.html' %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="listing-footer">
|
||||
|
@ -243,22 +226,9 @@
|
|||
{# Non-paid app region lists #}
|
||||
<div id="regions-island">
|
||||
<h2>{{ _('Regions and listings') }}</h2>
|
||||
{% if region_form.has_inappropriate_regions() %}
|
||||
{% include 'developers/payments/includes/regions_inappropriate.html' %}
|
||||
{% endif %}
|
||||
<section id="regions" class="island">
|
||||
{% include 'developers/payments/includes/regions_toggle.html' %}
|
||||
{{ region_form.regions.errors }}
|
||||
<div class="checkbox-choices"
|
||||
data-disabled="{{ region_form.disabled_regions|json }}">
|
||||
{{ region_form.regions }}
|
||||
</div>
|
||||
{% if region_form.disabled_regions %}
|
||||
{% include 'developers/payments/includes/regions_disabled.html' %}
|
||||
{% endif %}
|
||||
<div class="other-regions">
|
||||
{% include 'developers/payments/includes/regions_other.html' %}
|
||||
</div>
|
||||
{% include 'developers/payments/includes/region_form.html' %}
|
||||
<button>{{ _('Save Changes') }}</button>
|
||||
</section>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,6 @@ from amo.tests import app_factory, version_factory
|
|||
from amo.tests.test_helpers import get_image_path
|
||||
from addons.models import Addon, AddonCategory, Category, CategorySupervisor
|
||||
from files.helpers import copyfileobj
|
||||
from market.models import AddonPremium, Price
|
||||
from tags.models import Tag
|
||||
from users.models import UserProfile
|
||||
|
||||
|
@ -151,7 +150,7 @@ class TestCategoryForm(amo.tests.WebappTestCase):
|
|||
|
||||
|
||||
class TestRegionForm(amo.tests.WebappTestCase):
|
||||
fixtures = fixture('webapp_337141', 'prices')
|
||||
fixtures = fixture('webapp_337141')
|
||||
|
||||
def setUp(self):
|
||||
super(TestRegionForm, self).setUp()
|
||||
|
@ -160,254 +159,76 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
|
||||
def test_initial_empty(self):
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
eq_(form.initial['regions'], mkt.regions.REGION_IDS)
|
||||
eq_(form.initial['other_regions'], True)
|
||||
eq_(form.initial['regions'], mkt.regions.ALL_REGION_IDS)
|
||||
eq_(form.initial['enable_new_regions'], False)
|
||||
|
||||
def test_initial_excluded_in_region(self):
|
||||
AER.objects.create(addon=self.app, region=mkt.regions.BR.id)
|
||||
|
||||
regions = list(mkt.regions.REGION_IDS)
|
||||
regions = list(mkt.regions.ALL_REGION_IDS)
|
||||
regions.remove(mkt.regions.BR.id)
|
||||
|
||||
eq_(self.get_app().get_region_ids(), regions)
|
||||
eq_(self.get_app().get_region_ids(worldwide=True), regions)
|
||||
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
eq_(form.initial['regions'], regions)
|
||||
eq_(form.initial['other_regions'], True)
|
||||
eq_(form.initial['enable_new_regions'], False)
|
||||
|
||||
def test_initial_excluded_in_regions_and_future_regions(self):
|
||||
for region in [mkt.regions.BR, mkt.regions.UK, mkt.regions.WORLDWIDE]:
|
||||
AER.objects.create(addon=self.app, region=region.id)
|
||||
|
||||
regions = list(mkt.regions.REGION_IDS)
|
||||
regions = list(mkt.regions.ALL_REGION_IDS)
|
||||
regions.remove(mkt.regions.BR.id)
|
||||
regions.remove(mkt.regions.UK.id)
|
||||
regions.remove(mkt.regions.WORLDWIDE.id)
|
||||
|
||||
eq_(self.get_app().get_region_ids(), regions)
|
||||
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
eq_(form.initial['regions'], regions)
|
||||
eq_(form.initial['other_regions'], False)
|
||||
|
||||
@mock.patch('mkt.regions.BR.has_payments', new=True)
|
||||
def test_disable_regions_on_paid(self):
|
||||
eq_(self.app.get_region_ids(), mkt.regions.REGION_IDS)
|
||||
self.app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(id=1)
|
||||
AddonPremium.objects.create(addon=self.app,
|
||||
price=price)
|
||||
self.kwargs['price'] = price
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
form = forms.RegionForm(
|
||||
data={'regions': mkt.regions.ALL_PAID_REGION_IDS}, **self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.PL.id]},
|
||||
**self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
assert not form.has_inappropriate_regions()
|
||||
form.save()
|
||||
|
||||
self.assertSetEqual(self.app.get_region_ids(),
|
||||
[mkt.regions.PL.id])
|
||||
|
||||
@mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=[3, 4, 5])
|
||||
@mock.patch('mkt.developers.forms.ALL_REGION_IDS',
|
||||
new=[1, 2, 3, 4, 5, 6])
|
||||
def test_inappropriate_regions(self):
|
||||
self.app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
form.price_region_ids = [2, 3, 5]
|
||||
# Reset disabled_regions as we're modifying price_regions.
|
||||
form.disabled_regions = form._disabled_regions()
|
||||
|
||||
# 6 is not in price_region_ids or ALL_PAID_REGION_IDS
|
||||
form.region_ids = [6]
|
||||
assert form.has_inappropriate_regions(), 'Region 6 should be invalid'
|
||||
# Worldwide (1) is disabled for paid apps presently.
|
||||
form.region_ids = [mkt.regions.WORLDWIDE.id]
|
||||
assert form.has_inappropriate_regions(), 'Worldwide region should be invalid'
|
||||
# 4 is not in price_region_ids so should be invalid.
|
||||
form.region_ids = [4]
|
||||
assert form.has_inappropriate_regions(), 'Region 4 should be invalid'
|
||||
# 2 is in price_region_ids but not in ALL_PAID_REGION_IDS
|
||||
# so should be invalid.
|
||||
form.region_ids = [2]
|
||||
assert form.has_inappropriate_regions(), 'Region 2 should be invalid'
|
||||
# 3 is in price_region_ids and in ALL_PAID_REGION_IDS so should be ok.
|
||||
form.region_ids = [3]
|
||||
assert not form.has_inappropriate_regions(), 'Region 3 should be valid'
|
||||
|
||||
def test_inappropriate_regions_free_app(self):
|
||||
self.app.update(premium_type=amo.ADDON_FREE)
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
eq_(form.has_inappropriate_regions(), None)
|
||||
|
||||
@mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=[2, 3, 4, 5])
|
||||
@mock.patch('mkt.developers.forms.ALL_REGION_IDS',
|
||||
new=[1, 2, 3, 4, 5, 6])
|
||||
def test_disabled_regions_premium(self):
|
||||
self.app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
form.price_region_ids = [2, 3, 5]
|
||||
# Worldwide (1) is disabled for paid apps curently.
|
||||
self.assertSetEqual(form._disabled_regions(), [1, 4, 6])
|
||||
|
||||
@mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=[2, 3, 4, 5])
|
||||
@mock.patch('mkt.developers.forms.ALL_REGION_IDS',
|
||||
new=[1, 2, 3, 4, 5, 6])
|
||||
def test_disabled_regions_free_inapp(self):
|
||||
self.app.update(premium_type=amo.ADDON_FREE_INAPP)
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
# Worldwide (1) is disabled for paid apps curently.
|
||||
self.assertSetEqual(form._disabled_regions(), [1, 6])
|
||||
|
||||
@mock.patch('mkt.developers.forms.ALL_REGION_IDS',
|
||||
new=[1, 2, 3, 4, 5, 6])
|
||||
def test_disabled_regions_free(self):
|
||||
self.app.update(premium_type=amo.ADDON_FREE)
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
self.assertSetEqual(form._disabled_regions(), [])
|
||||
|
||||
def test_free_inapp_with_non_paid_region(self):
|
||||
# Start with a free app with in_app payments.
|
||||
self.app.update(premium_type=amo.ADDON_FREE_INAPP)
|
||||
self.kwargs['price'] = 'free'
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
all_paid_regions = set(mkt.regions.ALL_PAID_REGION_IDS)
|
||||
|
||||
new_paid = sorted(
|
||||
all_paid_regions.difference(set([mkt.regions.BR.id])))
|
||||
with mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=new_paid):
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.BR.id]},
|
||||
**self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
new_paid = sorted(
|
||||
all_paid_regions.difference(set([mkt.regions.UK.id])))
|
||||
with mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=new_paid):
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.UK.id]},
|
||||
**self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
new_paid = sorted(
|
||||
all_paid_regions.union(set([mkt.regions.PL.id])))
|
||||
with mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=new_paid):
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.PL.id]},
|
||||
**self.kwargs)
|
||||
assert form.is_valid()
|
||||
assert not form.has_inappropriate_regions()
|
||||
|
||||
def test_premium_to_free_inapp_with_non_paid_region(self):
|
||||
# At this point the app is premium.
|
||||
self.app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
self.kwargs['price'] = 'free'
|
||||
form = forms.RegionForm(data=None, **self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
all_paid_regions = set(mkt.regions.ALL_PAID_REGION_IDS)
|
||||
new_paid = sorted(
|
||||
all_paid_regions.difference(set([mkt.regions.BR.id])))
|
||||
with mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=new_paid):
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.BR.id]},
|
||||
**self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
new_paid = sorted(
|
||||
all_paid_regions.difference(set([mkt.regions.UK.id])))
|
||||
with mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=new_paid):
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.UK.id]},
|
||||
**self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
|
||||
new_paid = sorted(all_paid_regions.union(set([mkt.regions.PL.id])))
|
||||
with mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=new_paid):
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.PL.id]},
|
||||
**self.kwargs)
|
||||
assert form.is_valid()
|
||||
assert not form.has_inappropriate_regions()
|
||||
|
||||
def test_paid_enable_region(self):
|
||||
for region in mkt.regions.ALL_REGION_IDS:
|
||||
AER.objects.create(addon=self.app, region=region)
|
||||
self.app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(id=1)
|
||||
AddonPremium.objects.create(addon=self.app,
|
||||
price=price)
|
||||
self.kwargs['price'] = price
|
||||
form = forms.RegionForm(data={'regions': []}, **self.kwargs)
|
||||
assert not form.is_valid() # Fails due to needing at least 1 region.
|
||||
assert not form.has_inappropriate_regions(), (
|
||||
form.has_inappropriate_regions())
|
||||
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.PL.id]},
|
||||
**self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
assert not form.has_inappropriate_regions()
|
||||
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.BR.id]},
|
||||
**self.kwargs)
|
||||
assert not form.is_valid()
|
||||
assert form.has_inappropriate_regions()
|
||||
eq_(form.initial['enable_new_regions'], False)
|
||||
|
||||
def test_worldwide_only(self):
|
||||
form = forms.RegionForm(data={'other_regions': 'on'}, **self.kwargs)
|
||||
form = forms.RegionForm(data={'regions': [mkt.regions.WORLDWIDE.id]},
|
||||
**self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
|
||||
def test_enable_new_regions(self):
|
||||
form = forms.RegionForm(data={'enable_new_regions': 'on',
|
||||
'regions': mkt.regions.ALL_REGION_IDS},
|
||||
**self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
form.save()
|
||||
eq_(self.app.get_region_ids(True), [mkt.regions.WORLDWIDE.id])
|
||||
eq_(self.app.enable_new_regions, True)
|
||||
|
||||
def test_no_regions(self):
|
||||
form = forms.RegionForm(data={}, **self.kwargs)
|
||||
assert not form.is_valid()
|
||||
eq_(form.errors,
|
||||
{'__all__': ['You must select at least one region or '
|
||||
'"Other and new regions."']})
|
||||
{'__all__': ['You must select at least one region.']})
|
||||
|
||||
def test_exclude_each_region(self):
|
||||
"""Test that it's possible to exclude each region."""
|
||||
|
||||
for region_id in mkt.regions.REGION_IDS:
|
||||
if region_id == mkt.regions.WORLDWIDE.id:
|
||||
continue
|
||||
|
||||
to_exclude = list(mkt.regions.REGION_IDS)
|
||||
for region_id in mkt.regions.ALL_REGION_IDS:
|
||||
to_exclude = list(mkt.regions.ALL_REGION_IDS)
|
||||
to_exclude.remove(region_id)
|
||||
|
||||
form = forms.RegionForm(
|
||||
data={'regions': to_exclude,
|
||||
'other_regions': True}, **self.kwargs)
|
||||
'enable_new_regions': 'on'}, **self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
form.save()
|
||||
|
||||
eq_(self.app.get_region_ids(False), to_exclude)
|
||||
eq_(self.app.get_region_ids(True), to_exclude)
|
||||
|
||||
def test_brazil_games_excluded(self):
|
||||
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
|
||||
AddonCategory.objects.create(addon=self.app, category=games)
|
||||
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
|
||||
'other_regions': True}, **self.kwargs)
|
||||
'enable_new_regions': True}, **self.kwargs)
|
||||
|
||||
# Developers should still be able to save form OK, even
|
||||
# if they pass a bad region. Think of the grandfathered developers.
|
||||
|
@ -420,7 +241,7 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
eq_(set(form.initial['regions']),
|
||||
set(mkt.regions.REGION_IDS) -
|
||||
set([mkt.regions.BR.id, mkt.regions.WORLDWIDE.id]))
|
||||
eq_(form.initial['other_regions'], True)
|
||||
eq_(form.initial['enable_new_regions'], True)
|
||||
|
||||
def test_brazil_games_already_excluded(self):
|
||||
AER.objects.create(addon=self.app, region=mkt.regions.BR.id)
|
||||
|
@ -429,7 +250,7 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
AddonCategory.objects.create(addon=self.app, category=games)
|
||||
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
|
||||
'other_regions': True}, **self.kwargs)
|
||||
'enable_new_regions': True}, **self.kwargs)
|
||||
|
||||
assert form.is_valid()
|
||||
form.save()
|
||||
|
@ -438,7 +259,7 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
eq_(set(form.initial['regions']),
|
||||
set(mkt.regions.REGION_IDS) -
|
||||
set([mkt.regions.BR.id, mkt.regions.WORLDWIDE.id]))
|
||||
eq_(form.initial['other_regions'], True)
|
||||
eq_(form.initial['enable_new_regions'], True)
|
||||
|
||||
def test_brazil_games_with_content_rating(self):
|
||||
# This game has a government content rating!
|
||||
|
@ -449,8 +270,8 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
games = Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
|
||||
AddonCategory.objects.create(addon=self.app, category=games)
|
||||
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
|
||||
'other_regions': 'on'}, **self.kwargs)
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.ALL_REGION_IDS,
|
||||
'enable_new_regions': 'on'}, **self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
form.save()
|
||||
|
||||
|
@ -458,7 +279,7 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
|
||||
def test_exclude_worldwide(self):
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
|
||||
'other_regions': False}, **self.kwargs)
|
||||
'enable_new_regions': False}, **self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
form.save()
|
||||
eq_(self.app.get_region_ids(True), mkt.regions.REGION_IDS)
|
||||
|
@ -466,8 +287,8 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
def test_reinclude_region(self):
|
||||
AER.objects.create(addon=self.app, region=mkt.regions.BR.id)
|
||||
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
|
||||
'other_regions': True}, **self.kwargs)
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.ALL_REGION_IDS,
|
||||
'enable_new_regions': True}, **self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
form.save()
|
||||
eq_(self.app.get_region_ids(True), mkt.regions.ALL_REGION_IDS)
|
||||
|
@ -475,42 +296,22 @@ class TestRegionForm(amo.tests.WebappTestCase):
|
|||
def test_reinclude_worldwide(self):
|
||||
AER.objects.create(addon=self.app, region=mkt.regions.WORLDWIDE.id)
|
||||
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.REGION_IDS,
|
||||
'other_regions': True}, **self.kwargs)
|
||||
form = forms.RegionForm(data={'regions': mkt.regions.ALL_REGION_IDS},
|
||||
**self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
form.save()
|
||||
eq_(self.app.get_region_ids(True), mkt.regions.ALL_REGION_IDS)
|
||||
|
||||
@mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS',
|
||||
new=[2, 4, 5, 7])
|
||||
def test_enable_other_region_paid(self):
|
||||
def test_worldwide_valid_choice_paid(self):
|
||||
self.app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
form = forms.RegionForm(data={'regions': [2, 4],
|
||||
'other_regions': 'on'}, **self.kwargs)
|
||||
form.price_region_ids = [2, 4, 7]
|
||||
# Update disabled_regions as we tweaked price_regions.
|
||||
form.disabled_regions = form._disabled_regions()
|
||||
eq_(self.app.enable_new_regions, False)
|
||||
form = forms.RegionForm(
|
||||
data={'regions': [mkt.regions.WORLDWIDE.id]}, **self.kwargs)
|
||||
assert form.is_valid(), form.errors
|
||||
form.save()
|
||||
eq_(self.app.enable_new_regions, True)
|
||||
eq_(self.app.addonexcludedregion.filter(
|
||||
region=mkt.regions.WORLDWIDE.id).exists(), False)
|
||||
|
||||
def test_worldwide_invalid_choice_paid(self):
|
||||
self.app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
def test_worldwide_valid_choice_free(self):
|
||||
form = forms.RegionForm(
|
||||
data={'regions': [mkt.regions.WORLDWIDE.id]}, **self.kwargs)
|
||||
assert not form.is_valid(), form.errors
|
||||
assert ('Select a valid choice. 1 is not one of the available '
|
||||
'choices.' in form.errors['regions'])
|
||||
|
||||
def test_worldwide_invalid_choice(self):
|
||||
form = forms.RegionForm(
|
||||
data={'regions': [mkt.regions.WORLDWIDE.id]}, **self.kwargs)
|
||||
assert not form.is_valid(), form.errors
|
||||
assert ('Select a valid choice. 1 is not one of the available '
|
||||
'choices.' in form.errors['regions'])
|
||||
assert form.is_valid(), form.errors
|
||||
|
||||
|
||||
class TestNewManifestForm(amo.tests.TestCase):
|
||||
|
|
|
@ -225,9 +225,8 @@ class TestPremiumForm(amo.tests.TestCase):
|
|||
# 1 x Free with inapp
|
||||
# + 1 x price tier 0
|
||||
# + 3 x values grouped by billing
|
||||
# + 1 x 'Please select'
|
||||
# = 6
|
||||
eq_(len(form.fields['price'].choices), 6)
|
||||
# = 5
|
||||
eq_(len(form.fields['price'].choices), 5)
|
||||
html = form.as_p()
|
||||
eq_(len(pq(html)('#id_price optgroup')), 3, 'Should be 3 optgroups')
|
||||
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
from StringIO import StringIO
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.core.management.base import CommandError
|
||||
|
||||
from nose.tools import eq_, ok_, raises
|
||||
from mock import patch
|
||||
|
||||
import amo
|
||||
import amo.tests
|
||||
from market.models import AddonPremium, Price
|
||||
from mkt.developers.management.commands import (
|
||||
check_paid_app_regions)
|
||||
from mkt.regions import (ALL_REGION_IDS, REGIONS_CHOICES_ID_DICT,
|
||||
PL, US, WORLDWIDE)
|
||||
from mkt.site.fixtures import fixture
|
||||
from mkt.webapps.models import AddonExcludedRegion as AER, Webapp
|
||||
|
||||
|
||||
class TestRegionManagmentCommand(amo.tests.TestCase):
|
||||
fixtures = fixture('webapp_337141', 'prices')
|
||||
|
||||
@raises(CommandError)
|
||||
def test_unknown_slug(self):
|
||||
check_paid_app_regions.Command().handle('whatever')
|
||||
|
||||
@patch('mkt.developers.forms.ALL_PAID_REGION_IDS', new=[PL.id, US.id])
|
||||
@patch('sys.stdout', new_callable=StringIO)
|
||||
def test_app_has_bad_regions(self, mock_stdout):
|
||||
app = Webapp.objects.get(id=337141)
|
||||
app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(id=1)
|
||||
AddonPremium.objects.create(addon=app, price=price)
|
||||
call_command('check_paid_app_regions', app.app_slug)
|
||||
# From the fixture poland is the only ok region
|
||||
# for the price.
|
||||
stdout_val = mock_stdout.getvalue()
|
||||
assert 'Poland *' not in stdout_val
|
||||
assert '* Inappropriate region' in stdout_val
|
||||
|
||||
for region_id in ALL_REGION_IDS:
|
||||
region_id = int(region_id)
|
||||
if region_id in (PL.id, US.id):
|
||||
continue
|
||||
region_name = unicode(REGIONS_CHOICES_ID_DICT.get(
|
||||
region_id).name)
|
||||
ok_('%s *' % region_name in stdout_val,
|
||||
'%s not present' % region_name)
|
||||
|
||||
@raises(CommandError)
|
||||
def test_premium_no_price(self):
|
||||
app = Webapp.objects.get(id=337141)
|
||||
app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
check_paid_app_regions.Command().handle(app.app_slug)
|
||||
|
||||
@patch('sys.stdout', new_callable=StringIO)
|
||||
def test_include_region_by_id(self, mock_stdout):
|
||||
app = Webapp.objects.get(id=337141)
|
||||
app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(id=1)
|
||||
AddonPremium.objects.create(addon=app, price=price)
|
||||
AER.objects.create(addon=app, region=WORLDWIDE.id)
|
||||
eq_(len(AER.objects.all()), 1)
|
||||
call_command('check_paid_app_regions', app.app_slug,
|
||||
include_region_id=WORLDWIDE.id)
|
||||
eq_(AER.objects.all().exists(), False)
|
||||
|
||||
@patch('sys.stdout', new_callable=StringIO)
|
||||
def test_exclude_region_by_id(self, mock_stdout):
|
||||
app = Webapp.objects.get(id=337141)
|
||||
app.update(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(id=1)
|
||||
AddonPremium.objects.create(addon=app, price=price)
|
||||
eq_(len(AER.objects.all()), 0)
|
||||
call_command('check_paid_app_regions', app.app_slug,
|
||||
exclude_region_id=WORLDWIDE.id)
|
||||
eq_(AER.objects.get(addon=app).region, WORLDWIDE.id)
|
||||
|
||||
@patch('sys.stdout', new_callable=StringIO)
|
||||
@patch('mkt.developers.forms.ALL_PAID_REGION_IDS', new=[PL.id, US.id])
|
||||
def test_free_with_inapp(self, mock_stdout):
|
||||
app = Webapp.objects.get(id=337141)
|
||||
app.update(premium_type=amo.ADDON_FREE_INAPP)
|
||||
call_command('check_paid_app_regions', app.app_slug)
|
||||
# From the fixture poland is the only ok region
|
||||
# for the price.
|
||||
stdout_val = mock_stdout.getvalue()
|
||||
assert 'Poland *' not in stdout_val
|
||||
assert 'United States *' not in stdout_val
|
||||
assert '* Inappropriate region' in stdout_val
|
||||
|
||||
@raises(CommandError)
|
||||
def test_free_app(self):
|
||||
app = Webapp.objects.get(id=337141)
|
||||
app.update(premium_type=amo.ADDON_FREE)
|
||||
eq_(app.premium_type, amo.ADDON_FREE)
|
||||
check_paid_app_regions.Command().handle(app.app_slug)
|
|
@ -17,7 +17,7 @@ from constants.payments import (PAYMENT_METHOD_ALL,
|
|||
PAYMENT_METHOD_CARD,
|
||||
PAYMENT_METHOD_OPERATOR)
|
||||
from mkt.constants.payments import ACCESS_PURCHASE, ACCESS_SIMULATE
|
||||
from mkt.constants.regions import ALL_PAID_REGION_IDS
|
||||
from mkt.constants.regions import ALL_REGION_IDS
|
||||
from market.models import Price
|
||||
from users.models import UserProfile
|
||||
|
||||
|
@ -254,8 +254,6 @@ class TestPayments(amo.tests.TestCase):
|
|||
self.price = Price.objects.filter()[0]
|
||||
self.patch = mock.patch('mkt.developers.models.client')
|
||||
self.sol = self.patch.start()
|
||||
prs = set([p['region'] for p in self.price.prices()])
|
||||
self.price_regions = (set(ALL_PAID_REGION_IDS).intersection(prs))
|
||||
|
||||
def tearDown(self):
|
||||
self.patch.stop()
|
||||
|
@ -275,16 +273,6 @@ class TestPayments(amo.tests.TestCase):
|
|||
base.update(extension)
|
||||
return base
|
||||
|
||||
@mock.patch('mkt.developers.forms.ALL_PAID_REGION_IDS', new=[11])
|
||||
def test_paid_app_has_correct_regions_when_loaded(self):
|
||||
self.webapp.update(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(pk=1)
|
||||
res = self.client.post(
|
||||
self.url, self.get_postdata({'allow_inapp': False,
|
||||
'price': price.pk}), follow=True)
|
||||
pqr = pq(res.content)
|
||||
eq_(len(pqr('input[type=checkbox][value=11]:not(:disabled)')), 1)
|
||||
|
||||
def test_free(self):
|
||||
res = self.client.post(
|
||||
self.url, self.get_postdata({'toggle-paid': 'free'}), follow=True)
|
||||
|
@ -353,7 +341,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
self.client.post(
|
||||
self.url, self.get_postdata({'price': 'free',
|
||||
'allow_inapp': 'True',
|
||||
'regions': ALL_PAID_REGION_IDS}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
eq_(self.get_webapp().upsold, None)
|
||||
eq_(AddonPremium.objects.all().count(), 0)
|
||||
|
@ -366,7 +354,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'allow_inapp': True,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}))
|
||||
'regions': ALL_REGION_IDS}))
|
||||
self.assert3xx(res, self.url)
|
||||
eq_(self.get_webapp().premium_type, amo.ADDON_PREMIUM_INAPP)
|
||||
|
||||
|
@ -419,11 +407,11 @@ class TestPayments(amo.tests.TestCase):
|
|||
self.client.post(
|
||||
self.url, self.get_postdata({'price': 'free',
|
||||
'allow_inapp': 'True',
|
||||
'regions': self.price_regions}))
|
||||
'regions': ALL_REGION_IDS}))
|
||||
eq_(self.get_webapp().premium_type, amo.ADDON_FREE_INAPP)
|
||||
self.client.post(
|
||||
self.url, self.get_postdata({'toggle-paid': 'free',
|
||||
'regions': self.price_regions}))
|
||||
'regions': ALL_REGION_IDS}))
|
||||
eq_(self.get_webapp().premium_type, amo.ADDON_FREE)
|
||||
|
||||
def test_free_with_inapp_without_account_is_incomplete(self):
|
||||
|
@ -434,7 +422,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'price': 'free',
|
||||
'allow_inapp': 'True',
|
||||
'regions': ALL_PAID_REGION_IDS}))
|
||||
'regions': ALL_REGION_IDS}))
|
||||
self.assert3xx(res, self.url)
|
||||
eq_(self.get_webapp().status, amo.STATUS_NULL)
|
||||
eq_(AddonPremium.objects.all().count(), 0)
|
||||
|
@ -447,7 +435,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'price': self.price.pk,
|
||||
'allow_inapp': 'False',
|
||||
'regions': self.price_regions}))
|
||||
'regions': ALL_REGION_IDS}))
|
||||
self.assert3xx(res, self.url)
|
||||
eq_(self.get_webapp().status, amo.STATUS_NULL)
|
||||
|
||||
|
@ -494,7 +482,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'price': 'free',
|
||||
'allow_inapp': 'True',
|
||||
'regions': ALL_PAID_REGION_IDS,
|
||||
'regions': ALL_REGION_IDS,
|
||||
'accounts': acct.pk}), follow=True)
|
||||
self.assertNoFormErrors(res)
|
||||
eq_(res.status_code, 200)
|
||||
|
@ -510,7 +498,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'price': self.price.pk,
|
||||
'accounts': acct.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
eq_(api.bango.premium.post.call_count, 1)
|
||||
self.assertNoFormErrors(res)
|
||||
|
@ -551,7 +539,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'accounts': acct.pk,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
self.assertFormError(res, 'bango_account_list_form', 'accounts',
|
||||
[u'You are not permitted to change payment '
|
||||
|
@ -575,7 +563,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'accounts': owner_acct.pk,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
assert (AddonPaymentAccount.objects
|
||||
.filter(addon=self.webapp).exists())
|
||||
|
@ -589,7 +577,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'accounts': admin_acct.pk,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
|
||||
self.assertFormError(res, 'bango_account_list_form', 'accounts',
|
||||
|
@ -605,7 +593,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'accounts': owner_acct.pk,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
assert (AddonPaymentAccount.objects
|
||||
.filter(addon=self.webapp).exists())
|
||||
|
@ -628,7 +616,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'accounts': owner_acct2.pk,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
eq_(res.status_code, 200)
|
||||
self.assertNoFormErrors(res)
|
||||
|
@ -647,7 +635,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(
|
||||
self.url, self.get_postdata({'accounts': acct.pk,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
amo.set_user(self.other)
|
||||
# Make this user a dev so they have access to the payments page.
|
||||
|
@ -676,7 +664,7 @@ class TestPayments(amo.tests.TestCase):
|
|||
res = self.client.post(self.url,
|
||||
self.get_postdata({'accounts': owner_acct.pk,
|
||||
'price': self.price.pk,
|
||||
'regions': self.price_regions}),
|
||||
'regions': ALL_REGION_IDS}),
|
||||
follow=True)
|
||||
self.assertNoFormErrors(res)
|
||||
# Login as admin.
|
||||
|
@ -792,7 +780,7 @@ class TestRegions(amo.tests.TestCase):
|
|||
return Addon.objects.get(pk=337141)
|
||||
|
||||
def get_dict(self, **kwargs):
|
||||
extension = {'regions': mkt.regions.REGION_IDS,
|
||||
extension = {'regions': mkt.regions.ALL_REGION_IDS,
|
||||
'other_regions': 'on',
|
||||
'free_platforms': ['free-%s' % dt.class_name for dt in
|
||||
self.webapp.device_types]}
|
||||
|
@ -803,7 +791,7 @@ class TestRegions(amo.tests.TestCase):
|
|||
return sorted(AER.objects.filter(addon=self.webapp)
|
||||
.values_list('region', flat=True))
|
||||
|
||||
def test_edit_other_categories_are_not_excluded(self):
|
||||
def test_edit_all_regions_are_not_excluded(self):
|
||||
# Keep the category around for good measure.
|
||||
Category.objects.create(type=amo.ADDON_WEBAPP, slug='games')
|
||||
|
||||
|
@ -819,7 +807,7 @@ class TestRegions(amo.tests.TestCase):
|
|||
self.assertNoFormErrors(r)
|
||||
|
||||
td = pq(r.content)('#regions')
|
||||
eq_(td.find('div[data-disabled]').attr('data-disabled'),
|
||||
eq_(td.find('div[data-disabled-regions]').attr('data-disabled-regions'),
|
||||
'[%d]' % mkt.regions.BR.id)
|
||||
eq_(td.find('.note.disabled-regions').length, 1)
|
||||
|
||||
|
@ -833,13 +821,13 @@ class TestRegions(amo.tests.TestCase):
|
|||
|
||||
r = self.client.get(self.url)
|
||||
td = pq(r.content)('#regions')
|
||||
eq_(td.find('div[data-disabled]').attr('data-disabled'), '[]')
|
||||
eq_(td.find('div[data-disabled-regions]').attr('data-disabled-regions'), '[]')
|
||||
eq_(td.find('.note.disabled-regions').length, 0)
|
||||
|
||||
def test_brazil_other_cats_form_enabled(self):
|
||||
r = self.client.get(self.url)
|
||||
td = pq(r.content)('#regions')
|
||||
eq_(td.find('div[data-disabled]').attr('data-disabled'), '[]')
|
||||
eq_(td.find('div[data-disabled-regions]').attr('data-disabled-regions'), '[]')
|
||||
eq_(td.find('.note.disabled-regions').length, 0)
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ from mkt.constants import DEVICE_LOOKUP
|
|||
from mkt.developers.decorators import dev_required
|
||||
from mkt.developers.models import (AddonPaymentAccount, PaymentAccount,
|
||||
UserInappKey, uri_to_pk)
|
||||
from mkt.regions import ALL_PAID_REGION_IDS_BY_SLUG
|
||||
|
||||
from . import forms, forms_payments
|
||||
|
||||
|
@ -62,10 +63,6 @@ def payments(request, addon_id, addon, webapp=False):
|
|||
request.POST or None, addon=addon, user=request.amo_user)
|
||||
|
||||
if request.method == 'POST':
|
||||
if premium_form.is_valid():
|
||||
region_form = forms.RegionForm(request.POST, product=addon,
|
||||
request=request, price=premium_form.cleaned_data['price']
|
||||
)
|
||||
|
||||
success = all(form.is_valid() for form in
|
||||
[premium_form, region_form, upsell_form,
|
||||
|
@ -146,7 +143,9 @@ def payments(request, addon_id, addon, webapp=False):
|
|||
PAYMENT_METHOD_ALL: _('All'),
|
||||
PAYMENT_METHOD_CARD: _('Credit card'),
|
||||
PAYMENT_METHOD_OPERATOR: _('Carrier'),
|
||||
}})
|
||||
},
|
||||
'all_paid_region_ids_by_slug': ALL_PAID_REGION_IDS_BY_SLUG,
|
||||
})
|
||||
|
||||
|
||||
@login_required
|
||||
|
|
|
@ -577,13 +577,6 @@ class Webapp(Addon):
|
|||
|
||||
return sorted(list(excluded))
|
||||
|
||||
def get_possible_price_region_ids(self):
|
||||
# TODO: Stuart is going to rip this out.
|
||||
if self.has_premium() and self.premium:
|
||||
ids = [p['region'] for p in self.premium.price.prices()]
|
||||
return sorted(ids)
|
||||
return []
|
||||
|
||||
def get_price_region_ids(self):
|
||||
tier = self.get_tier()
|
||||
if tier:
|
||||
|
|
|
@ -232,21 +232,6 @@ class TestWebapp(amo.tests.TestCase):
|
|||
webapp._premium.price = 0
|
||||
eq_(webapp.has_premium(), True)
|
||||
|
||||
def test_get_possible_prices_premium(self):
|
||||
webapp = Webapp.objects.create(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(pk=1)
|
||||
AddonPremium.objects.create(addon=webapp, price=price)
|
||||
ok_(len(webapp.get_possible_price_region_ids()) > 0)
|
||||
ok_(isinstance(webapp.get_possible_price_region_ids(), list))
|
||||
|
||||
def test_get_possible_prices_premium_then_free_inapp(self):
|
||||
webapp = Webapp.objects.create(premium_type=amo.ADDON_PREMIUM)
|
||||
price = Price.objects.get(pk=1)
|
||||
AddonPremium.objects.create(addon=webapp, price=price)
|
||||
webapp.premium_type = amo.ADDON_FREE_INAPP
|
||||
eq_(len(webapp.get_possible_price_region_ids()), 0)
|
||||
ok_(isinstance(webapp.get_possible_price_region_ids(), list))
|
||||
|
||||
def test_get_price_no_premium(self):
|
||||
webapp = Webapp(premium_type=amo.ADDON_PREMIUM)
|
||||
eq_(webapp.get_price(), None)
|
||||
|
|
Загрузка…
Ссылка в новой задаче