# 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