diff --git a/api/lib/prices.py b/api/lib/prices.py index dd0b848..f7490c0 100644 --- a/api/lib/prices.py +++ b/api/lib/prices.py @@ -3,6 +3,7 @@ from api.lib.utils import round_half_up from api.lib.limits import calculate_canvas_limits +from api.lib import pwinty def m2_price( @@ -300,17 +301,17 @@ def framed_print_price( sku, market, designer=None, reseller=None, inquiry=None, rounded=True, inc_vat=True ): sku_prices = { - "GLOBAL-CFP-12x12": 446, - "GLOBAL-CFP-11x14": 478, - "GLOBAL-CFP-12x16": 494, - "GLOBAL-CFP-16x20": 574, - "GLOBAL-CFP-20x20": 690, - "GLOBAL-CFP-18x24": 708, - "GLOBAL-CFP-20x28": 761, - "GLOBAL-CFP-24x32": 831, - "GLOBAL-CFP-28x28": 867, - "GLOBAL-CFP-24x36": 1035, - "GLOBAL-CFP-28x40": 1127, + 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: diff --git a/api/lib/pwinty.py b/api/lib/pwinty.py new file mode 100644 index 0000000..e391027 --- /dev/null +++ b/api/lib/pwinty.py @@ -0,0 +1,25 @@ +GLOBAL_CFP_12x12 = "GLOBAL-CFP-12x12" +GLOBAL_CFP_11x14 = "GLOBAL-CFP-11x14" +GLOBAL_CFP_12x16 = "GLOBAL-CFP-12x16" +GLOBAL_CFP_16x20 = "GLOBAL-CFP-16x20" +GLOBAL_CFP_20x20 = "GLOBAL-CFP-20x20" +GLOBAL_CFP_18x24 = "GLOBAL-CFP-18x24" +GLOBAL_CFP_20x28 = "GLOBAL-CFP-20x28" +GLOBAL_CFP_24x32 = "GLOBAL-CFP-24x32" +GLOBAL_CFP_28x28 = "GLOBAL-CFP-28x28" +GLOBAL_CFP_24x36 = "GLOBAL-CFP-24x36" +GLOBAL_CFP_28x40 = "GLOBAL-CFP-28x40" + +SKU_CODES = [ + GLOBAL_CFP_12x12, + GLOBAL_CFP_11x14, + GLOBAL_CFP_12x16, + GLOBAL_CFP_16x20, + GLOBAL_CFP_20x20, + GLOBAL_CFP_18x24, + GLOBAL_CFP_20x28, + GLOBAL_CFP_24x32, + GLOBAL_CFP_28x28, + GLOBAL_CFP_24x36, + GLOBAL_CFP_28x40, +] diff --git a/api/resources/prices.py b/api/resources/prices.py index 1218157..da2dd5c 100644 --- a/api/resources/prices.py +++ b/api/resources/prices.py @@ -1,10 +1,11 @@ from flask import Blueprint, request, jsonify, abort from api.helpers import check_api_key -from api.validators import validate_territory, validate_number +from api.validators import validate_territory, validate_number, validate_any_of 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 import pwinty from api.lib.prices import ( wallpaper_price, canvas_price, @@ -242,6 +243,7 @@ def poster_hanger(): @mod.route("/framed-print", methods=["GET"]) @validate_territory("territory") +@validate_any_of("sku", pwinty.SKU_CODES) def framed_print(): sku = request.args.get("sku", type=str) market = market_model.from_territory(request.args.get("territory")) diff --git a/api/validators.py b/api/validators.py index 056cec4..1fc3967 100644 --- a/api/validators.py +++ b/api/validators.py @@ -94,3 +94,22 @@ def validate_territory(*keys): return wrapper return decorator + + +def validate_any_of(key, values): + def decorator(f): + @wraps(f) + def wrapper(*args, **kwargs): + _check_parameter_exists(key) + value = request.args.get(key) + if not value in values: + raise ValidationError( + "{} contains an invalid value, must be one of: {}".format( + key, values + ) + ) + return f(*args, **kwargs) + + return wrapper + + return decorator diff --git a/tests/resources/test_prices.py b/tests/resources/test_prices.py index ea89eb2..b0350a4 100644 --- a/tests/resources/test_prices.py +++ b/tests/resources/test_prices.py @@ -4,6 +4,7 @@ from api import create_app, db from api.models.product import Material, Product from api.models.inquiry import Inquiry from api.models.designer import Designer +from api.lib import pwinty class TestEndpoints(flask_testing.TestCase): @@ -209,3 +210,13 @@ class TestEndpoints(flask_testing.TestCase): self.assert200(response) expected = [{"price": 557.5, "price_excl_vat": 446, "sku": "GLOBAL-CFP-12x12"}] self.assertEqual(expected, response.json["data"]) + + def test_framed_print_invalid_sku(self): + response = self.client.get("/prices/framed-print?sku=invalid&territory=SE") + self.assert400(response) + self.assertEqual( + "sku contains an invalid value, must be one of: {}".format( + pwinty.SKU_CODES + ), + response.json["message"], + ) diff --git a/tests/test_web.py b/tests/test_web.py index c0e7beb..1bdd7ed 100644 --- a/tests/test_web.py +++ b/tests/test_web.py @@ -12,6 +12,7 @@ from api.validators import ( validate_number, validate_territory, validate_jsonschema, + validate_any_of, ) @@ -138,3 +139,18 @@ class TestValidators(flask_testing.TestCase): content_type="application/json", ).data, ) + + def test_validate_any_of(self): + app = self.app + + @app.route("/", methods=["GET"]) + @validate_any_of("color", ["red", "green", "blue"]) + def index(): + return "ok" + + self.assertEqual(b"No color is specified", self.client.get("/").data) + self.assertEqual( + b"color contains an invalid value, must be one of: ['red', 'green', 'blue']", + self.client.get("/?color=black").data, + ) + self.assertEqual(b"ok", self.client.get("/?color=blue").data)