537 lines
13 KiB
Python
537 lines
13 KiB
Python
# coding=UTF-8
|
|
""" Price formulas """
|
|
|
|
from api.lib.utils import round_half_up
|
|
from api.lib.limits import calculate_canvas_limits
|
|
from api.lib import pwinty
|
|
|
|
|
|
def wallpaper_m2_price(
|
|
material,
|
|
market,
|
|
designer=None,
|
|
reseller=None,
|
|
inquiry=None,
|
|
rounded=True,
|
|
inc_vat=True,
|
|
):
|
|
""" calculates price per square meter """
|
|
price = material.price / 100.0
|
|
|
|
if designer:
|
|
price *= (float(designer.pricepremium_wallpaper) / 100) + 1
|
|
|
|
if reseller:
|
|
price *= (float(reseller.pricepremium) / 100) + 1
|
|
|
|
if inquiry:
|
|
price *= (float(inquiry.pricepremium) / 100) + 1
|
|
|
|
price *= market.exchange_rate
|
|
price *= market.price_adjustments
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|
|
|
|
|
|
def wallpaper_price(
|
|
width,
|
|
height,
|
|
material,
|
|
market,
|
|
designer=None,
|
|
reseller=None,
|
|
inquiry=None,
|
|
rounded=True,
|
|
inc_vat=True,
|
|
):
|
|
price = wallpaper_m2_price(
|
|
material, market, designer, reseller, inquiry, rounded=False, inc_vat=False
|
|
)
|
|
|
|
sqm = (width / 100) * (height / 100)
|
|
|
|
if market.name == "US":
|
|
min_sqm = 2
|
|
else:
|
|
min_sqm = 1
|
|
|
|
sqm = max(sqm, min_sqm)
|
|
|
|
price *= sqm
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round(price)
|
|
|
|
return price
|
|
|
|
|
|
def canvas_cm2_price(cm2):
|
|
price_cm2_at_1cm2 = 0.2461
|
|
price_cm2_at_5000cm2 = 0.144
|
|
price_cm2_at_10000cm2 = 0.096
|
|
price_cm2_at_22500cm2 = 0.064
|
|
|
|
if cm2 <= 5000:
|
|
diff = price_cm2_at_1cm2 - price_cm2_at_5000cm2
|
|
discount = (diff / 5000) * cm2
|
|
cm2_price = price_cm2_at_1cm2 - discount
|
|
|
|
elif cm2 > 5000 and cm2 <= 10000:
|
|
diff = price_cm2_at_5000cm2 - price_cm2_at_10000cm2
|
|
discount = (diff / 5000) * (cm2 - 5000)
|
|
cm2_price = price_cm2_at_5000cm2 - discount
|
|
|
|
elif cm2 > 10000:
|
|
diff = price_cm2_at_10000cm2 - price_cm2_at_22500cm2
|
|
discount = (diff / 12500) * (cm2 - 10000)
|
|
cm2_price = price_cm2_at_10000cm2 - discount
|
|
|
|
cm2_price = max(cm2_price, 0.064)
|
|
|
|
return cm2_price
|
|
|
|
|
|
def package_price(product_group, width, height, market):
|
|
if market.name == "US":
|
|
if product_group in ["canvas", "poster"]:
|
|
if width > 110:
|
|
return 150
|
|
else:
|
|
return 100
|
|
return 0
|
|
|
|
|
|
def canvas_price(
|
|
width,
|
|
height,
|
|
market,
|
|
framed=True,
|
|
designer=None,
|
|
reseller=None,
|
|
inquiry=None,
|
|
rounded=True,
|
|
inc_vat=True,
|
|
):
|
|
cm2 = width * height
|
|
|
|
cm2_price = canvas_cm2_price(cm2)
|
|
|
|
# calculate price for canvas with frame
|
|
price = cm2 * cm2_price
|
|
price = max(price, 341.4848) # the price can never go below 341.4848 SEK
|
|
|
|
if not framed:
|
|
price *= 0.7
|
|
|
|
price *= market.price_adjustments
|
|
|
|
if designer:
|
|
price *= (float(designer.pricepremium_canvas) / 100) + 1
|
|
|
|
if reseller:
|
|
price *= (float(reseller.pricepremium) / 100) + 1
|
|
|
|
if inquiry:
|
|
price *= (float(inquiry.pricepremium) / 100) + 1
|
|
|
|
price += package_price("canvas", width, height, market)
|
|
|
|
price *= market.exchange_rate
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|
|
|
|
|
|
def canvas_frame_price(
|
|
width, height, market, reseller=None, rounded=True, inc_vat=True
|
|
):
|
|
width, height = calculate_canvas_limits(width, height, framed=True)
|
|
cm2 = width * height
|
|
cm2_price = canvas_cm2_price(cm2)
|
|
price = cm2 * cm2_price
|
|
price = max(price, 317.44)
|
|
price *= 0.65
|
|
|
|
price *= market.price_adjustments
|
|
|
|
if reseller:
|
|
price *= (float(reseller.pricepremium) / 100) + 1
|
|
|
|
price += package_price("canvas", width, height, market)
|
|
|
|
price *= market.exchange_rate
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|
|
|
|
|
|
def poster_cm2_price(cm2):
|
|
price_cm2_at_1cm2 = 0.1008
|
|
price_cm2_at_5000cm2 = 0.04704
|
|
price_cm2_at_10000cm2 = 0.04032
|
|
price_cm2_at_22500cm2 = 0.0336
|
|
|
|
if cm2 <= 5000:
|
|
diff = price_cm2_at_1cm2 - price_cm2_at_5000cm2
|
|
discount = (diff / 5000) * cm2
|
|
cm2_price = price_cm2_at_1cm2 - discount
|
|
|
|
elif cm2 > 5000 and cm2 <= 10000:
|
|
diff = price_cm2_at_5000cm2 - price_cm2_at_10000cm2
|
|
discount = (diff / 5000) * (cm2 - 5000)
|
|
cm2_price = price_cm2_at_5000cm2 - discount
|
|
|
|
elif cm2 > 10000:
|
|
diff = price_cm2_at_10000cm2 - price_cm2_at_22500cm2
|
|
discount = (diff / 12500) * (cm2 - 10000)
|
|
cm2_price = price_cm2_at_10000cm2 - discount
|
|
|
|
cm2_price = max(cm2_price, 0.028)
|
|
|
|
return cm2_price
|
|
|
|
|
|
def poster_price(
|
|
width,
|
|
height,
|
|
market,
|
|
hanger=True,
|
|
designer=None,
|
|
reseller=None,
|
|
inquiry=None,
|
|
rounded=True,
|
|
inc_vat=True,
|
|
):
|
|
cm2 = width * height
|
|
cm2_price = poster_cm2_price(cm2)
|
|
price = cm2 * cm2_price
|
|
price = max(price, 200) # the price can never go below 200 SEK
|
|
|
|
if hanger:
|
|
price += _price_for_poster_hanger_size(width)
|
|
|
|
price *= market.price_adjustments
|
|
|
|
if designer:
|
|
price *= (float(designer.pricepremium_poster) / 100) + 1
|
|
|
|
if reseller:
|
|
price *= (float(reseller.pricepremium) / 100) + 1
|
|
|
|
if inquiry:
|
|
price *= (float(inquiry.pricepremium) / 100) + 1
|
|
|
|
price += package_price("poster", width, height, market)
|
|
|
|
price *= market.exchange_rate
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|
|
|
|
|
|
def poster_hanger_price(width, market, reseller=None, rounded=True, inc_vat=True):
|
|
"""calculates price for poster hanger only"""
|
|
price = _price_for_poster_hanger_size(width)
|
|
price += 50 # add 50 SEK extra since they are buying only the hanger
|
|
|
|
price *= market.price_adjustments
|
|
|
|
if reseller:
|
|
price *= (float(reseller.pricepremium) / 100) + 1
|
|
|
|
price += package_price(
|
|
"poster", width, 10, market
|
|
) # we assume the poster hanger has a height of 10cm here
|
|
|
|
price *= market.exchange_rate
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|
|
|
|
|
|
def _price_for_poster_hanger_size(size):
|
|
if size > 0 and size <= 30:
|
|
return 83
|
|
if size > 30 and size <= 50:
|
|
return 118
|
|
if size > 50 and size <= 60:
|
|
return 125
|
|
if size > 60 and size <= 70:
|
|
return 132
|
|
if size > 70 and size <= 100:
|
|
return 192
|
|
if size > 100 and size <= 125:
|
|
return 218
|
|
if size > 125 and size <= 150:
|
|
return 262
|
|
|
|
raise ValueError("Invalid poster hanger size: {}".format(size))
|
|
|
|
|
|
def framed_print_price(
|
|
sku, market, designer=None, reseller=None, inquiry=None, rounded=True, inc_vat=True
|
|
):
|
|
sku_prices = {
|
|
pwinty.GLOBAL_CFP_12x12: 446,
|
|
pwinty.GLOBAL_CFP_11x14: 478,
|
|
pwinty.GLOBAL_CFP_12x16: 494,
|
|
pwinty.GLOBAL_CFP_16x20: 574,
|
|
pwinty.GLOBAL_CFP_20x20: 690,
|
|
pwinty.GLOBAL_CFP_18x24: 708,
|
|
pwinty.GLOBAL_CFP_20x28: 761,
|
|
pwinty.GLOBAL_CFP_24x32: 831,
|
|
pwinty.GLOBAL_CFP_28x28: 867,
|
|
pwinty.GLOBAL_CFP_24x36: 1035,
|
|
pwinty.GLOBAL_CFP_28x40: 1127,
|
|
}
|
|
|
|
if not sku in sku_prices:
|
|
raise ValueError("Invalid SKU number: {}".format(sku))
|
|
|
|
price = sku_prices[sku]
|
|
|
|
# add extra shipping price (in SEK)
|
|
extra_shipping_price = {
|
|
pwinty.GLOBAL_CFP_11x14: { # 28x36
|
|
"US": 167,
|
|
"NO": 247,
|
|
"FI": 85,
|
|
"PL": 102,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_12x16: { # 30x40
|
|
"US": 167,
|
|
"NO": 247,
|
|
"FI": 85,
|
|
"PL": 102,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_16x20: { # 40x50
|
|
"US": 243,
|
|
"NO": 247,
|
|
"FI": 85,
|
|
"PL": 123,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_18x24: { # 45x60
|
|
"US": 243,
|
|
"NO": 247,
|
|
"FI": 85,
|
|
"PL": 139,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_20x28: { # 50x70
|
|
"US": 472,
|
|
"NO": 371,
|
|
"FI": 85,
|
|
"PL": 150,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_24x32: { # 60x80
|
|
"US": 472,
|
|
"NO": 371,
|
|
"FI": 85,
|
|
"PL": 160,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_24x36: { # 60x90
|
|
"US": 510,
|
|
"NO": 989,
|
|
"FI": 85,
|
|
"PL": 196,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_28x40: { # 70x100
|
|
"US": 510,
|
|
"NO": 989,
|
|
"FI": 85,
|
|
"PL": 211,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_12x12: { # 30x30
|
|
"US": 167,
|
|
"NO": 247,
|
|
"FI": 85,
|
|
"PL": 102,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_20x20: { # 50x50
|
|
"US": 243,
|
|
"NO": 247,
|
|
"FI": 85,
|
|
"PL": 123,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
pwinty.GLOBAL_CFP_28x28: { # 70x70
|
|
"US": 472,
|
|
"NO": 371,
|
|
"FI": 85,
|
|
"PL": 150,
|
|
"ES": 63,
|
|
"SE": 32,
|
|
},
|
|
}
|
|
|
|
price += extra_shipping_price[sku].get(market.name, 0)
|
|
|
|
price *= market.price_adjustments
|
|
|
|
if designer:
|
|
price *= (float(designer.pricepremium_framed_print) / 100) + 1
|
|
|
|
if reseller:
|
|
price *= (float(reseller.pricepremium) / 100) + 1
|
|
|
|
if inquiry:
|
|
price *= (float(inquiry.pricepremium) / 100) + 1
|
|
|
|
price *= market.exchange_rate
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|
|
|
|
|
|
def inquiry_price(
|
|
inquiry, inc_price_retouch=True, rounded=True, inc_vat=True, **kwargs
|
|
):
|
|
width = kwargs.get("width", inquiry.width)
|
|
height = kwargs.get("height", inquiry.height)
|
|
material = kwargs.get("material", inquiry.material)
|
|
framed = kwargs.get("framed", inquiry.framed)
|
|
hanger = kwargs.get("hanger", inquiry.hanger)
|
|
sku = kwargs.get("sku")
|
|
reseller = kwargs.get("reseller", inquiry.dealer_store)
|
|
|
|
if inquiry.product_group == "photo-wallpaper":
|
|
price = wallpaper_price(
|
|
width,
|
|
height,
|
|
material,
|
|
inquiry.market,
|
|
designer=inquiry.designer,
|
|
reseller=reseller,
|
|
inquiry=inquiry,
|
|
rounded=False,
|
|
inc_vat=False,
|
|
)
|
|
elif inquiry.product_group == "canvas":
|
|
price = canvas_price(
|
|
width,
|
|
height,
|
|
inquiry.market,
|
|
designer=inquiry.designer,
|
|
reseller=reseller,
|
|
inquiry=inquiry,
|
|
framed=framed,
|
|
rounded=False,
|
|
inc_vat=False,
|
|
)
|
|
elif inquiry.product_group == "poster" and not sku:
|
|
price = poster_price(
|
|
width,
|
|
height,
|
|
inquiry.market,
|
|
designer=inquiry.designer,
|
|
reseller=reseller,
|
|
inquiry=inquiry,
|
|
hanger=hanger,
|
|
rounded=False,
|
|
inc_vat=False,
|
|
)
|
|
# Framed prints product group for inquires will be poster until addToCart but always has sku
|
|
elif sku:
|
|
price = framed_print_price(
|
|
sku=sku,
|
|
market=inquiry.market,
|
|
designer=inquiry.designer,
|
|
reseller=reseller,
|
|
inquiry=inquiry,
|
|
rounded=False,
|
|
inc_vat=False,
|
|
)
|
|
else:
|
|
raise ValueError("Invalid product group: {}".format(inquiry.product_group))
|
|
|
|
effect_price = inquiry.price_effect
|
|
if effect_price:
|
|
price += float(effect_price)
|
|
|
|
if inc_price_retouch:
|
|
retouch_price = inquiry.local_price_retouch(rounded=False, inc_vat=False)
|
|
if retouch_price:
|
|
price += retouch_price
|
|
|
|
if inc_vat:
|
|
price *= inquiry.market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|
|
|
|
def wallpaper_kit_price(
|
|
market, reseller=None, rounded=True, inc_vat=True
|
|
):
|
|
# Hardcode price as it hasn't been updated for a long time
|
|
# price from "product-stockprices"
|
|
price = 143.2
|
|
|
|
price *= market.price_adjustments
|
|
|
|
if reseller:
|
|
price *= (float(reseller.pricepremium) / 100) + 1
|
|
|
|
price *= market.exchange_rate
|
|
|
|
if inc_vat:
|
|
price *= market.vat
|
|
|
|
if rounded:
|
|
price = round_half_up(price)
|
|
|
|
return price
|