Skip to content

Commit

Permalink
Merge pull request #4042 from open-formulieren/feature/3688-payment-b…
Browse files Browse the repository at this point in the history
…ack-to-patch

[#3688] Fix payment updates: use PATCH, represent payment as float
  • Loading branch information
sergei-maertens authored Mar 22, 2024
2 parents 75c3268 + bd65fb7 commit 551a95f
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 49 deletions.
13 changes: 11 additions & 2 deletions docker/objects-apis/fixtures/objecttypes_api_fixtures.json
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,17 @@
"submission_payment_completed": {
"type": "boolean"
},
"submission_payment_amount": {
"type": "string"
"nested": {
"type": "object",
"properties": {
"unrelated": {
"type": "string"
},
"submission_payment_amount": {
"type": "number",
"multipleOf": 0.01
}
}
},
"submission_payment_public_ids": {
"type": "array"
Expand Down
6 changes: 1 addition & 5 deletions src/openforms/registrations/contrib/objects_api/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,7 @@ def update_payment_status(

object_url = submission.registration_result["url"]
with get_objects_client() as objects_client:
operation = (
objects_client.patch if options["version"] == 1 else objects_client.put
)

response = operation(
response = objects_client.patch(
url=object_url,
json=updated_object_data,
headers={"Content-Crs": "EPSG:4326"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class PaymentAmount(BaseStaticVariable):
def get_initial_value(self, submission: Submission | None = None):
if submission is None:
return None
return str(submission.payments.sum_amount())
return float(submission.payments.sum_amount())


@register("payment_public_order_ids")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
SubmissionFileAttachment,
SubmissionReport,
)
from openforms.typing import JSONValue
from openforms.typing import JSONObject
from openforms.variables.service import get_static_variables
from openforms.variables.utils import get_variables_for_context

Expand All @@ -36,6 +36,7 @@
from .registration_variables import register as variables_registry
from .typing import (
ConfigVersion,
ObjecttypeVariableMapping,
RegistrationOptions,
RegistrationOptionsV1,
RegistrationOptionsV2,
Expand Down Expand Up @@ -357,6 +358,31 @@ def get_update_payment_status_data(

class ObjectsAPIV2Handler(ObjectsAPIRegistrationHandler[RegistrationOptionsV2]):

@staticmethod
def _get_record_data(
variables_values: FormioData, variables_mapping: list[ObjecttypeVariableMapping]
) -> JSONObject:
record_data: JSONObject = {}

for mapping in variables_mapping:
variable_key = mapping["variable_key"]
if variable_key not in variables_values:
# This should only happen for payment status update,
# where only a subset of the variables are updated.
continue
target_path = mapping["target_path"]

# Type hint is wrong: currently some static variables are of type date/datetime
value = cast(Any, variables_values[variable_key])

# Comply with JSON Schema "format" specs:
if isinstance(value, (datetime, date)):
value = value.isoformat()

glom.assign(record_data, glom.Path(*target_path), value, missing=dict)

return record_data

@override
def get_object_data(
self, submission: Submission, options: RegistrationOptionsV2
Expand Down Expand Up @@ -401,22 +427,8 @@ def get_object_data(
)

variables_values = FormioData({**dynamic_values, **static_values})

variables_mapping = options["variables_mapping"]
record_data: dict[str, JSONValue] = {}

for mapping in variables_mapping:
variable_key = mapping["variable_key"]
target_path = mapping["target_path"]

# Type hint is wrong: currently some static variables are of type date/datetime
value = cast(Any, variables_values[variable_key])

# Comply with JSON Schema "format" specs:
if isinstance(value, (datetime, date)):
value = value.isoformat()

glom.assign(record_data, glom.Path(*target_path), value, missing=dict)
record_data = self._get_record_data(variables_values, variables_mapping)

object_data = prepare_data_for_registration(
record_data=record_data,
Expand All @@ -435,10 +447,28 @@ def get_object_data(
def get_update_payment_status_data(
self, submission: Submission, options: RegistrationOptionsV2
) -> dict[str, Any]:
# In V2, a PUT request is made, so we essentially return the same
# payload from the initial registration. Payment related variables
# will have their value updated.
return self.get_object_data(submission, options)

values = {
variable.key: variable.initial_value
for variable in get_static_variables(
submission=submission,
variables_registry=variables_registry,
)
if variable.key
in ["payment_completed", "payment_amount", "payment_public_order_ids"]
}

variables_values = FormioData(values)
variables_mapping = options["variables_mapping"]
record_data = self._get_record_data(variables_values, variables_mapping)

object_data = prepare_data_for_registration(
record_data=record_data,
objecttype=options["objecttype"],
objecttype_version=options["objecttype_version"],
)

return object_data


HANDLER_MAPPING: dict[ConfigVersion, ObjectsAPIRegistrationHandler[Any]] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ interactions:
body: '{"type": "http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48",
"record": {"typeVersion": 3, "data": {"age": 20, "name": {"last.name": "My last
name"}, "submission_pdf_url": "http://example.com", "submission_csv_url": "http://example.com",
"submission_payment_completed": false, "submission_payment_amount": "0", "submission_payment_public_ids":
[], "submission_date": "2020-02-02T00:00:00+00:00"}, "startAt": "2020-02-02"}}'
"submission_payment_completed": false, "nested": {"unrelated": "some_value",
"submission_payment_amount": 0}, "submission_payment_public_ids": [], "submission_date":
"2020-02-02T00:00:00+00:00"}, "startAt": "2020-02-02"}}'
headers:
Accept:
- '*/*'
Expand All @@ -17,7 +18,7 @@ interactions:
Content-Crs:
- EPSG:4326
Content-Length:
- '456'
- '493'
Content-Type:
- application/json
User-Agent:
Expand All @@ -26,21 +27,21 @@ interactions:
uri: http://localhost:8002/api/v2/objects
response:
body:
string: '{"url":"http://localhost:8002/api/v2/objects/2c287cd4-7737-473d-84de-8b0a018a46bb","uuid":"2c287cd4-7737-473d-84de-8b0a018a46bb","type":"http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","record":{"index":1,"typeVersion":3,"data":{"age":20,"name":{"last.name":"My
last name"},"submission_pdf_url":"http://example.com","submission_csv_url":"http://example.com","submission_payment_completed":false,"submission_payment_amount":"0","submission_payment_public_ids":[],"submission_date":"2020-02-02T00:00:00+00:00"},"geometry":null,"startAt":"2020-02-02","endAt":null,"registrationAt":"2024-03-19","correctionFor":null,"correctedBy":null}}'
string: '{"url":"http://localhost:8002/api/v2/objects/302d84d5-b428-4e6b-8fb5-9127a893fd5e","uuid":"302d84d5-b428-4e6b-8fb5-9127a893fd5e","type":"http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","record":{"index":1,"typeVersion":3,"data":{"age":20,"name":{"last.name":"My
last name"},"submission_pdf_url":"http://example.com","submission_csv_url":"http://example.com","submission_payment_completed":false,"nested":{"unrelated":"some_value","submission_payment_amount":0},"submission_payment_public_ids":[],"submission_date":"2020-02-02T00:00:00+00:00"},"geometry":null,"startAt":"2020-02-02","endAt":null,"registrationAt":"2024-03-22","correctionFor":null,"correctedBy":null}}'
headers:
Allow:
- GET, POST, HEAD, OPTIONS
Content-Crs:
- EPSG:4326
Content-Length:
- '669'
- '703'
Content-Type:
- application/json
Cross-Origin-Opener-Policy:
- same-origin
Location:
- http://localhost:8002/api/v2/objects/2c287cd4-7737-473d-84de-8b0a018a46bb
- http://localhost:8002/api/v2/objects/302d84d5-b428-4e6b-8fb5-9127a893fd5e
Referrer-Policy:
- same-origin
X-Content-Type-Options:
Expand All @@ -52,11 +53,9 @@ interactions:
message: Created
- request:
body: '{"type": "http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48",
"record": {"typeVersion": 3, "data": {"age": 20, "name": {"last.name": "My last
name"}, "submission_date": "2020-02-02T00:00:00+00:00", "submission_pdf_url":
"", "submission_csv_url": "", "submission_payment_completed": true, "submission_payment_amount":
"10.01", "submission_payment_public_ids": ["TEST-123"]}, "startAt": "2020-02-02",
"geometry": {"type": "Point", "coordinates": [52.36673378967122, 4.893164274470299]}}}'
"record": {"typeVersion": 3, "data": {"submission_payment_completed": true,
"nested": {"submission_payment_amount": 10.01}, "submission_payment_public_ids":
["TEST-123"]}, "startAt": "2020-02-02"}}'
headers:
Accept:
- '*/*'
Expand All @@ -69,24 +68,24 @@ interactions:
Content-Crs:
- EPSG:4326
Content-Length:
- '519'
- '293'
Content-Type:
- application/json
User-Agent:
- python-requests/2.31.0
method: PUT
uri: http://localhost:8002/api/v2/objects/2c287cd4-7737-473d-84de-8b0a018a46bb
method: PATCH
uri: http://localhost:8002/api/v2/objects/302d84d5-b428-4e6b-8fb5-9127a893fd5e
response:
body:
string: '{"url":"http://localhost:8002/api/v2/objects/2c287cd4-7737-473d-84de-8b0a018a46bb","uuid":"2c287cd4-7737-473d-84de-8b0a018a46bb","type":"http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","record":{"index":2,"typeVersion":3,"data":{"age":20,"name":{"last.name":"My
last name"},"submission_date":"2020-02-02T00:00:00+00:00","submission_pdf_url":"","submission_csv_url":"","submission_payment_completed":true,"submission_payment_amount":"10.01","submission_payment_public_ids":["TEST-123"]},"geometry":{"type":"Point","coordinates":[52.36673378967122,4.893164274470299]},"startAt":"2020-02-02","endAt":null,"registrationAt":"2024-03-19","correctionFor":null,"correctedBy":null}}'
string: '{"url":"http://localhost:8002/api/v2/objects/302d84d5-b428-4e6b-8fb5-9127a893fd5e","uuid":"302d84d5-b428-4e6b-8fb5-9127a893fd5e","type":"http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","record":{"index":2,"typeVersion":3,"data":{"age":20,"name":{"last.name":"My
last name"},"nested":{"unrelated":"some_value","submission_payment_amount":10.01},"submission_date":"2020-02-02T00:00:00+00:00","submission_csv_url":"http://example.com","submission_pdf_url":"http://example.com","submission_payment_completed":true,"submission_payment_public_ids":["TEST-123"]},"geometry":null,"startAt":"2020-02-02","endAt":null,"registrationAt":"2024-03-22","correctionFor":null,"correctedBy":null}}'
headers:
Allow:
- GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Crs:
- EPSG:4326
Content-Length:
- '710'
- '716'
Content-Type:
- application/json
Cross-Origin-Opener-Policy:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ def test_update_payment_status(self):
"submission_pdf_url": "http://example.com",
"submission_csv_url": "http://example.com",
"submission_payment_completed": False,
"submission_payment_amount": "0",
"nested": {
"unrelated": "some_value",
"submission_payment_amount": 0,
},
"submission_payment_public_ids": [],
"submission_date": timezone.now().isoformat(),
},
Expand Down Expand Up @@ -137,7 +140,7 @@ def test_update_payment_status(self):
},
{
"variable_key": "payment_amount",
"target_path": ["submission_payment_amount"],
"target_path": ["nested", "submission_payment_amount"],
},
{
"variable_key": "payment_public_order_ids",
Expand All @@ -164,5 +167,11 @@ def test_update_payment_status(self):
result_data = result["record"]["data"]

self.assertTrue(result_data["submission_payment_completed"])
self.assertEqual(result_data["submission_payment_amount"], "10.01")
self.assertEqual(
result_data["nested"],
{
"unrelated": "some_value",
"submission_payment_amount": 10.01,
},
)
self.assertEqual(result_data["submission_payment_public_ids"], ["TEST-123"])

0 comments on commit 551a95f

Please sign in to comment.