mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-21 04:48:08 -05:00
Allow custom pricing for location targets.
This commit is contained in:
@@ -575,13 +575,15 @@ class PromotedLinkRoadblock(tdb_cassandra.View):
|
||||
|
||||
class PromotionPrices(tdb_cassandra.View):
|
||||
"""
|
||||
Price rules:
|
||||
* Location targeting trumps all: Anything targeting a metro gets the global
|
||||
metro price.
|
||||
* Any collection or subreddit with a specified price gets that price
|
||||
* Any collection or subreddit without a specified price gets the global
|
||||
collection or subreddit price
|
||||
* Frontpage gets the global collection price.
|
||||
Check all the following potentially specially priced conditions:
|
||||
* metro level targeting
|
||||
* country level targeting (but not if the metro targeting is used)
|
||||
* collection targeting
|
||||
* frontpage targeting
|
||||
* subreddit targeting
|
||||
|
||||
The price is the maximum price for all matching conditions. If no special
|
||||
conditions are met use the global price.
|
||||
|
||||
"""
|
||||
|
||||
@@ -595,10 +597,14 @@ class PromotionPrices(tdb_cassandra.View):
|
||||
"default_validation_class": tdb_cassandra.INT_TYPE,
|
||||
}
|
||||
|
||||
COLLECTION_DEFAULT = g.cpm_selfserve_collection.pennies
|
||||
SUBREDDIT_DEFAULT = g.cpm_selfserve.pennies
|
||||
COUNTRY_DEFAULT = g.cpm_selfserve_collection.pennies
|
||||
METRO_DEFAULT = g.cpm_selfserve_geotarget_metro.pennies
|
||||
|
||||
@classmethod
|
||||
def _get_components(cls, target, cpm):
|
||||
def _rowkey_and_column_from_target(cls, target):
|
||||
rowkey = column_name = None
|
||||
column_value = cpm
|
||||
|
||||
if isinstance(target, Target):
|
||||
if target.is_collection:
|
||||
@@ -611,50 +617,94 @@ class PromotionPrices(tdb_cassandra.View):
|
||||
if not rowkey or not column_name:
|
||||
raise ValueError("target must be Target")
|
||||
|
||||
return rowkey, column_name, column_value
|
||||
return rowkey, column_name
|
||||
|
||||
@classmethod
|
||||
def set_price(cls, target, cpm):
|
||||
rowkey, column_name, column_value = cls._get_components(target, cpm)
|
||||
cls._cf.insert(rowkey, {column_name: column_value})
|
||||
def _rowkey_and_column_from_location(cls, location):
|
||||
if not isinstance(location, Location):
|
||||
raise ValueError("location must be Location")
|
||||
|
||||
if location.metro:
|
||||
rowkey = "METRO"
|
||||
# NOTE: the column_name will also be the key used in the frontend
|
||||
# to determine pricing
|
||||
column_name = ''.join(map(str, (location.country, location.metro)))
|
||||
else:
|
||||
rowkey = "COUNTRY"
|
||||
column_name = location.country
|
||||
return rowkey, column_name
|
||||
|
||||
@classmethod
|
||||
def get_price(cls, target, location):
|
||||
if location and location.metro:
|
||||
return g.cpm_selfserve_geotarget_metro.pennies
|
||||
def set_target_price(cls, target, cpm):
|
||||
rowkey, column_name = cls._rowkey_and_column_from_target(target)
|
||||
cls._cf.insert(rowkey, {column_name: cpm})
|
||||
|
||||
# check for Frontpage
|
||||
if (isinstance(target, Target) and
|
||||
not target.is_collection and
|
||||
target.subreddit_name == Frontpage.name):
|
||||
return g.cpm_selfserve_collection.pennies
|
||||
@classmethod
|
||||
def set_location_price(cls, location, cpm):
|
||||
rowkey, column_name = cls._rowkey_and_column_from_location(location)
|
||||
cls._cf.insert(rowkey, {column_name: cpm})
|
||||
|
||||
# check for target specific override price
|
||||
rowkey, column_name, _ = cls._get_components(target, None)
|
||||
@classmethod
|
||||
def lookup_target_price(cls, target, default):
|
||||
rowkey, column_name = cls._rowkey_and_column_from_target(target)
|
||||
target_price = cls._lookup_price(rowkey, column_name)
|
||||
return target_price or default
|
||||
|
||||
@classmethod
|
||||
def lookup_location_price(cls, location, default):
|
||||
rowkey, column_name = cls._rowkey_and_column_from_location(location)
|
||||
location_price = cls._lookup_price(rowkey, column_name)
|
||||
return location_price or default
|
||||
|
||||
@classmethod
|
||||
def _lookup_price(cls, rowkey, column_name):
|
||||
try:
|
||||
columns = cls._cf.get(rowkey, columns=[column_name])
|
||||
except tdb_cassandra.NotFoundException:
|
||||
columns = {}
|
||||
if column_name in columns:
|
||||
return columns[column_name]
|
||||
|
||||
# use global price
|
||||
if isinstance(target, Target):
|
||||
if target.is_collection:
|
||||
return g.cpm_selfserve_collection.pennies
|
||||
else:
|
||||
return g.cpm_selfserve.pennies
|
||||
return columns.get(column_name)
|
||||
|
||||
raise ValueError("target must be Target")
|
||||
@classmethod
|
||||
def get_price(cls, target, location):
|
||||
prices = []
|
||||
|
||||
# set location specific prices or use defaults
|
||||
if location and location.metro:
|
||||
metro_price = cls.lookup_location_price(location, cls.METRO_DEFAULT)
|
||||
prices.append(metro_price)
|
||||
elif location:
|
||||
country_price = cls.lookup_location_price(
|
||||
location, cls.COUNTRY_DEFAULT)
|
||||
prices.append(country_price)
|
||||
|
||||
# set target specific prices or use default
|
||||
if (not target.is_collection and
|
||||
target.subreddit_name == Frontpage.name):
|
||||
# Frontpage is priced as a collection
|
||||
prices.append(cls.COLLECTION_DEFAULT)
|
||||
elif target.is_collection:
|
||||
collection_price = cls.lookup_target_price(
|
||||
target, cls.COLLECTION_DEFAULT)
|
||||
prices.append(collection_price)
|
||||
else:
|
||||
subreddit_price = cls.lookup_target_price(
|
||||
target, cls.SUBREDDIT_DEFAULT)
|
||||
prices.append(subreddit_price)
|
||||
|
||||
return max(prices)
|
||||
|
||||
@classmethod
|
||||
def get_price_dict(cls):
|
||||
r = {
|
||||
"COLLECTION": {},
|
||||
"SUBREDDIT": {},
|
||||
"METRO": g.cpm_selfserve_geotarget_metro.pennies,
|
||||
"COUNTRY": {},
|
||||
"METRO": {},
|
||||
"COLLECTION_DEFAULT": g.cpm_selfserve_collection.pennies,
|
||||
"SUBREDDIT_DEFAULT": g.cpm_selfserve.pennies,
|
||||
"COUNTRY_DEFAULT": g.cpm_selfserve_collection.pennies,
|
||||
"METRO_DEFAULT": g.cpm_selfserve_geotarget_metro.pennies,
|
||||
}
|
||||
|
||||
try:
|
||||
@@ -667,10 +717,26 @@ class PromotionPrices(tdb_cassandra.View):
|
||||
except tdb_cassandra.NotFoundException:
|
||||
subreddits = {}
|
||||
|
||||
try:
|
||||
countries = cls._cf.get("COUNTRY")
|
||||
except tdb_cassandra.NotFoundException:
|
||||
countries = {}
|
||||
|
||||
try:
|
||||
metros = cls._cf.get("METRO")
|
||||
except tdb_cassandra.NotFoundException:
|
||||
metros = {}
|
||||
|
||||
for name, cpm in collections.iteritems():
|
||||
r["COLLECTION"][name] = cpm
|
||||
|
||||
for name, cpm in subreddits.iteritems():
|
||||
r["SUBREDDIT"][name] = cpm
|
||||
|
||||
for name, cpm in countries.iteritems():
|
||||
r["COUNTRY"][name] = cpm
|
||||
|
||||
for name, cpm in metros.iteritems():
|
||||
r["METRO"][name] = cpm
|
||||
|
||||
return r
|
||||
|
||||
@@ -820,23 +820,34 @@ var exports = r.sponsored = {
|
||||
},
|
||||
|
||||
get_cpm: function($form) {
|
||||
var isMetroGeotarget = $('#metro').val() !== null && !$('#metro').is(':disabled'),
|
||||
isSubreddit = $form.find('input[name="targeting"][value="one"]').is(':checked'),
|
||||
collectionVal = $form.find('input[name="collection"]:checked').val(),
|
||||
isFrontpage = !isSubreddit && collectionVal === 'none',
|
||||
isCollection = !isSubreddit && !isFrontpage,
|
||||
sr = isSubreddit ? $form.find('*[name="sr"]').val() : '',
|
||||
collection = isCollection ? collectionVal : null
|
||||
var isMetroGeotarget = $('#metro').val() !== null && !$('#metro').is(':disabled');
|
||||
var metro = $('#metro').val();
|
||||
var country = $('#country').val();
|
||||
var isGeotarget = country !== '' && !$('#country').is(':disabled');
|
||||
var isSubreddit = $form.find('input[name="targeting"][value="one"]').is(':checked');
|
||||
var collectionVal = $form.find('input[name="collection"]:checked').val();
|
||||
var isFrontpage = !isSubreddit && collectionVal === 'none';
|
||||
var isCollection = !isSubreddit && !isFrontpage;
|
||||
var sr = isSubreddit ? $form.find('*[name="sr"]').val() : '';
|
||||
var collection = isCollection ? collectionVal : null;
|
||||
var prices = [];
|
||||
|
||||
if (isMetroGeotarget) {
|
||||
return this.priceDict.METRO
|
||||
} else if (isFrontpage) {
|
||||
return this.priceDict.COLLECTION_DEFAULT
|
||||
} else if (isCollection) {
|
||||
return this.priceDict.COLLECTION[collection] || this.priceDict.COLLECTION_DEFAULT
|
||||
} else {
|
||||
return this.priceDict.SUBREDDIT[sr] || this.priceDict.SUBREDDIT_DEFAULT
|
||||
var metroKey = metro + country;
|
||||
prices.push(this.priceDict.METRO[metro] || this.priceDict.METRO_DEFAULT);
|
||||
} else if (isGeotarget) {
|
||||
prices.push(this.priceDict.COUNTRY[country] || this.priceDict.COUNTRY_DEFAULT);
|
||||
}
|
||||
|
||||
if (isFrontpage) {
|
||||
prices.push(this.priceDict.COLLECTION_DEFAULT);
|
||||
} else if (isCollection) {
|
||||
prices.push(this.priceDict.COLLECTION[collectionVal] || this.priceDict.COLLECTION_DEFAULT);
|
||||
} else {
|
||||
prices.push(this.priceDict.SUBREDDIT[sr] || this.priceDict.SUBREDDIT_DEFAULT);
|
||||
}
|
||||
|
||||
return _.max(prices);
|
||||
},
|
||||
|
||||
get_targeting: function($form) {
|
||||
|
||||
Reference in New Issue
Block a user