From 407ff70c567ac437338aa85572a6a4501aac2dea Mon Sep 17 00:00:00 2001 From: stumpylog <797416+stumpylog@users.noreply.github.com> Date: Mon, 20 Apr 2026 14:13:28 -0700 Subject: [PATCH] Rejects string prefixed exact monetary queries --- src/documents/filters.py | 6 ++++++ .../tests/test_api_filter_by_custom_fields.py | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/documents/filters.py b/src/documents/filters.py index 75501357f..080ff8db7 100644 --- a/src/documents/filters.py +++ b/src/documents/filters.py @@ -627,6 +627,12 @@ class CustomFieldQueryParser: elif custom_field.data_type == CustomField.FieldDataType.URL: # For URL fields we don't need to be strict about validation (e.g., for istartswith). field = serializers.CharField() + elif custom_field.data_type == CustomField.FieldDataType.MONETARY and ( + op in self.EXPR_BY_CATEGORY["arithmetic"] or op in {"exact", "in"} + ): + # These ops compare against value_monetary_amount (a DecimalField), so the + # filter value must be numeric, not a currency-prefixed string like "USD100". + field = serializers.DecimalField(max_digits=65, decimal_places=2) else: # The general case: inferred from the corresponding field in CustomFieldInstance. value_field_name = CustomFieldInstance.get_value_field_name( diff --git a/src/documents/tests/test_api_filter_by_custom_fields.py b/src/documents/tests/test_api_filter_by_custom_fields.py index bbb38f3bb..f6bbef1eb 100644 --- a/src/documents/tests/test_api_filter_by_custom_fields.py +++ b/src/documents/tests/test_api_filter_by_custom_fields.py @@ -479,6 +479,26 @@ class TestCustomFieldsSearch(DirectoriesMixin, APITestCase): ), ) + def test_exact_monetary_with_currency_prefix_is_invalid(self) -> None: + # Providing a currency-prefixed string like "USD100" for an exact/arithmetic + # monetary filter should be rejected, since these ops compare against the + # extracted numeric amount and cannot accept non-numeric values. + self._assert_validation_error( + json.dumps(["monetary_field", "exact", "USD100"]), + ["custom_field_query", "2"], + "valid number", + ) + self._assert_validation_error( + json.dumps(["monetary_field", "gt", "USD100"]), + ["custom_field_query", "2"], + "valid number", + ) + self._assert_validation_error( + json.dumps(["monetary_field", "in", ["USD100", "EUR50"]]), + ["custom_field_query", "2", "0"], + "valid number", + ) + # ==========================================================# # Subset check (document link field only) # # ==========================================================#