Skip to content

Commit

Permalink
[maykinmedia/open-producten#24] Add open producten client & command t…
Browse files Browse the repository at this point in the history
…ests
  • Loading branch information
Floris272 committed Oct 29, 2024
1 parent 6d36aa4 commit 3420888
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 44 deletions.
3 changes: 2 additions & 1 deletion src/openforms/contrib/open_producten/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def get_current_prices(self) -> list[ProductType]:
response.raise_for_status()
except requests.RequestException as exc:
logger.exception(
"exception while making KVK basisprofiel request", exc_info=exc
"exception while fetching current prices from Open Producten",
exc_info=exc,
)
raise exc

Expand Down
70 changes: 70 additions & 0 deletions src/openforms/contrib/open_producten/tests/test_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from django.test import TestCase

import requests_mock
from zgw_consumers.test.factories import ServiceFactory

from openforms.contrib.open_producten.client import (
NoServiceConfigured,
OpenProductenClient,
get_open_producten_client,
)
from openforms.contrib.open_producten.models import OpenProductenConfig


class TestOpenProductenClient(TestCase):
def setUp(self):
self.client = OpenProductenClient(base_url="https://test")
self.requests_mock = requests_mock.Mocker()
self.requests_mock.start()
self.addCleanup(self.requests_mock.stop)

def test_get_current_prices(self):

self.requests_mock.get(
json={
"id": "f714ce89-0c98-4249-9e03-9fc929a29a09",
"name": "test",
"upl_name": "UPL-naam nog niet beschikbaar",
"upl_uri": "http://standaarden.overheid.nl/owms/terms/UPL-naam_nog_niet_beschikbaar",
"current_price": {
"id": "1ec25528-4c6b-4bbf-84f7-d0a3efdbe314",
"options": [
{
"id": "1c3cc677-b643-46f7-8f30-cbc18e297cad",
"amount": "24.00",
"description": "normaal",
}
],
"valid_from": "2024-10-23",
},
},
status_code=200,
url="https://test/producttypes/current-prices",
)

product_type = self.client.get_current_prices()
self.assertEqual(product_type.name, "test")
self.assertEqual(product_type.id, "f714ce89-0c98-4249-9e03-9fc929a29a09")
self.assertEqual(
product_type.current_price.id, "1ec25528-4c6b-4bbf-84f7-d0a3efdbe314"
)
self.assertEqual(
product_type.current_price.options[0].id,
"1c3cc677-b643-46f7-8f30-cbc18e297cad",
)
self.assertEqual(product_type.current_price.options[0].amount, "24.00")

def test_get_open_producten_client_without_service(self):
OpenProductenConfig.objects.create()

with self.assertRaisesMessage(
NoServiceConfigured, "No open producten service configured!"
):
get_open_producten_client()

def test_get_open_producten_client_with_service(self):
service = ServiceFactory(api_root="http://test")
OpenProductenConfig.objects.create(producten_service=service)

client = get_open_producten_client()
self.assertEqual(client.base_url, "http://test/")
61 changes: 61 additions & 0 deletions src/openforms/contrib/open_producten/tests/test_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from io import StringIO
from unittest.mock import patch
from uuid import uuid4

from django.core.management import call_command
from django.test import TestCase

from zgw_consumers.test.factories import ServiceFactory

from openforms.contrib.open_producten.models import OpenProductenConfig
from openforms.contrib.open_producten.tests.factories import (
PriceFactory,
PriceOptionFactory,
)
from openforms.products.tests.factories import ProductFactory


class TestImportPrices(TestCase):

def call_command(self, *args, **kwargs):
out = StringIO()
call_command(
"import_prices",
*args,
stdout=out,
stderr=StringIO(),
**kwargs,
)
return out.getvalue()

def test_import_prices_without_config(self):
out = self.call_command()
self.assertEqual(
out, "Please define the OpenProductenConfig before running this command.\n"
)

@patch(
"openforms.contrib.open_producten.management.commands.import_prices.get_open_producten_client"
)
@patch(
"openforms.contrib.open_producten.management.commands.import_prices.PriceImporter.import_product_types"
)
def test_import_prices(self, mock_import_product_types, mock_client):
OpenProductenConfig.objects.create(producten_service=ServiceFactory.create())

uuid = uuid4()

mock_import_product_types.return_value = (
[
ProductFactory.create(uuid=uuid),
PriceFactory.create(uuid=uuid),
PriceOptionFactory.create(uuid=uuid),
],
[],
)
out = self.call_command()

self.assertEqual(
out,
f"updated 0 exising product type(s)\ncreated 3 new product type(s):\nProduct: {uuid}\nPrice: {uuid}\nPriceOption: {uuid}\n",
)
34 changes: 22 additions & 12 deletions src/openforms/formio/components/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,21 +364,31 @@ def mutate_config_dynamically(
"inline": False,
"inputType": "radio",
"validate": {"required": True},
"values": [],
}
)
current_price = submission.form.product.open_producten_price
if current_price:
component["values"] = [
{
"label": f"{option.description}: € {option.amount}",
"value": option.uuid,
}
for option in current_price.options.all()
]

if not component["values"]:
logger.warning("Product does not have price options.")
# TODO: error?
# TODO: errors instead of logs?
if not submission.form.product:
logger.error("Form is not linked to product.")

else:
current_price = submission.form.product.open_producten_price

if not current_price:
logger.error("Product does not have an active price.")

elif not current_price.options.count():
logger.error("Product does not have price options.")

else:
component["values"] = [
{
"label": f"{option.description}: € {option.amount}",
"value": option.uuid,
}
for option in current_price.options.all()
]


@register("bsn")
Expand Down
85 changes: 54 additions & 31 deletions src/openforms/formio/tests/test_product_price.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,27 @@
)
from openforms.formio.datastructures import FormioConfigurationWrapper
from openforms.formio.dynamic_config import rewrite_formio_components
from openforms.products.tests.factories import ProductFactory
from openforms.submissions.tests.factories import SubmissionFactory

request_factory = APIRequestFactory()


class ProductPriceConfigurationTests(TestCase):

def test_mutate_config_dynamically_changes_type_and_adds_options(self):
component = {
def setUp(self):
self.component = {
"type": "productPrice",
"key": "productPrice",
"label": "select a price option",
}

def test_mutate_config_dynamically_changes_type_and_adds_options(self):

price = PriceFactory.create(valid_from=datetime.date(2024, 1, 1))
price_option = PriceOptionFactory.create(price=price)

config_wrapper = FormioConfigurationWrapper({"components": [component]})
config_wrapper = FormioConfigurationWrapper({"components": [self.component]})
submission = SubmissionFactory.create(form__product=price.product_type)

new_config_wrapper = rewrite_formio_components(config_wrapper, submission)
Expand All @@ -52,36 +55,56 @@ def test_mutate_config_dynamically_changes_type_and_adds_options(self):
},
)

def test_mutate_config_dynamically_changes_type_and_adds_options(self):
component = {
"type": "productPrice",
"key": "productPrice",
"label": "select a price option",
}
def test_mutate_config_dynamically_logs_warning_when_form_has_no_product(self):

config_wrapper = FormioConfigurationWrapper({"components": [self.component]})
submission = SubmissionFactory.create(form__product=None)

with self.assertLogs(
"openforms.formio.components.custom", level="ERROR"
) as log:
rewrite_formio_components(config_wrapper, submission)
self.assertEqual(
log.output,
[
"ERROR:openforms.formio.components.custom:Form is not linked to product."
],
)

price = PriceFactory.create(valid_from=datetime.date(2024, 1, 1))
price_option = PriceOptionFactory.create(price=price)
def test_mutate_config_dynamically_logs_warning_when_form_product_has_no_price(
self,
):
product = ProductFactory.create()

config_wrapper = FormioConfigurationWrapper({"components": [component]})
submission = SubmissionFactory.create(form__product=price.product_type)
config_wrapper = FormioConfigurationWrapper({"components": [self.component]})
submission = SubmissionFactory.create(form__product=product)

new_config_wrapper = rewrite_formio_components(config_wrapper, submission)
new_component = new_config_wrapper.configuration["components"][0]
with self.assertLogs(
"openforms.formio.components.custom", level="ERROR"
) as log:
rewrite_formio_components(config_wrapper, submission)
self.assertEqual(
new_component,
{
"type": "radio",
"key": "productPrice",
"label": "select a price option",
"fieldSet": False,
"inline": False,
"inputType": "radio",
"validate": {"required": True},
"values": [
{
"label": f"{price_option.description}: € {price_option.amount}",
"value": UUID(price_option.uuid),
},
],
},
log.output,
[
"ERROR:openforms.formio.components.custom:Product does not have an active price."
],
)

def test_mutate_config_dynamically_logs_warning_when_form_product_has_no_price_options(
self,
):
price = PriceFactory.create(valid_from=datetime.date(2024, 1, 1))

config_wrapper = FormioConfigurationWrapper({"components": [self.component]})
submission = SubmissionFactory.create(form__product=price.product_type)

with self.assertLogs(
"openforms.formio.components.custom", level="ERROR"
) as log:
rewrite_formio_components(config_wrapper, submission)
self.assertEqual(
log.output,
[
"ERROR:openforms.formio.components.custom:Product does not have price options."
],
)

0 comments on commit 3420888

Please sign in to comment.