diff --git a/api_v2/tests.py b/api_v2/tests.py index cd489cd..22c072f 100644 --- a/api_v2/tests.py +++ b/api_v2/tests.py @@ -840,6 +840,29 @@ class PlateOrderByProcessNodeV2APITest(TestCase): self.assertEqual(resp.data['count'], 0) self.assertEqual(resp.data['results'], []) + def test_param_filter_supports_fuzzy_match(self): + log = stateflow_models.StateFlowRecord.objects.filter( + business_object=self.po_state3.business_object, + state=self.state2, + is_cancelled=False, + ).first() + stateflow_models.StateLogParameterRecord.objects.create( + state_log=log, + parameters={'temperature': '30C'}, + ) + + resp = self.client.get( + self.url, + { + 'process_node_id': self.node2.id, + 'param_key': 'temperature', + 'param_value': '30', + }, + ) + self.assertEqual(resp.status_code, 200) + ids = [item['id'] for item in resp.data['results']] + self.assertEqual(ids, [self.po_state3.id]) + def test_date_filter_requires_both(self): resp = self.client.get(self.url, {'process_node_id': self.node2.id, 'date_from': '2026-02-01'}) self.assertEqual(resp.status_code, 400) diff --git a/api_v2/views/printing.py b/api_v2/views/printing.py index 4e42318..d66b13a 100644 --- a/api_v2/views/printing.py +++ b/api_v2/views/printing.py @@ -4,6 +4,7 @@ from django.utils import timezone from django.db import transaction from django.db import models as django_models from django.db.models import Q, Count, CharField, Prefetch, Exists, OuterRef, Subquery +from django.db.models.fields.json import KeyTextTransform from django.db.models.functions import Cast, Coalesce from rest_framework import serializers, status, permissions from rest_framework.pagination import LimitOffsetPagination @@ -577,7 +578,11 @@ class PlateOrderByProcessNodeView(APIView): business_object_id=OuterRef('business_object_id'), state_id=target_state_id, is_cancelled=False, - parameter_records__parameters__contains={param_key: param_value}, + parameter_records__parameters__has_key=param_key, + ).annotate( + _param_value=KeyTextTransform(param_key, 'parameter_records__parameters') + ).filter( + _param_value__icontains=param_value, ) queryset = queryset.annotate(_has_state_param=Exists(matching_logs)).filter(_has_state_param=True) diff --git a/docs/api_v2_plate_orders_by_process_node_2026-02-06.md b/docs/api_v2_plate_orders_by_process_node_2026-02-06.md index 9f368f9..90ee6e8 100644 --- a/docs/api_v2_plate_orders_by_process_node_2026-02-06.md +++ b/docs/api_v2_plate_orders_by_process_node_2026-02-06.md @@ -26,7 +26,7 @@ ### param_key / param_value 过滤说明 - 必须成对提供,否则返回 400。 -- 过滤语义:存在任意一次“未撤销”的目标节点状态日志(StateFlowRecord.is_cancelled=false),其参数记录包含 {param_key: param_value} 即命中。 +- 过滤语义:存在任意一次“未撤销”的目标节点状态日志(StateFlowRecord.is_cancelled=false),其参数记录包含 param_key,且对应值 **模糊匹配** param_value 即命中(icontains)。 ## 返回结构 ```