def _get_reason(result, message, reason_from_func, default_reason): """ Returns reason in priority: message > reason_from_func > default_reason. Helper function to determine the reason string. """ if message and not result: return message if reason_from_func: return reason_from_func return default_reason def check_rule(source_result, against_result, optional_settings, rejection, message=None): """ Compares source_result against against_result using the specified operator. :param source_result: The source value to compare :param against_result: List containing [value, operator] to compare against :param optional_settings: List containing [source_option, against_option] :param message: Optional custom message to return :return: list where index 0 is result[bool] and index 1 is reason[string] """ operator = against_result[1] against_result_value = against_result[0] empty_data = [None, "", {}, []] source_option = optional_settings[0] against_option = optional_settings[1] reason_from_func = None if source_result is None: numeric_operators = {"greaterThanEqual", "lessThanEqual", "greaterThan", "lessThan", "inBetween", "notInBetween"} if operator in numeric_operators: source_result = 0 else: source_result = "" empty_data = [None, "", {}, []] # Check if values are empty if source_result not in empty_data and against_result_value not in empty_data: # Handle list in against_result_value if isinstance(against_result_value, list): against_result_value = against_result[0][0] reason_from_func = against_result[0][1] numeric_operators = {"greaterThanEqual", "lessThanEqual", "greaterThan", "lessThan"} if isinstance(against_result_value, int): # round off added against_result_value = round(against_result_value) target = float(against_result_value) if operator in numeric_operators else against_result_value # Comparison operator mapping comparison_operators = { "equal": lambda: target == source_result, "greaterThanEqual": lambda: target >= source_result, "lessThanEqual": lambda: target <= source_result, "greaterThan": lambda: target > source_result, "lessThan": lambda: target < source_result } if operator in comparison_operators: result = comparison_operators[operator]() default_reason = ( f"{'Passed:' if result else 'Failed: '} {target} " f"{operator if result else 'not ' + operator} {source_result}" ) reason = _get_reason(result, message, reason_from_func, default_reason) elif operator == "inBetween": result = source_result[0] <= int(target) <= source_result[-1] default_reason = ( f"Passed: {target} in between {source_result[0]} and {source_result[-1]}" if result else f"Failed: {target} not in between {source_result[0]} and {source_result[-1]}" ) reason = _get_reason(result, message, reason_from_func, default_reason) elif operator == "notInBetween": result = not (source_result[0] < int(target) < source_result[-1]) default_reason = ( f"Passed: {target} not in between {source_result[0]} and {source_result[-1]}" if result else f"Failed: {target} not in between {source_result[0]} and {source_result[-1]}" ) reason = _get_reason(result, message, reason_from_func, default_reason) elif operator == "inList": result = str(source_result) in against_result[0] default_reason = ( f"{'Passed: ' if result else 'Failed: '} {source_result} " f"{operator if result else 'not ' + operator} {against_result[0]}" ) reason = _get_reason(result, message, reason_from_func, default_reason) elif operator == "notInList": result = source_result not in against_result[0] default_reason = ( f"{'Passed: ' if result else 'Failed: '} {source_result} " f"{'notInList' if result else 'inList'} {against_result[0]}" ) reason = _get_reason(result, message, reason_from_func, default_reason) # Unmatched operator else: result = False reason = f"Failed: Unmatched Operator {operator}" # Handle optional settings elif source_option == 1 or against_option == 1: result = True option = {"source": source_option, "against": against_option} reason = f"Passed: Optional Setting is True: {option}" # Empty data case else: if rejection: result = None reason = "Data not found" else: result = True reason = "NTC Case - No tradelines found" return [result, reason]