Use generated field for monetary amount to allow arithmetic filtering

This commit is contained in:
shamoon 2024-09-28 17:40:11 -07:00
parent 4daa4edd33
commit 6ee2d1ac7d
5 changed files with 35 additions and 2 deletions

View File

@ -93,6 +93,7 @@ export const CUSTOM_FIELD_QUERY_OPERATOR_GROUPS_BY_TYPE = {
[CustomFieldDataType.Monetary]: [ [CustomFieldDataType.Monetary]: [
CustomFieldQueryOperatorGroups.Basic, CustomFieldQueryOperatorGroups.Basic,
CustomFieldQueryOperatorGroups.String, CustomFieldQueryOperatorGroups.String,
CustomFieldQueryOperatorGroups.Arithmetic,
], ],
[CustomFieldDataType.DocumentLink]: [ [CustomFieldDataType.DocumentLink]: [
CustomFieldQueryOperatorGroups.Basic, CustomFieldQueryOperatorGroups.Basic,

View File

@ -261,7 +261,7 @@ class CustomFieldQueryParser:
CustomField.FieldDataType.BOOL: ("basic",), CustomField.FieldDataType.BOOL: ("basic",),
CustomField.FieldDataType.INT: ("basic", "arithmetic"), CustomField.FieldDataType.INT: ("basic", "arithmetic"),
CustomField.FieldDataType.FLOAT: ("basic", "arithmetic"), CustomField.FieldDataType.FLOAT: ("basic", "arithmetic"),
CustomField.FieldDataType.MONETARY: ("basic", "string"), CustomField.FieldDataType.MONETARY: ("basic", "string", "arithmetic"),
CustomField.FieldDataType.DOCUMENTLINK: ("basic", "containment"), CustomField.FieldDataType.DOCUMENTLINK: ("basic", "containment"),
CustomField.FieldDataType.SELECT: ("basic",), CustomField.FieldDataType.SELECT: ("basic",),
} }
@ -417,6 +417,13 @@ class CustomFieldQueryParser:
value_field_name = CustomFieldInstance.get_value_field_name( value_field_name = CustomFieldInstance.get_value_field_name(
custom_field.data_type, custom_field.data_type,
) )
if custom_field.data_type == CustomField.FieldDataType.MONETARY and op in (
"gt",
"gte",
"lt",
"lte",
):
value_field_name = "value_monetary_amount"
has_field = Q(custom_fields__field=custom_field) has_field = Q(custom_fields__field=custom_field)
# Our special exists operator. # Our special exists operator.

View File

@ -1,5 +1,6 @@
# Generated by Django 5.1.1 on 2024-09-28 04:48 # Generated by Django 5.1.1 on 2024-09-29 00:39
import django.db.models.functions.text
from django.db import migrations from django.db import migrations
from django.db import models from django.db import models
@ -10,6 +11,15 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.AddField(
model_name="customfieldinstance",
name="value_monetary_amount",
field=models.GeneratedField(
db_persist=True,
expression=django.db.models.functions.text.Substr("value_monetary", 4),
output_field=models.DecimalField(decimal_places=2, max_digits=125),
),
),
migrations.AlterField( migrations.AlterField(
model_name="savedviewfilterrule", model_name="savedviewfilterrule",
name="rule_type", name="rule_type",

View File

@ -22,6 +22,7 @@ from multiselectfield import MultiSelectField
if settings.AUDIT_LOG_ENABLED: if settings.AUDIT_LOG_ENABLED:
from auditlog.registry import auditlog from auditlog.registry import auditlog
from django.db.models.functions import Substr
from django_softdelete.models import SoftDeleteModel from django_softdelete.models import SoftDeleteModel
from documents.data_models import DocumentSource from documents.data_models import DocumentSource
@ -922,6 +923,12 @@ class CustomFieldInstance(models.Model):
value_monetary = models.CharField(null=True, max_length=128) value_monetary = models.CharField(null=True, max_length=128)
value_monetary_amount = models.GeneratedField(
expression=Substr("value_monetary", 4),
output_field=models.DecimalField(decimal_places=2, max_digits=125),
db_persist=True,
)
value_document_ids = models.JSONField(null=True) value_document_ids = models.JSONField(null=True)
value_select = models.PositiveSmallIntegerField(null=True) value_select = models.PositiveSmallIntegerField(null=True)

View File

@ -393,6 +393,14 @@ class TestCustomFieldsSearch(DirectoriesMixin, APITestCase):
and document["date_field"].year >= 2024, and document["date_field"].year >= 2024,
) )
def test_gt_monetary(self):
self._assert_query_match_predicate(
["monetary_field", "gt", "99"],
lambda document: "monetary_field" in document
and document["monetary_field"] is not None
and document["monetary_field"] == "USD100.00",
)
# ==========================================================# # ==========================================================#
# Subset check (document link field only) # # Subset check (document link field only) #
# ==========================================================# # ==========================================================#