P5-2777 add poster price calculations
This commit is contained in:
@@ -50,6 +50,7 @@ def wallpaper_price(width, height, material, market, designer=None, reseller=Non
|
||||
|
||||
if rounded:
|
||||
price = round(price)
|
||||
|
||||
return price
|
||||
|
||||
|
||||
@@ -75,6 +76,7 @@ def canvas_cm2_price(cm2):
|
||||
cm2_price = price_cm2_at_10000cm2 - discount
|
||||
|
||||
cm2_price = max(cm2_price, 0.064)
|
||||
|
||||
return cm2_price
|
||||
|
||||
|
||||
@@ -146,6 +148,106 @@ def canvas_frame_price(width, height, market, reseller=None, rounded=True, inc_v
|
||||
return price
|
||||
|
||||
|
||||
def poster_cm2_price(cm2):
|
||||
price_cm2_at_1cm2 = 0.084
|
||||
price_cm2_at_5000cm2 = 0.0392
|
||||
price_cm2_at_10000cm2 = 0.0336
|
||||
price_cm2_at_22500cm2 = 0.028
|
||||
|
||||
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, 134.4) # the price can never go below 134.4 SEK
|
||||
|
||||
if(hanger):
|
||||
price += _price_for_poster_hanger_size(width)
|
||||
|
||||
price *= market.price_adjustments
|
||||
|
||||
price += package_price(width, height, market)
|
||||
|
||||
if designer:
|
||||
price *= (float(designer.pricepremium) / 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 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
|
||||
price += package_price(width, 10, market) # we assume the poster hanger has a height of 10cm here
|
||||
|
||||
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
|
||||
|
||||
|
||||
def _price_for_poster_hanger_size(size):
|
||||
if size > 0 and size <= 30:
|
||||
return 95.2
|
||||
if size > 30 and size <= 50:
|
||||
return 135.2
|
||||
if size > 50 and size <= 60:
|
||||
return 143.2
|
||||
if size > 60 and size <= 70:
|
||||
return 151.2
|
||||
if size > 70 and size <= 100:
|
||||
return 220
|
||||
if size > 100 and size <= 125:
|
||||
return 250
|
||||
if size > 125 and size <= 150:
|
||||
return 300
|
||||
|
||||
raise ValueError('Invalid poster hanger size: {}'.format(size))
|
||||
|
||||
|
||||
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)
|
||||
|
||||
+49
-2
@@ -5,7 +5,15 @@ from api.models.inquiry import Inquiry
|
||||
from api.models.product import Material, Product
|
||||
from api.models.contract_customer import ContractCustomer
|
||||
from api.models import market as market_model
|
||||
from api.lib.prices import wallpaper_price, canvas_price, canvas_frame_price, m2_price, inquiry_price
|
||||
from api.lib.prices import (
|
||||
wallpaper_price,
|
||||
canvas_price,
|
||||
canvas_frame_price,
|
||||
poster_price,
|
||||
poster_hanger_price,
|
||||
m2_price,
|
||||
inquiry_price,
|
||||
)
|
||||
from api.lib.limits import calculate_canvas_limits
|
||||
|
||||
mod = Blueprint('prices', __name__, url_prefix='/prices')
|
||||
@@ -70,7 +78,6 @@ def canvas():
|
||||
request.args.get('height', type=int),
|
||||
framed
|
||||
)
|
||||
# def canvas_price(width, height, market, framed=True, designer=None, reseller=None, inquiry=None, rounded=True, inc_vat=True):
|
||||
|
||||
data.append({
|
||||
'framed': framed,
|
||||
@@ -83,6 +90,30 @@ def canvas():
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@mod.route('/poster', methods=['GET'])
|
||||
@validate_number('width', 'height')
|
||||
@validate_territory('territory')
|
||||
def poster():
|
||||
width = request.args.get('width', type=int)
|
||||
height = request.args.get('height', type=int)
|
||||
market = market_model.from_territory(request.args.get('territory'))
|
||||
reseller = get_reseller()
|
||||
designer = get_designer()
|
||||
|
||||
data = []
|
||||
|
||||
for hanger in [True, False]:
|
||||
data.append({
|
||||
'hanger': hanger,
|
||||
'width': width,
|
||||
'height': height,
|
||||
'price': poster_price(width, height, market, hanger=hanger, designer=designer, reseller=reseller, rounded=False, inc_vat=True),
|
||||
'price_excl_vat': poster_price(width, height, market, hanger=hanger, designer=designer, reseller=reseller, rounded=False, inc_vat=False),
|
||||
})
|
||||
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
@mod.route('/diy-frame', methods=['GET'])
|
||||
@validate_number('width', 'height')
|
||||
@validate_territory('territory')
|
||||
@@ -104,6 +135,22 @@ def diy_frame():
|
||||
|
||||
return jsonify(data=data)
|
||||
|
||||
@mod.route('/poster-hanger', methods=['GET'])
|
||||
@validate_number('width')
|
||||
@validate_territory('territory')
|
||||
def poster_hanger():
|
||||
width = request.args.get('width', type=int)
|
||||
market = market_model.from_territory(request.args.get('territory'))
|
||||
reseller = get_reseller()
|
||||
|
||||
data = [{
|
||||
'width': width,
|
||||
'price': poster_hanger_price(width, market, reseller=reseller, rounded=False),
|
||||
'price_excl_vat': poster_hanger_price(width, market, reseller=reseller, rounded=False, inc_vat=False)
|
||||
}]
|
||||
|
||||
return jsonify(data=data)
|
||||
|
||||
|
||||
def get_inquiry_measurements(inquiry):
|
||||
""" this function returns width and height to be used in the price calculations """
|
||||
|
||||
+69
-4
@@ -7,7 +7,7 @@ The prices resource provides a simple API to retrive price information about wal
|
||||
Calculate price inc VAT of a wallpaper product. The response will contain prices for all available materials.
|
||||
|
||||
| Parameter | Description |
|
||||
| --------- | -----| -------- | -
|
||||
| --------- | ------------|
|
||||
| `width` | Wallpaper width in cm e.g `100` |
|
||||
| `height` | Wallpaper height in cm e.g `50` |
|
||||
| `territory` | Two letter iso code e.g `SE`. Territory affect the price in different ways like VAT, currency exchanges etc. |
|
||||
@@ -48,7 +48,7 @@ Sample response
|
||||
Calculate price inc VAT of a canvas product. The response will contain information for both framed/not framed canvases. Note that width and height parameters may be adjusted if they go over or under the limits that are valid for a canvas. The values that are used in the price-calculation are always returned in the response.
|
||||
|
||||
| Parameter | Description |
|
||||
| --------- | -----| -------- | -
|
||||
| --------- | ------------|
|
||||
| `width` | Canvas width in cm e.g `100` |
|
||||
| `height` | Canvas height in cm e.g `50` |
|
||||
| `territory` | Two letter iso code e.g `SE`. Territory affect the price in different ways like VAT, currency exchanges etc. |
|
||||
@@ -86,13 +86,50 @@ Sample response
|
||||
}
|
||||
```
|
||||
|
||||
## Calculate poster price
|
||||
|
||||
Calculate price inc VAT of a poster product. The response will contain prices for both with and without hanger.
|
||||
|
||||
| Parameter | Description |
|
||||
| --------- | ------------|
|
||||
| `width` | Poster width in cm e.g `100` |
|
||||
| `height` | Poster height in cm e.g `50` |
|
||||
| `territory` | Two letter iso code e.g `SE`. Territory affect the price in different ways like VAT, currency exchanges etc. |
|
||||
| `dealerurl` | Optional parameter e.g `ackes`. Should always be used when calling the api from a dealerstore. If a dealerstore exists with this url additional fees will be applied to the price. |
|
||||
| `product` | Optional parameter e.g `43894`. If a product with this id exists the api will calculate the price for the given product. |
|
||||
|
||||
Sample request
|
||||
|
||||
`curl -X GET 'https://api2.photowall.com/prices/poster?width=50&height=30&territory=SE&product=46654`
|
||||
|
||||
Sample response
|
||||
```
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"hanger": true,
|
||||
"height": 30,
|
||||
"price": 401.03000000000003,
|
||||
"price_excl_vat": 320.824,
|
||||
"width": 50
|
||||
},
|
||||
{
|
||||
"hanger": false,
|
||||
"height": 30,
|
||||
"price": 199.92000000000002,
|
||||
"price_excl_vat": 159.936,
|
||||
"width": 50
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Calculate "Do it yourself frame" price
|
||||
|
||||
Calculate the price for the "do it yourself frame" (DIY). Note that width and height parameters may be adjusted if they go over or under the limits that are valid for a canvas-frame. The values that are used in the price-calculation are always returned in the response.
|
||||
|
||||
| Parameter | Description |
|
||||
| --------- | -----| -------- | -
|
||||
| --------- | ------------|
|
||||
| `width` | Canvas width in cm e.g `100` |
|
||||
| `height` | Canvas height in cm e.g `50` |
|
||||
| `territory` | Two letter iso code e.g `SE`. Territory affect the price in different ways like VAT, currency exchanges etc. |
|
||||
@@ -116,13 +153,41 @@ Sample response
|
||||
}
|
||||
```
|
||||
|
||||
## Calculate Poster hanger price
|
||||
|
||||
Calculate the price for a poster hanger
|
||||
|
||||
| Parameter | Description |
|
||||
| --------- | ------------|
|
||||
| `width` | Poster hanger width in cm e.g `100` |
|
||||
| `territory` | Two letter iso code e.g `SE`. Territory affect the price in different ways like VAT, currency exchanges etc. |
|
||||
| `dealerurl` | Optional parameter e.g `ackes`. Should always be used when calling the api from a dealerstore. If a dealerstore exists with this url additional fees will be applied to the price. |
|
||||
|
||||
|
||||
Sample request
|
||||
|
||||
`curl -X GET 'https://api2.photowall.com/prices/poster-hanger?width=50&territory=SE`
|
||||
|
||||
Sample response
|
||||
```
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"price": 231.5,
|
||||
"price_excl_vat": 185.2,
|
||||
"width": 50
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Calculate inquiry price
|
||||
|
||||
Calculates the price of an inquiry. For wallpapers inquiries the response will contain price information for all available materials and for canvas it will contain the price for both the framed and the not-framed canvas. The `group` attribute tells which kind of product you are dealing with.
|
||||
The width and height stored on the inquiry will be used in the calculations by default. If you want to override these values you can send in your own width/height parameters in the request.
|
||||
|
||||
| Parameter | Description |
|
||||
| --------- | -----| -------- | -
|
||||
| --------- | ------------|
|
||||
| `width` | Width in cm e.g `100`. Defaults to the inquiry stored width |
|
||||
| `height` | Height in cm e.g `50`. Defaults to the inquiry stored height |
|
||||
|
||||
|
||||
@@ -247,3 +247,19 @@ class TestPrice(unittest2.TestCase):
|
||||
def test_package_price(self):
|
||||
self.assertEqual(800, package_price(150, 40, market=us))
|
||||
self.assertEqual(0, package_price(150, 40, market=sweden))
|
||||
|
||||
def test_poster_cm2_price(self):
|
||||
self.assertEqual(0.08399104, poster_cm2_price(1))
|
||||
self.assertEqual(0.08310400000000001, poster_cm2_price(100))
|
||||
self.assertEqual(0.07504000000000001, poster_cm2_price(1000))
|
||||
self.assertEqual(0.0336, poster_cm2_price(10000))
|
||||
self.assertEqual(0.028, poster_cm2_price(100000))
|
||||
|
||||
def test_poster_price(self):
|
||||
self.assertEqual(287, poster_price(width=30, height=40, hanger=True, market=sweden))
|
||||
self.assertEqual(168, poster_price(width=30, height=40, hanger=False, market=sweden))
|
||||
self.assertEqual(152, poster_price(width=125, height=40, market=us), 'extra cost for large packages')
|
||||
|
||||
def test_poster_hanger_price(self):
|
||||
self.assertEqual(182, poster_hanger_price(30, market=sweden))
|
||||
self.assertEqual(438, poster_hanger_price(150, market=sweden))
|
||||
|
||||
@@ -152,6 +152,35 @@ class TestEndpoints(flask_testing.TestCase):
|
||||
self.assertEqual(50, product['height'])
|
||||
self.assertAlmostEqual(731.25, product['price'], places=2)
|
||||
|
||||
def test_poster(self):
|
||||
response = self.client.get('/prices/poster?width=50&height=30&territory=SE')
|
||||
self.assert200(response)
|
||||
expected = [
|
||||
{
|
||||
'hanger': True,
|
||||
'height': 30,
|
||||
'price': 337.0,
|
||||
'price_excl_vat': 269.6,
|
||||
'width': 50
|
||||
},
|
||||
{
|
||||
'hanger': False,
|
||||
'height': 30,
|
||||
'price': 168.0,
|
||||
'price_excl_vat': 134.4,
|
||||
'width': 50
|
||||
}
|
||||
]
|
||||
self.assertEqual(expected, response.json['data'])
|
||||
|
||||
def test_poster_hanger(self):
|
||||
response = self.client.get('/prices/poster-hanger?width=50&territory=SE')
|
||||
self.assert200(response)
|
||||
product = response.json['data'][0]
|
||||
self.assertEqual(231.5, product['price'])
|
||||
self.assertEqual(185.2, product['price_excl_vat'])
|
||||
self.assertEqual(50, product['width'])
|
||||
|
||||
def test_inquiry_wallpaper(self):
|
||||
self._add_material('standard-wallpaper', 1, 236)
|
||||
self._add_material('premium-wallpaper', 1, 260)
|
||||
|
||||
Reference in New Issue
Block a user