Skip to content

Commit

Permalink
[#18] add requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Floris272 committed Mar 5, 2025
1 parent 1e11ac4 commit e0cce73
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 38 deletions.
4 changes: 2 additions & 2 deletions docs/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ Product API `0.0.2 <https://redocly.github.io/redoc/?url=https://raw
Producttype API `0.0.2 <https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/maykinmedia/open-producten/v0.0.2/src/producttypen-openapi.yaml>`__
====================== ==========================================

In addition, Open Producten requires access to a `Notificaties API`_. Open Producten uses
`Open Notificaties`_ by default.
In addition, Open Producten can work with `Notificaties API`_. Open Producten uses
`Open Notificaties`_ by default but this can be disabled using ``NOTIFICATIONS_DISABLED`` :ref:`installation_env_config` .

.. _`Notificaties API`: https://vng-realisatie.github.io/gemma-zaken/standaard/notificaties/
.. _`Open Notificaties`: https://github.com/open-zaak/open-notificaties
8 changes: 0 additions & 8 deletions docs/installation/config/openproducten_config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ Configure Notificaties API
Next, the notifications for Open Producten must be configured. We assume you're also
using Open Notificaties to make a complete setup.

.. There are 2 things to keep in mind:
.. 1. Open Producten offers an Autorisaties API and thus the Open Producten Autorisaties API
.. must be consulted by the Notificaties API to check for **autorisations**.
.. 2. Each component handles **authentication** themselves and thus we need to store
.. the Client IDs and secrets in each component that wants to communicate with
.. each other.
Open Producten
--------------

Expand Down
5 changes: 4 additions & 1 deletion docs/installation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ Before you begin
* Open Producten: ``open-producten.<organization.local>``
* `Open Notificaties`_: ``open-notificaties.<organization.local>``

The machine(s) do not need to be publically accessible and do not need a public DNS
.. note:: notifications can be disabled using ``NOTIFICATIONS_DISABLED`` :ref:`installation_env_config`.


The machine(s) do not need to be publicly accessible and do not need a public DNS
entry. In some cases, you might want this but it's not recommended. The same machine
can be used for both Open Producten and `Open Notificaties`_.

Expand Down
2 changes: 1 addition & 1 deletion docs/introduction/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Open Producten exposes several :ref:`API's<api_index>` to store and retrieve dat
* Producten API
* Producttype API

The `Notificaties API`_ is required for Open Zaak to work but is available as
The `Notificaties API`_ is required for Open Producten to work if notifications are enabled, but is available as
a separate package, `Open Notificaties`_.

.. _`Notificaties API`: https://vng-realisatie.github.io/gemma-zaken/standaard/notificaties/
Expand Down
6 changes: 4 additions & 2 deletions src/open_producten/producten/kanalen.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from notifications_api_common.kanalen import Kanaal
from open_producten.utils.kanaal import Kanaal

from .models import Product

KANAAL_PRODUCTEN = Kanaal(
"producten", main_resource=Product, kenmerken=("product_type_id",)
"producten",
main_resource=Product,
kenmerken=("product_type.id",), # TODO decide on kenmerken
)
2 changes: 1 addition & 1 deletion src/open_producten/producten/serializers/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ProductSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name="product-detail")
product_type = NestedProductTypeSerializer(read_only=True)
product_type_id = serializers.PrimaryKeyRelatedField(
queryset=ProductType.objects.all(), source="product_type"
write_only=True, queryset=ProductType.objects.all(), source="product_type"
)

class Meta:
Expand Down
25 changes: 12 additions & 13 deletions src/open_producten/producten/tests/api/test_notifications_send.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@

@freeze_time("2024-2-2T00:00:00Z")
class SendNotifTestCase(BaseApiTestCase):

def setUp(self):
super().setUp()
@classmethod
def setUpTestData(cls):

service, _ = Service.objects.update_or_create(
api_root="https://notificaties-api.vng.cloud/api/v1/",
Expand All @@ -33,19 +32,19 @@ def setUp(self):
config.notifications_api_service = service
config.save()

self.product_type = ProductTypeFactory.create(toegestane_statussen=["gereed"])
self.data = {
"product_type_id": self.product_type.id,
cls.product_type = ProductTypeFactory.create(toegestane_statussen=["gereed"])
cls.data = {
"product_type_id": cls.product_type.id,
"bsn": "111222333",
"status": "initieel",
"prijs": "20.20",
"frequentie": "eenmalig",
}

self.product = ProductFactory.create(**self.data)
product = ProductFactory.create(**cls.data)

self.path = reverse("product-list")
self.detail_path = reverse("product-detail", args=[self.product.id])
cls.path = reverse("product-list")
cls.detail_path = reverse("product-detail", args=[product.id])

@patch("notifications_api_common.viewsets.send_notification.delay")
def test_send_notif_create_object(self, mock_task):
Expand All @@ -63,7 +62,7 @@ def test_send_notif_create_object(self, mock_task):
"actie": "create",
"aanmaakdatum": "2024-02-02T01:00:00+01:00",
"kenmerken": {
"productTypeId": data["product_type_id"],
"productType.id": data["product_type"]["id"],
},
}

Expand All @@ -85,7 +84,7 @@ def test_send_notif_update_object(self, mock_task):
"actie": "update",
"aanmaakdatum": "2024-02-02T01:00:00+01:00",
"kenmerken": {
"productTypeId": data["product_type_id"],
"productType.id": data["product_type"]["id"],
},
}

Expand All @@ -107,7 +106,7 @@ def test_send_notif_partial_update_object(self, mock_task):
"actie": "partial_update",
"aanmaakdatum": "2024-02-02T01:00:00+01:00",
"kenmerken": {
"productTypeId": data["product_type_id"],
"productType.id": data["product_type"]["id"],
},
}

Expand All @@ -128,7 +127,7 @@ def test_send_notif_delete_object(self, mock_task):
"actie": "destroy",
"aanmaakdatum": "2024-02-02T01:00:00+01:00",
"kenmerken": {
"productTypeId": str(self.product_type.id),
"productType.id": str(self.product_type.id),
},
}

Expand Down
4 changes: 0 additions & 4 deletions src/open_producten/producten/tests/api/test_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ def test_create_product(self):
"frequentie": product.frequentie,
"aanmaak_datum": product.aanmaak_datum.astimezone().isoformat(),
"update_datum": product.update_datum.astimezone().isoformat(),
"product_type_id": product_type.id,
"product_type": {
"id": str(product_type.id),
"code": product_type.code,
Expand Down Expand Up @@ -229,7 +228,6 @@ def test_read_producten(self):
"frequentie": product1.frequentie,
"aanmaak_datum": product1.aanmaak_datum.astimezone().isoformat(),
"update_datum": product1.update_datum.astimezone().isoformat(),
"product_type_id": self.product_type.id,
"product_type": {
"id": str(self.product_type.id),
"code": self.product_type.code,
Expand All @@ -254,7 +252,6 @@ def test_read_producten(self):
"frequentie": product2.frequentie,
"aanmaak_datum": product2.aanmaak_datum.astimezone().isoformat(),
"update_datum": product2.update_datum.astimezone().isoformat(),
"product_type_id": self.product_type.id,
"product_type": {
"id": str(self.product_type.id),
"code": self.product_type.code,
Expand Down Expand Up @@ -290,7 +287,6 @@ def test_read_product(self):
"frequentie": product.frequentie,
"aanmaak_datum": "2025-12-31T01:00:00+01:00",
"update_datum": "2025-12-31T01:00:00+01:00",
"product_type_id": product_type.id,
"product_type": {
"id": str(product_type.id),
"code": product_type.code,
Expand Down
2 changes: 0 additions & 2 deletions src/open_producten/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,8 @@
IndexView.as_view(component="producttypen"),
name="index-producttypen",
),
path("ref/", include("vng_api_common.urls")),
path("ref/", include("notifications_api_common.urls")),
# path("view-config/", ViewConfigView.as_view(), name="view-config"),
path("markdownx/", include("markdownx.urls")),
]

# NOTE: The staticfiles_urlpatterns also discovers static files (ie. no need to run collectstatic). Both the static
Expand Down
50 changes: 50 additions & 0 deletions src/open_producten/utils/kanaal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from typing import Dict, cast

from django.db.models import Field, Model

from glom import glom
from notifications_api_common.kanalen import Kanaal as _Kanaal
from rest_framework.request import Request
from vng_api_common.tests import reverse


class Kanaal(_Kanaal):
@staticmethod
def get_field(model: Model, field: str) -> Field:
"""
Function to retrieve a field from a Model, can also be passed a path to a field
(e.g. `zaaktype.catalogus`)
"""
if "." in field:
model_field = None
bits = field.split(".")
for i, part in enumerate(bits):
model_field = model._meta.get_field(part)
if fk_field := getattr(model_field, "fk_field", None):
model_field = model._meta.get_field(fk_field)
if i != len(bits):
model = cast(Model, model_field.related_model)
assert model_field, "Could not find field on model"
return model_field
return model._meta.get_field(field)

def get_kenmerken(
self, obj: Model, data: dict | None = None, request: Request | None = None
) -> Dict:
"""
Overridden to support sending kenmerken that are not directly part of the main
resource (e.g `Zaak.zaaktype.catalogus`)
"""
data = data or {}
kenmerken = {}
for kenmerk in self.kenmerken:
value = data.get(kenmerk, glom(obj, kenmerk, default=""))
if isinstance(value, Model):
if _loose_fk_data := getattr(value, "_loose_fk_data", None):
value = _loose_fk_data["url"]
else:
value = reverse(value)
if request:
value = request.build_absolute_uri(value)
kenmerken[kenmerk] = value
return kenmerken
6 changes: 2 additions & 4 deletions src/producten-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,7 @@ components:
product_type_id:
type: string
format: uuid
writeOnly: true
gepubliceerd:
type: boolean
description: Geeft aan of het object getoond kan worden.
Expand Down Expand Up @@ -589,9 +590,6 @@ components:
allOf:
- $ref: '#/components/schemas/NestedProductType'
readOnly: true
product_type_id:
type: string
format: uuid
gepubliceerd:
type: boolean
description: Geeft aan of het object getoond kan worden.
Expand Down Expand Up @@ -668,7 +666,6 @@ components:
- id
- prijs
- product_type
- product_type_id
- update_datum
- url
ProductRequest:
Expand All @@ -677,6 +674,7 @@ components:
product_type_id:
type: string
format: uuid
writeOnly: true
gepubliceerd:
type: boolean
description: Geeft aan of het object getoond kan worden.
Expand Down

0 comments on commit e0cce73

Please sign in to comment.