Add new pricing system (#65)
This commit is contained in:
@@ -3,6 +3,33 @@
|
|||||||
from api.lib.utils import round_half_up
|
from api.lib.utils import round_half_up
|
||||||
from api.models.external_print_product import get_external_print_product
|
from api.models.external_print_product import get_external_print_product
|
||||||
from api.models.price_adjustments import get_price_adjustment
|
from api.models.price_adjustments import get_price_adjustment
|
||||||
|
from api.models.prices import get_wallpaper_m2_price, get_external_product_price, get_own_image_wallpaper_m2_price, get_external_product_own_image_price
|
||||||
|
|
||||||
|
|
||||||
|
def wallpaper_m2_price_new(
|
||||||
|
product_id,
|
||||||
|
material_id,
|
||||||
|
market,
|
||||||
|
inquiry=None,
|
||||||
|
):
|
||||||
|
own_image = inquiry is not None and inquiry.productId is None
|
||||||
|
|
||||||
|
if own_image:
|
||||||
|
price_m2_incl_vat = get_own_image_wallpaper_m2_price(material_id, market.id)
|
||||||
|
else:
|
||||||
|
price_m2_incl_vat = get_wallpaper_m2_price(product_id, material_id, market.id)
|
||||||
|
|
||||||
|
price_m2_excl_vat = price_m2_incl_vat / market.vat
|
||||||
|
|
||||||
|
if inquiry:
|
||||||
|
inquiry_premium = (float(inquiry.pricepremium) / 100) + 1
|
||||||
|
price_m2_excl_vat = price_m2_excl_vat * inquiry_premium
|
||||||
|
price_m2_incl_vat = price_m2_excl_vat * market.vat
|
||||||
|
|
||||||
|
return {
|
||||||
|
"incl_vat": price_m2_incl_vat,
|
||||||
|
"excl_vat": price_m2_excl_vat,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def wallpaper_m2_price(
|
def wallpaper_m2_price(
|
||||||
@@ -41,6 +68,34 @@ def wallpaper_m2_price(
|
|||||||
return price
|
return price
|
||||||
|
|
||||||
|
|
||||||
|
def wallpaper_price_new(
|
||||||
|
product_id,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
material,
|
||||||
|
market,
|
||||||
|
inquiry=None,
|
||||||
|
):
|
||||||
|
m2_prices = wallpaper_m2_price_new(product_id, material.id, market, inquiry)
|
||||||
|
|
||||||
|
sqm = (width / 100) * (height / 100)
|
||||||
|
|
||||||
|
min_sqm = 1
|
||||||
|
|
||||||
|
sqm = max(sqm, min_sqm)
|
||||||
|
|
||||||
|
price_excl_vat = m2_prices["excl_vat"] * sqm
|
||||||
|
|
||||||
|
price_incl_vat = price_excl_vat * market.vat
|
||||||
|
|
||||||
|
return {
|
||||||
|
"incl_vat": price_incl_vat,
|
||||||
|
"excl_vat": price_excl_vat,
|
||||||
|
"m2_price_incl_vat": m2_prices["incl_vat"],
|
||||||
|
"m2_price_excl_vat": m2_prices["excl_vat"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def wallpaper_price(
|
def wallpaper_price(
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
@@ -86,6 +141,28 @@ def _designer_pricepremium(designer, group_id):
|
|||||||
raise ValueError("Unexpected group id: {}".format(group_id))
|
raise ValueError("Unexpected group id: {}".format(group_id))
|
||||||
|
|
||||||
|
|
||||||
|
def external_product_own_image_price(external_product_id, market):
|
||||||
|
price_incl_vat = get_external_product_own_image_price(external_product_id, market.id)
|
||||||
|
|
||||||
|
price_excl_vat = price_incl_vat / market.vat
|
||||||
|
|
||||||
|
return {
|
||||||
|
'incl_vat': price_incl_vat,
|
||||||
|
'excl_vat': price_excl_vat,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def external_product_price_new(product_id, external_product_id, market):
|
||||||
|
price_incl_vat = get_external_product_price(product_id, external_product_id, market.id)
|
||||||
|
|
||||||
|
price_excl_vat = price_incl_vat / market.vat
|
||||||
|
|
||||||
|
return {
|
||||||
|
'incl_vat': price_incl_vat,
|
||||||
|
'excl_vat': price_excl_vat,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def external_product_price(
|
def external_product_price(
|
||||||
id, market, designer=None, inquiry=None, rounded=True, inc_vat=True
|
id, market, designer=None, inquiry=None, rounded=True, inc_vat=True
|
||||||
):
|
):
|
||||||
@@ -112,6 +189,54 @@ def external_product_price(
|
|||||||
return price
|
return price
|
||||||
|
|
||||||
|
|
||||||
|
def inquiry_price_new(
|
||||||
|
inquiry, **kwargs
|
||||||
|
):
|
||||||
|
width = kwargs.get("width", inquiry.width)
|
||||||
|
height = kwargs.get("height", inquiry.height)
|
||||||
|
material = kwargs.get("material", inquiry.material)
|
||||||
|
external_id = kwargs.get("external_id")
|
||||||
|
|
||||||
|
product_id = inquiry.productId
|
||||||
|
is_own_image = product_id is None
|
||||||
|
|
||||||
|
if external_id:
|
||||||
|
if not is_own_image:
|
||||||
|
raise ValueError("Manual inquiries only available for wallpapers")
|
||||||
|
prices = external_product_own_image_price(external_id, inquiry.market)
|
||||||
|
return prices
|
||||||
|
elif inquiry.product_group == "photo-wallpaper":
|
||||||
|
if is_own_image:
|
||||||
|
prices = wallpaper_price_new(None, width, height, material, inquiry.market, inquiry)
|
||||||
|
else:
|
||||||
|
prices = wallpaper_price_new(product_id, width, height, material, inquiry.market, inquiry)
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid product group: {}".format(inquiry.product_group))
|
||||||
|
|
||||||
|
price_excl_vat = prices["excl_vat"]
|
||||||
|
effect_price = inquiry.price_effect
|
||||||
|
if effect_price:
|
||||||
|
price_excl_vat += float(effect_price)
|
||||||
|
|
||||||
|
price_excl_retouch_excl_vat = price_excl_vat
|
||||||
|
price_excl_retouch_incl_vat = price_excl_retouch_excl_vat * inquiry.market.vat
|
||||||
|
|
||||||
|
retouch_price = inquiry.local_price_retouch(rounded=False, inc_vat=False)
|
||||||
|
if retouch_price:
|
||||||
|
price_excl_vat += retouch_price
|
||||||
|
|
||||||
|
price_incl_vat = price_excl_vat * inquiry.market.vat
|
||||||
|
|
||||||
|
return {
|
||||||
|
"incl_vat": price_incl_vat,
|
||||||
|
"excl_vat": price_excl_vat,
|
||||||
|
"excl_retouch_incl_vat": price_excl_retouch_incl_vat,
|
||||||
|
"excl_retouch_excl_vat": price_excl_retouch_excl_vat,
|
||||||
|
"m2_price_incl_vat": prices["m2_price_incl_vat"],
|
||||||
|
"m2_price_excl_vat": prices["m2_price_excl_vat"],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def inquiry_price(
|
def inquiry_price(
|
||||||
inquiry, inc_price_retouch=True, rounded=True, inc_vat=True, **kwargs
|
inquiry, inc_price_retouch=True, rounded=True, inc_vat=True, **kwargs
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -30,7 +30,13 @@ def get_external_print_product(id):
|
|||||||
return external_product
|
return external_product
|
||||||
|
|
||||||
|
|
||||||
def get_cheapest_canvas_product():
|
def get_cheapest_canvas_product(new_version):
|
||||||
|
if new_version:
|
||||||
|
# We simply return the smallest size, assuming that is also the cheapest.
|
||||||
|
# It is technically possible that a larger size is cheaper, but unlikely, so we avoid the extra complexity
|
||||||
|
# of calculating the guaranteed cheapest product.
|
||||||
|
return 'canvas_200x300-mm-8x12-inch_canvas_wood-fsc-slim_4-0_ver'
|
||||||
|
|
||||||
sql = "select external_product_id from external_print_products where group_id = 2 order by price_sek limit 1"
|
sql = "select external_product_id from external_print_products where group_id = 2 order by price_sek limit 1"
|
||||||
result = db.session.execute(sql)
|
result = db.session.execute(sql)
|
||||||
external_id = result.first()[0]
|
external_id = result.first()[0]
|
||||||
@@ -38,7 +44,10 @@ def get_cheapest_canvas_product():
|
|||||||
return external_id
|
return external_id
|
||||||
|
|
||||||
|
|
||||||
def get_cheapest_poster_product():
|
def get_cheapest_poster_product(new_version):
|
||||||
|
if new_version:
|
||||||
|
return 'flat_250x250-mm-10x10-inch_200-gsm-80lb-uncoated_4-0_ver'
|
||||||
|
|
||||||
sql = "select external_product_id from external_print_products where group_id in (7,8) order by price_sek limit 1"
|
sql = "select external_product_id from external_print_products where group_id in (7,8) order by price_sek limit 1"
|
||||||
result = db.session.execute(sql)
|
result = db.session.execute(sql)
|
||||||
external_id = result.first()[0]
|
external_id = result.first()[0]
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ class Inquiry(db.Model):
|
|||||||
return 0
|
return 0
|
||||||
price = float(self.price_retouch)
|
price = float(self.price_retouch)
|
||||||
price *= self.market.exchange_rate
|
price *= self.market.exchange_rate
|
||||||
|
# Todo: review if the retouch price should no longer use the price_adjustments value
|
||||||
price *= self.market.price_adjustments
|
price *= self.market.price_adjustments
|
||||||
if inc_vat:
|
if inc_vat:
|
||||||
price *= self.market.vat
|
price *= self.market.vat
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# coding=UTF-8
|
||||||
|
|
||||||
|
from api.extensions import db
|
||||||
|
|
||||||
|
|
||||||
|
def get_wallpaper_m2_price(product_id, material_id, market_id):
|
||||||
|
sql = """
|
||||||
|
select
|
||||||
|
price
|
||||||
|
from
|
||||||
|
v_price_product_segments v
|
||||||
|
join prices_wallpaper_m2 p on v.segment_id = p.segment_id
|
||||||
|
where
|
||||||
|
productid = :product_id and market_id = :market_id and material_id = :material_id
|
||||||
|
order by priority desc
|
||||||
|
limit 1;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = db.session.execute(sql, {
|
||||||
|
"product_id": product_id,
|
||||||
|
"market_id": market_id,
|
||||||
|
"material_id": material_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
rows = result.fetchall()
|
||||||
|
for row in rows:
|
||||||
|
price = row[0]
|
||||||
|
return float(price)
|
||||||
|
|
||||||
|
raise Exception("Failed reading wallpaper m2 price")
|
||||||
|
|
||||||
|
|
||||||
|
def get_external_product_price(product_id, external_product_id, market_id):
|
||||||
|
sql = """
|
||||||
|
select
|
||||||
|
price
|
||||||
|
from
|
||||||
|
v_price_product_segments v
|
||||||
|
join prices_external_products p on v.segment_id = p.segment_id
|
||||||
|
where
|
||||||
|
productid = :product_id and market_id = :market_id and external_product_id = :external_id
|
||||||
|
order by priority desc
|
||||||
|
limit 1;
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = db.session.execute(sql, {
|
||||||
|
"product_id": product_id,
|
||||||
|
"market_id": market_id,
|
||||||
|
"external_id": external_product_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
rows = result.fetchall()
|
||||||
|
for row in rows:
|
||||||
|
price = row[0]
|
||||||
|
return float(price)
|
||||||
|
|
||||||
|
raise Exception("Failed reading external product price")
|
||||||
|
|
||||||
|
|
||||||
|
def get_own_image_wallpaper_m2_price(material_id, market_id):
|
||||||
|
sql = """
|
||||||
|
select
|
||||||
|
price
|
||||||
|
from
|
||||||
|
prices_wallpaper_m2
|
||||||
|
where
|
||||||
|
market_id = :market_id and material_id = :material_id
|
||||||
|
and segment_id = (select id from price_segments where name = 'OWN-IMAGE')
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = db.session.execute(sql, {
|
||||||
|
"market_id": market_id,
|
||||||
|
"material_id": material_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
rows = result.fetchall()
|
||||||
|
for row in rows:
|
||||||
|
price = row[0]
|
||||||
|
return float(price)
|
||||||
|
|
||||||
|
raise Exception("Failed reading own image wallpaper m2 price")
|
||||||
|
|
||||||
|
|
||||||
|
def get_external_product_own_image_price(external_product_id, market_id):
|
||||||
|
sql = """
|
||||||
|
select
|
||||||
|
price
|
||||||
|
from
|
||||||
|
prices_external_products
|
||||||
|
where
|
||||||
|
market_id = :market_id and external_product_id = :external_id
|
||||||
|
and segment_id = (select id from price_segments where name = 'OWN-IMAGE')
|
||||||
|
"""
|
||||||
|
|
||||||
|
result = db.session.execute(sql, {
|
||||||
|
"market_id": market_id,
|
||||||
|
"external_id": external_product_id,
|
||||||
|
})
|
||||||
|
|
||||||
|
rows = result.fetchall()
|
||||||
|
for row in rows:
|
||||||
|
price = row[0]
|
||||||
|
return float(price)
|
||||||
|
|
||||||
|
raise Exception("Failed reading external product own image price")
|
||||||
+77
-10
@@ -15,6 +15,9 @@ from api.lib.prices import (
|
|||||||
inquiry_price,
|
inquiry_price,
|
||||||
wallpaper_kit_price,
|
wallpaper_kit_price,
|
||||||
external_product_price,
|
external_product_price,
|
||||||
|
wallpaper_price_new,
|
||||||
|
external_product_price_new,
|
||||||
|
inquiry_price_new,
|
||||||
)
|
)
|
||||||
|
|
||||||
mod = Blueprint("prices", __name__, url_prefix="/prices")
|
mod = Blueprint("prices", __name__, url_prefix="/prices")
|
||||||
@@ -45,6 +48,8 @@ def wallpaper():
|
|||||||
width = request.args.get("width", type=int)
|
width = request.args.get("width", type=int)
|
||||||
height = request.args.get("height", type=int)
|
height = request.args.get("height", type=int)
|
||||||
market_id = request.args.get("market", type=int)
|
market_id = request.args.get("market", type=int)
|
||||||
|
product_id = request.args.get("product", type=int)
|
||||||
|
new_version = request.args.get("new_version") is not None
|
||||||
market = Market.query.get_or_404(market_id)
|
market = Market.query.get_or_404(market_id)
|
||||||
designer = get_designer()
|
designer = get_designer()
|
||||||
reseller = get_reseller()
|
reseller = get_reseller()
|
||||||
@@ -55,6 +60,20 @@ def wallpaper():
|
|||||||
materials = Material.query.wallpapers().all()
|
materials = Material.query.wallpapers().all()
|
||||||
data = []
|
data = []
|
||||||
for material in materials:
|
for material in materials:
|
||||||
|
if new_version:
|
||||||
|
prices = wallpaper_price_new(product_id, width, height, material, market)
|
||||||
|
data.append(
|
||||||
|
{
|
||||||
|
"material": material.name,
|
||||||
|
"material_id": material.id,
|
||||||
|
"m2_price": prices["m2_price_incl_vat"],
|
||||||
|
"m2_price_excl_vat": prices["m2_price_excl_vat"],
|
||||||
|
"price": prices["incl_vat"],
|
||||||
|
"price_excl_vat": prices["excl_vat"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
data.append(
|
data.append(
|
||||||
{
|
{
|
||||||
"material": material.name,
|
"material": material.name,
|
||||||
@@ -139,7 +158,7 @@ def get_inquiry_measurements(inquiry):
|
|||||||
return width, height
|
return width, height
|
||||||
|
|
||||||
|
|
||||||
def inquiry_wallpaper(inquiry):
|
def inquiry_wallpaper(inquiry, new_version=False):
|
||||||
width, height = get_inquiry_measurements(inquiry)
|
width, height = get_inquiry_measurements(inquiry)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
@@ -152,6 +171,22 @@ def inquiry_wallpaper(inquiry):
|
|||||||
materials = Material.query.wallpapers().all()
|
materials = Material.query.wallpapers().all()
|
||||||
prices = []
|
prices = []
|
||||||
for material in materials:
|
for material in materials:
|
||||||
|
if new_version:
|
||||||
|
price = inquiry_price_new(inquiry, material=material, width=width, height=height)
|
||||||
|
prices.append(
|
||||||
|
{
|
||||||
|
"material": material.name,
|
||||||
|
"material_id": material.id,
|
||||||
|
"m2_price": price["m2_price_incl_vat"],
|
||||||
|
"m2_price_excl_vat": price["m2_price_excl_vat"],
|
||||||
|
"inquiry_price": price["incl_vat"],
|
||||||
|
"inquiry_price_excl_vat": price["excl_vat"],
|
||||||
|
"inquiry_price_excl_retouch": price["excl_retouch_incl_vat"],
|
||||||
|
"inquiry_price_excl_retouch_excl_vat": price["excl_retouch_excl_vat"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
prices.append(
|
prices.append(
|
||||||
{
|
{
|
||||||
"material": material.name,
|
"material": material.name,
|
||||||
@@ -215,7 +250,24 @@ def inquiry_wallpaper(inquiry):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def inquiry_external_product(inquiry, external_id):
|
def inquiry_external_product(inquiry, external_id, new_version):
|
||||||
|
if new_version:
|
||||||
|
result = inquiry_price_new(inquiry, external_id=external_id)
|
||||||
|
data = {
|
||||||
|
"id": inquiry.id,
|
||||||
|
# No manual inquiries for external products, hence no retouch price
|
||||||
|
"retouch_price": 0,
|
||||||
|
"prices": [
|
||||||
|
{
|
||||||
|
"inquiry_price": result["incl_vat"],
|
||||||
|
"inquiry_price_excl_vat": result["excl_vat"],
|
||||||
|
"inquiry_price_excl_retouch": result["incl_vat"],
|
||||||
|
"inquiry_price_excl_retouch_excl_vat": result["excl_vat"],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"id": inquiry.id,
|
"id": inquiry.id,
|
||||||
"retouch_price": inquiry.local_price_retouch(rounded=False, inc_vat=True),
|
"retouch_price": inquiry.local_price_retouch(rounded=False, inc_vat=True),
|
||||||
@@ -245,19 +297,20 @@ def inquiry(inquiry_id):
|
|||||||
inquiry = Inquiry.query.get_or_404(inquiry_id)
|
inquiry = Inquiry.query.get_or_404(inquiry_id)
|
||||||
external_product_id = request.args.get("external_product_id")
|
external_product_id = request.args.get("external_product_id")
|
||||||
listprice = request.args.get("listprice")
|
listprice = request.args.get("listprice")
|
||||||
|
new_version = request.args.get("new_version") is not None
|
||||||
|
|
||||||
if (listprice):
|
if listprice:
|
||||||
if (listprice == 'canvas'):
|
if listprice == 'canvas':
|
||||||
external_product_id = get_cheapest_canvas_product()
|
external_product_id = get_cheapest_canvas_product(new_version)
|
||||||
elif (listprice == 'poster'):
|
elif listprice == 'poster':
|
||||||
external_product_id = get_cheapest_poster_product()
|
external_product_id = get_cheapest_poster_product(new_version)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid listprice group {}".format(listprice))
|
raise ValueError("Invalid listprice group {}".format(listprice))
|
||||||
|
|
||||||
if external_product_id:
|
if external_product_id:
|
||||||
data = inquiry_external_product(inquiry, external_product_id)
|
data = inquiry_external_product(inquiry, external_product_id, new_version)
|
||||||
elif inquiry.product_group == "photo-wallpaper":
|
elif inquiry.product_group == "photo-wallpaper":
|
||||||
data = inquiry_wallpaper(inquiry)
|
data = inquiry_wallpaper(inquiry, new_version)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Invalid group {}".format(inquiry.product_group))
|
raise ValueError("Invalid group {}".format(inquiry.product_group))
|
||||||
|
|
||||||
@@ -270,8 +323,22 @@ def inquiry(inquiry_id):
|
|||||||
def external_product():
|
def external_product():
|
||||||
market_id = request.args.get("market", type=int)
|
market_id = request.args.get("market", type=int)
|
||||||
market = Market.query.get_or_404(market_id)
|
market = Market.query.get_or_404(market_id)
|
||||||
designer = get_designer()
|
|
||||||
id = request.args.get("id", type=str)
|
id = request.args.get("id", type=str)
|
||||||
|
new_version = request.args.get("new_version") is not None
|
||||||
|
|
||||||
|
if new_version:
|
||||||
|
product_id = request.args.get("product", type=int)
|
||||||
|
prices = external_product_price_new(product_id, id, market)
|
||||||
|
data = [
|
||||||
|
{
|
||||||
|
"id": id,
|
||||||
|
"price": prices["incl_vat"],
|
||||||
|
"price_excl_vat": prices['excl_vat']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return jsonify(data=data)
|
||||||
|
|
||||||
|
designer = get_designer()
|
||||||
|
|
||||||
data = [
|
data = [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user