def build_pipeline_prerequisite(target_topic: Topic) -> ParameterJoint: return ParameterJoint( jointType=ParameterJointType.AND, filters=[ParameterExpression( left=ConstantParameter(kind=ParameterKind.CONSTANT, value=f'{{targettopicname}}'), operator=ParameterExpressionOperator.EQUALS, right=ConstantParameter(kind=ParameterKind.CONSTANT, value=f'{target_topic.name}'), )] )
def fake_time_range_to_dataset_filter(self) -> Optional[ParameterJoint]: time_range_factor_id = self.inspection.timeRangeFactorId if is_blank(time_range_factor_id): return None time_range_factor = self.find_factor(time_range_factor_id, lambda: 'Time range factor not declared.') time_ranges = ArrayHelper(self.inspection.timeRanges) \ .filter(lambda x: x is not None and x.value is not None).to_list() if len(time_ranges) == 0: # no ranges given return None operator = ParameterExpressionOperator.EQUALS if len(time_ranges) == 1 else ParameterExpressionOperator.IN right = time_ranges[0].value if len(time_ranges) == 1 \ else ArrayHelper(time_ranges).map(lambda x: x.value).join(',') time_range_measure = self.inspection.timeRangeMeasure if self.has_year_or_month(time_range_factor): if time_range_measure == MeasureMethod.YEAR: compute_type = ParameterComputeType.YEAR_OF elif time_range_measure == MeasureMethod.MONTH: compute_type = ParameterComputeType.MONTH_OF else: raise IndicatorKernelException( f'Measure method[{time_range_measure}] for factor type[{time_range_factor.type}] is not supported.') joint = ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=ComputedParameter( kind=ParameterKind.COMPUTED, type=compute_type, parameters=[ TopicFactorParameter( kind=ParameterKind.TOPIC, topicId=self.topic.topicId, factorId=time_range_factor_id) ] ), operator=operator, right=ConstantParameter(kind=ParameterKind.CONSTANT, value=str(right)) ) ] ) else: joint = ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId=self.topic.topicId, factorId=time_range_factor_id), operator=operator, right=ConstantParameter(kind=ParameterKind.CONSTANT, value=str(right)) ) ] ) return joint
def test_criteria(self): joint = ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=ConstantParameter(kind=ParameterKind.CONSTANT, value="ABC"), operator=ParameterExpressionOperator.EQUALS, right=ConstantParameter( kind=ParameterKind.CONSTANT, value="{policy.productCode}-{policy.policyNo}")) ]) parsed = parse_condition_for_storage(joint, [ TopicSchema( Topic(name='policy', factors=[ Factor(name='productCode', type=FactorType.TEXT), Factor(name='policyNo', type=FactorType.TEXT) ])) ], create_fake_principal_service(), True) variables = PipelineVariables(None, {}, None) variables.put('policy', {'productCode': 'A001', 'policyNo': 'P001'}) result = parsed.run(variables, create_fake_principal_service()) print(result.to_dict())
def to_category_case_route(self, segment: CategorySegment, factor: Factor) -> Parameter: return ConstantParameter( kind=ParameterKind.CONSTANT, conditional=True, on=ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId=self.topic.topicId, factorId=factor.factorId), operator=ParameterExpressionOperator.IN, right=segment.value ), ] ), value=segment.name )
def to_numeric_range_case_route( self, segment: NumericValueSegment, include: RangeBucketValueIncluding, factor: Factor ) -> Parameter: name = segment.name min_value = segment.value.min max_value = segment.value.max if include == RangeBucketValueIncluding.INCLUDE_MIN: min_operator = ParameterExpressionOperator.MORE_EQUALS max_operator = ParameterExpressionOperator.LESS else: min_operator = ParameterExpressionOperator.MORE max_operator = ParameterExpressionOperator.LESS_EQUALS return ConstantParameter( kind=ParameterKind.CONSTANT, conditional=True, on=ParameterJoint( jointType=ParameterJointType.AND, filters=ArrayHelper([ None if min_value is not None else ParameterExpression( left=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId=self.topic.topicId, factorId=factor.factorId), operator=min_operator, right=min_value ), None if max_value is not None else ParameterExpression( left=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId=self.topic.topicId, factorId=factor.factorId), operator=max_operator, right=max_value ) ]).map(lambda x: x is not None).to_list() ), value=name )
def fake_measure_on_to_dataset_column( self, column_index: int) -> Tuple[Optional[SubjectDatasetColumn], Optional[int], int]: measure_on = self.inspection.measureOn if measure_on is None or measure_on == InspectMeasureOn.NONE: return None, None, column_index if measure_on == InspectMeasureOn.OTHER: measure_on_factor_id = self.inspection.measureOnFactorId if is_blank(measure_on_factor_id): return None, None, column_index elif measure_on == InspectMeasureOn.VALUE: measure_on_factor_id = self.indicator.factorId else: return None, None, column_index measure_on_factor = self.find_factor(measure_on_factor_id, lambda: 'Measure on factor not declared.') measure_on_bucket_id = self.inspection.measureOnBucketId if is_blank(measure_on_bucket_id): if measure_on == InspectMeasureOn.OTHER: # using naturally classification column = SubjectDatasetColumn( columnId=str(column_index), parameter=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId=self.topic.topicId, factorId=measure_on_factor_id), alias=f'column_{column_index}' ) else: raise IndicatorKernelException('Measure on bucket not declared.') else: bucket = ask_bucket(measure_on_bucket_id, self.principalService) if measure_on == InspectMeasureOn.VALUE: bucket = self.to_numeric_segments_bucket(bucket) include = RangeBucketValueIncluding.INCLUDE_MIN if bucket.include is None else bucket.include # at least has one value segments = ArrayHelper(bucket.segments) \ .filter(lambda x: x.value is not None) \ .filter(lambda x: x.value.min is not None or x.value.max is not None) \ .to_list() if len(segments) == 0: raise IndicatorKernelException('Numeric range segments not declared.') column = SubjectDatasetColumn( columnId=str(column_index), parameter=ComputedParameter( kind=ParameterKind.COMPUTED, type=ParameterComputeType.CASE_THEN, parameters=[ *ArrayHelper(segments).map( lambda x: self.to_numeric_range_case_route(x, include, measure_on_factor)).to_list(), # an anyway route, additional ConstantParameter(kind=ParameterKind.CONSTANT, value='-') ] ), alias=f'column_{column_index}' ) elif measure_on == InspectMeasureOn.OTHER: bucket = self.to_category_segments_bucket(bucket) segments = ArrayHelper(bucket.segments) \ .filter(lambda x: x.value is not None and len(x.value) != 0).to_list() if len(segments) == 0: raise IndicatorKernelException('Category segments not declared.') anyway_segment: CategorySegment = ArrayHelper(segments) \ .find(lambda x: len(x.value) == 1 and x.value[0] == OtherCategorySegmentValue) if anyway_segment is not None: conditional_routes = ArrayHelper(segments).filter(lambda x: x != anyway_segment).to_list() anyway_route = ConstantParameter(kind=ParameterKind.CONSTANT, value=anyway_segment.name) else: conditional_routes = segments anyway_route = ConstantParameter(kind=ParameterKind.CONSTANT, value='-') column = SubjectDatasetColumn( columnId=str(column_index), parameter=ComputedParameter( kind=ParameterKind.COMPUTED, type=ParameterComputeType.CASE_THEN, parameters=[ *ArrayHelper(conditional_routes).map( lambda x: self.to_category_case_route(x, measure_on_factor)).to_list(), anyway_route ] ), alias=f'column_{column_index}' ) else: raise IndicatorKernelException(f'Measure[{measure_on}] is not supported.') return column, column_index, column_index + 1
def translate_constant(param: ConstantParameter) -> ConstantParameter: # in constant, use alias name from subject columns # translate is not needed here return ConstantParameter(kind=ParameterKind.CONSTANT, value=param.value)
def fake_time_range_to_report(self) -> Optional[ParameterJoint]: time_range_factor_id = self.inspection.timeRangeFactorId if is_blank(time_range_factor_id): return None time_range_column = self.find_column(time_range_factor_id, lambda: 'Time range factor not declared.') time_ranges = ArrayHelper(self.inspection.timeRanges) \ .filter(lambda x: x is not None and x.value is not None).to_list() if len(time_ranges) == 0: # no ranges given return None operator = ParameterExpressionOperator.EQUALS if len(time_ranges) == 1 else ParameterExpressionOperator.IN right = time_ranges[0].value if len(time_ranges) == 1 \ else ArrayHelper(time_ranges).map(lambda x: x.value).join(',') time_range_measure = self.inspection.timeRangeMeasure if isinstance(time_range_column.parameter, TopicFactorParameter): topic_id = time_range_column.parameter.topicId if is_blank(topic_id): raise IndicatorKernelException(f'Topic not declared for time range factor[id={time_range_factor_id}].') topic = get_topic_service(self.principalService).find_by_id(topic_id) if topic is None: raise IndicatorKernelException(f'Topic[id={topic_id}] not found.') factor_id = time_range_column.parameter.factorId if is_blank(topic_id): raise IndicatorKernelException(f'Factor not declared for time range factor[id={time_range_factor_id}].') factor = ArrayHelper(topic.factors).find(lambda x: x.factorId == factor_id) if factor is None: raise IndicatorKernelException(f'Factor[id={factor_id}] not found on topic[id={topic_id}].') if self.has_year_or_month(factor): if time_range_measure == MeasureMethod.YEAR: compute_type = ParameterComputeType.YEAR_OF elif time_range_measure == MeasureMethod.MONTH: compute_type = ParameterComputeType.MONTH_OF else: raise IndicatorKernelException( f'Measure method[{time_range_measure}] for factor type[{factor.type}] is not supported.') joint = ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=ComputedParameter( kind=ParameterKind.COMPUTED, type=compute_type, parameters=[ TopicFactorParameter( kind=ParameterKind.TOPIC, topicId='1', factorId=time_range_factor_id) ] ), operator=operator, right=ConstantParameter(kind=ParameterKind.CONSTANT, value=str(right)) ) ] ) else: joint = ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId='1', factorId=time_range_factor_id), operator=operator, right=ConstantParameter(kind=ParameterKind.CONSTANT, value=str(right)) ) ] ) else: joint = ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId='1', factorId=time_range_factor_id), operator=operator, right=ConstantParameter(kind=ParameterKind.CONSTANT, value=str(right)) ) ] ) return joint
def to_mapping_factor(target_factor: Factor) -> MappingFactor: return MappingFactor( source=ConstantParameter(kind=ParameterKind.CONSTANT, value=f'{{{target_factor.name}}}'), arithmetic=AggregateArithmetic.NONE, factorId=target_factor.factorId )
def test_single_topic(self): self.prepare_data() subject = Subject(dataset=SubjectDataset(columns=[ SubjectDatasetColumn( columnId='1', parameter=ComputedParameter( kind=ParameterKind.COMPUTED, type=ParameterComputeType.ADD, parameters=[ TopicFactorParameter(kind=ParameterKind.TOPIC, topicId='1', factorId='1'), ConstantParameter(kind=ParameterKind.CONSTANT, value='2') ]), alias='Column1', arithmetic=SubjectColumnArithmetic.SUMMARY), SubjectDatasetColumn( columnId='2', parameter=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId='1', factorId='1'), alias='Column2'), SubjectDatasetColumn(columnId='3', parameter=ConstantParameter( kind=ParameterKind.CONSTANT, value='{&now}'), alias='Column3'), SubjectDatasetColumn(columnId='4', parameter=ConstantParameter( kind=ParameterKind.CONSTANT, value='HELLO WORLD!'), alias='Column4'), SubjectDatasetColumn( columnId='5', parameter=ComputedParameter( kind=ParameterKind.COMPUTED, type=ParameterComputeType.ADD, parameters=[ ConstantParameter(kind=ParameterKind.CONSTANT, value='201'), ConstantParameter(kind=ParameterKind.CONSTANT, value='102') ]), alias='Column5'), SubjectDatasetColumn(columnId='6', parameter=ComputedParameter( kind=ParameterKind.COMPUTED, type=ParameterComputeType.YEAR_OF, parameters=[ ConstantParameter( kind=ParameterKind.CONSTANT, value='2022/03/03'), ]), alias='Column6'), SubjectDatasetColumn( columnId='7', parameter=TopicFactorParameter( kind=ParameterKind.TOPIC, topicId='1', factorId='2'), alias='Column7') ]), connectId='1', userId='1', tenantId='1') subject_data_service = SubjectDataService( subject, create_fake_principal_service()) page = subject_data_service.page(Pageable(pageNumber=1, pageSize=100)) print(page) report = Report( indicators=[ ReportIndicator(columnId='1', name='sum_value', arithmetic=ReportIndicatorArithmetic.SUMMARY) ], dimensions=[ReportDimension(columnId='7', name='enabled')], filters=ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=TopicFactorParameter(kind=ParameterKind.TOPIC, factorId='7'), operator=ParameterExpressionOperator.EQUALS, right=ConstantParameter(kind=ParameterKind.CONSTANT, value='true')) ])) report_data_service = ReportDataService( subject, report, create_fake_principal_service(), False) data = report_data_service.find() print(data)
def test_no_storage_filter(self): joint = ParameterJoint( jointType=ParameterJointType.OR, filters=[ # 0 ParameterExpression( left=ConstantParameter(value='abc'), operator=ParameterExpressionOperator.EMPTY), # 1 ParameterExpression( left=ConstantParameter(value='2022/01'), operator=ParameterExpressionOperator.NOT_EMPTY), # 2 ParameterExpression( left=ConstantParameter(value='2'), operator=ParameterExpressionOperator.EQUALS, right=ComputedParameter(type=ParameterComputeType.ADD, parameters=[ ConstantParameter(value='0'), ConstantParameter(value='2') ])), # 3 ParameterExpression( left=ConstantParameter(value='{items.&count}'), operator=ParameterExpressionOperator.NOT_EQUALS, right=ConstantParameter(value='{items.amount.&sum}')), # 4 ParameterExpression( left=ConstantParameter(value='10'), operator=ParameterExpressionOperator.LESS_EQUALS, right=ComputedParameter( type=ParameterComputeType.CASE_THEN, parameters=[ ConstantParameter( conditional=True, on=ParameterJoint(filters=[ ParameterExpression( left=ConstantParameter( value='{&old.customer.name}'), operator=ParameterExpressionOperator. NOT_EMPTY) ]), value='{&old.customer.name.&length}'), ConstantParameter(value='{customer.name.&length}') ])) ]) principal_service = create_fake_principal_service() # noinspection PyTypeChecker parsed_joint: ParsedStorageJoint = parse_condition_for_storage( joint, [], principal_service, True) # print(parsed_joint) previous_data = { 'items': [{ 'name': 'name-1', 'amount': 100 }], 'customer': { 'name': 'customer-11' } } current_data = { 'items': [{ 'name': 'name-1', 'amount': 100 }, { 'name': 'name-2', 'amount': 101 }], 'customer': { 'name': 'customer-1' } } variables = PipelineVariables(previous_data, current_data, None) result: EntityCriteriaJoint = parsed_joint.run(variables, principal_service) # assertion self.assertEqual(result.conjunction, EntityCriteriaJointConjunction.OR) self.assertEqual(len(result.children), 5) # expression 0 exp0: EntityCriteriaExpression = result.children[0] self.assertIsInstance(exp0, EntityCriteriaExpression) self.assertEqual(exp0.left, 'abc') self.assertEqual(exp0.operator, EntityCriteriaOperator.IS_EMPTY) self.assertIsNone(exp0.right) # expression 1 exp1: EntityCriteriaExpression = result.children[1] self.assertIsInstance(exp1, EntityCriteriaExpression) self.assertEqual(exp1.left, '2022/01') self.assertEqual(exp1.operator, EntityCriteriaOperator.IS_NOT_EMPTY) self.assertIsNone(exp1.right) # expression 2 exp2: EntityCriteriaExpression = result.children[2] self.assertIsInstance(exp2, EntityCriteriaExpression) self.assertEqual(exp2.left, '2') self.assertEqual(exp2.operator, EntityCriteriaOperator.EQUALS) exp2_right: ComputedLiteral = exp2.right self.assertIsInstance(exp2_right, ComputedLiteral) self.assertEqual(exp2_right.operator, ComputedLiteralOperator.ADD) self.assertEqual(exp2_right.elements, ['0', '2']) # expression 3 exp3: EntityCriteriaExpression = result.children[3] self.assertIsInstance(exp3, EntityCriteriaExpression) self.assertEqual(exp3.left, 2) self.assertIsInstance(exp3.left, int) self.assertEqual(exp3.operator, EntityCriteriaOperator.NOT_EQUALS) self.assertEqual(exp3.right, 201) self.assertIsInstance(exp3.right, Decimal) # expression 4 exp4: EntityCriteriaExpression = result.children[4] self.assertIsInstance(exp4, EntityCriteriaExpression) self.assertEqual(exp4.left, '10') self.assertEqual(exp4.operator, EntityCriteriaOperator.LESS_THAN_OR_EQUALS) exp4_right: ComputedLiteral = exp4.right self.assertIsInstance(exp4_right, ComputedLiteral) self.assertEqual(exp4_right.operator, ComputedLiteralOperator.CASE_THEN) self.assertIsInstance(exp4_right.elements[0], Tuple) exp4_right_case_1_condition: EntityCriteriaJoint = exp4_right.elements[ 0][0] self.assertIsInstance(exp4_right_case_1_condition, EntityCriteriaJoint) self.assertEqual(exp4_right_case_1_condition.conjunction, EntityCriteriaJointConjunction.AND) self.assertEqual(len(exp4_right_case_1_condition.children), 1) exp4_right_case_1_condition_exp: EntityCriteriaExpression = exp4_right_case_1_condition.children[ 0] self.assertIsInstance(exp4_right_case_1_condition_exp, EntityCriteriaExpression) self.assertEqual(exp4_right_case_1_condition_exp.left, 'customer-11') self.assertEqual(exp4_right_case_1_condition_exp.operator, EntityCriteriaOperator.IS_NOT_EMPTY) exp4_right_case_1_value = exp4_right.elements[0][1] self.assertEqual(exp4_right_case_1_value, 11) self.assertIsInstance(exp4_right_case_1_value, int) exp4_right_anyway = exp4_right.elements[1] self.assertEqual(exp4_right_anyway, 10) self.assertIsInstance(exp4_right_anyway, int)
def ask_dqc_pipelines(topics: List[Topic]) -> List[Pipeline]: # define all dqc pipelines topic_raw: Topic = find_topic(topics, 'dqc_raw_rule_result') topic_daily: Topic = find_topic(topics, 'dqc_rule_daily') return [ Pipeline( name='DQC Pipeline', topicId=topic_raw.topicId, type=PipelineTriggerType.INSERT_OR_MERGE, stages=[ PipelineStage( stageId='dqcp-s-1', name='DQC Pipeline Stage 1', units=[ PipelineUnit( unitId='dqcp-u-1', name='DQC Pipeline Unit 1', do=[ InsertOrMergeRowAction( actionId='dqcp-a-1', type=WriteTopicActionType. INSERT_OR_MERGE_ROW, topicId=topic_daily.topicId, mapping=[ MappingFactor( source=find_source_parameter( topic_raw, 'ruleCode'), factorId=find_factor( topic_daily, 'ruleCode').factorId), MappingFactor( source=find_source_parameter( topic_raw, 'topicId'), factorId=find_factor( topic_daily, 'topicId').factorId), MappingFactor( source=find_source_parameter( topic_raw, 'factorId'), factorId=find_factor( topic_daily, 'factorId').factorId), MappingFactor( source=find_part_of_process_date( topic_raw, 'processDate', ParameterComputeType.YEAR_OF), factorId=find_factor( topic_daily, 'year').factorId), MappingFactor( source=find_part_of_process_date( topic_raw, 'processDate', ParameterComputeType.MONTH_OF), factorId=find_factor( topic_daily, 'month').factorId), MappingFactor( source=find_part_of_process_date( topic_raw, 'processDate', ParameterComputeType. DAY_OF_MONTH), factorId=find_factor( topic_daily, 'day').factorId), MappingFactor( source=find_source_parameter( topic_raw, 'processDate'), factorId=find_factor( topic_daily, 'processDate').factorId), MappingFactor(source=ComputedParameter( kind=ParameterKind.COMPUTED, type=ParameterComputeType. CASE_THEN, parameters=[ ConstantParameter( kind=ParameterKind. CONSTANT, conditional=True, on=ParameterJoint( jointType= ParameterJointType.AND, filters=[ ParameterExpression( left= find_source_parameter( topic_raw, 'detected' ), operator= ParameterExpressionOperator .EQUALS, right= ConstantParameter( kind= ParameterKind .CONSTANT, value="true" )) ]), value="1"), ConstantParameter( kind=ParameterKind. CONSTANT, value="0") ]), factorId=find_factor( topic_daily, 'count').factorId) ], by=ParameterJoint( jointType=ParameterJointType.AND, filters=[ ParameterExpression( left=find_source_parameter( topic_raw, 'ruleCode'), operator= ParameterExpressionOperator. EQUALS, right=find_source_parameter( topic_daily, 'ruleCode')), ParameterExpression( left=find_source_parameter( topic_raw, 'topicId'), operator= ParameterExpressionOperator. EQUALS, right=find_source_parameter( topic_daily, 'topicId')), ParameterExpression( left=find_source_parameter( topic_raw, 'factorId'), operator= ParameterExpressionOperator. EQUALS, right=find_source_parameter( topic_daily, 'factorId')), ParameterExpression( left=find_part_of_process_date( topic_raw, 'processDate', ParameterComputeType. YEAR_OF), operator= ParameterExpressionOperator. EQUALS, right=find_source_parameter( topic_daily, 'year')), ParameterExpression( left=find_part_of_process_date( topic_raw, 'processDate', ParameterComputeType. MONTH_OF), operator= ParameterExpressionOperator. EQUALS, right=find_source_parameter( topic_daily, 'month')), ParameterExpression( left=find_part_of_process_date( topic_raw, 'processDate', ParameterComputeType. DAY_OF_MONTH), operator= ParameterExpressionOperator. EQUALS, right=find_source_parameter( topic_daily, 'day')) ])) ]) ]) ], enabled=True, validated=True) ]
def test_to_dict(self): dm = DataModel(a=1, b='2', c=True, d=datetime.now()) x = dm.to_dict() print(x) action = InsertOrMergeRowAction( actionId='1', type=WriteTopicActionType.INSERT_OR_MERGE_ROW, topicId='1', mapping=[ MappingFactor(factorId='1', parameter=ConstantParameter( kind=ParameterKind.CONSTANT, value='100')) ], by=ParameterJoint( jointType=ParameterJointType.AND, filters=[ # 0 ParameterExpression( left=ConstantParameter(value='abc'), operator=ParameterExpressionOperator.EMPTY), # 1 ParameterExpression( left=ConstantParameter(value='2022/01'), operator=ParameterExpressionOperator.NOT_EMPTY), # 2 ParameterExpression( left=ConstantParameter(value='2'), operator=ParameterExpressionOperator.EQUALS, right=ComputedParameter( type=ParameterComputeType.ADD, parameters=[ ConstantParameter(value='0'), ConstantParameter(value='2') ])), # 3 ParameterExpression( left=ConstantParameter(value='{items.&count}'), operator=ParameterExpressionOperator.NOT_EQUALS, right=ConstantParameter(value='{items.amount.&sum}')), # 4 ParameterExpression( left=ConstantParameter(value='10'), operator=ParameterExpressionOperator.LESS_EQUALS, right=ComputedParameter( type=ParameterComputeType.CASE_THEN, parameters=[ ConstantParameter( conditional=True, on=ParameterJoint(filters=[ ParameterExpression( left=ConstantParameter( value='{&old.customer.name}'), operator=ParameterExpressionOperator .NOT_EMPTY) ]), value='{&old.customer.name.&length}'), ConstantParameter( value='{customer.name.&length}') ])) ])) x = action.to_dict() print(x)
def build_value_criteria_right(self, topic_id: TopicId, factor_id: FactorId, value: Optional[str]): return ConstantParameter(kind=ParameterKind.CONSTANT, value=value)