Fluent Commerce Logo
Docs
Sign In

Case Scenario - Implement Fraud Check

Essential knowledge

Authors:

Ankit Mehta, Cille Schliebitz, Anita Gu

Changed on:

4 Feb 2025

Overview

In this scenario we will implement a Fraud Check step in the Order Workflow

Key points

  • Prerequisites setup
  • Basics of Rule writing

Client Scenario — Implement Fraud Check.

  • Our Client has experienced a high number of fraud cases in the past 6 months. 
  • In order to resolve the problem, our client has decided to implement fraud protection into their Order Fulfilment Workflow. 
  • Instead of manually verifying incoming orders, the client now wishes to implement an automated mechanism to check.

So, if the total price is greater than the standard value — let's say the standard value is called  HighValueThreshold, then create a 'flag' on the order. Based on the client scenario, we will now view the results after a requirements analysis and solution design has been conducted.

🔎 Requirements Analysis 

Flag the Order as 'HIGH VALUE' when the Order's Total Price is greater than HighValueThreshold

⚙️ Solution Design

Create a custom Rule in our Workflow with the following specifications:

  • Define a parameter for the Order Total Price Threshold: HighValueThreshold
  • Add a Boolean Attribute to the Order named IS_HIGH_VALUE, and set it to TRUE if the Order's Total Price is above the value defined in the HighValueThreshold parameter.
  • If the Order Total Price is less than (or equal to) the HighValueThreshold, then the rule will not do anything.

The next lesson contains exercises to help guide you through the steps for how to create a Rule.   In these exercises, you will need to use the results from the requirements analysis and solution design from the above scenario.

But before moving on please take note of some important design principles.

Designing your Rule

Most of the time, you will be thinking about the Rule in the context of a specific Workflow and Use Case.  It is also important to think about your Rule design.   Follow the basic design principles when designing your Rule:

  • Be simplified
  • Be generic
  • Be flexible
  • Be re-usable
  • Be part of multiple compositions.

To learn more read Rule Development Guidelines & Recommended Practices and Designing Rules.

Writing the Rule

Create a Rule Class

In this module, you will learn how to create a Rule class in your Plugin Project and create a HighValueThreshold  constant. You will also learn how to declare @RuleInfo and @ParamString Annotations to the Rule class.

Remember the client scenario?

The steps below will use the Rule based on the Client Scenario — Implement Fraud Check.

In Steps 1 to 3 below, you will learn to write a Rule based on the solution designed as per the Client's requirement (discussed in the previous section). You will use the (earlier created) plugin project created earlier in the course.

 Step 1. Create a Rule Class
  • Using any Java IDE (we are using IntelliJ) open the Plugin Project created in the previous section.
  • Create a new class named MarkOrderHighValueRule — Right-click on the src/main/java/com.training/rule folder of your plugin project to create a new java class. Name the class as MarkOrderHighValueRule 
  • Implement the v2 Rule Interface — Make your class 'MarkOrderHighValueRule', and  implement Rule Interface com.fluentretail.rubix.v2.rule.Rule
  • Override the run method and use the context in the run method.  Please note, the v2 Rule interface is the one that supports GraphQL.

Important:  Please import com.fluentretail.rubix.v2.rule.Rule interface.

Please follow the Rule's naming convention on Fluent Docs

👁‍🗨 Video Demonstration for Step 1

This video illustrates:

✅ How to create a Rule Class

✅ Import com.fluentretail.rubix.v2.rule.Rule

✅ How to pass the Context to run method.

Step 2. Create a HighValueThreshold Constant (solution design specification)

To avoid magic Strings, declare your constants in the src/main/java.com/training/util folder. 

Define the HighValueThreshold parameter (required in the Solution design) in the util package by using the below code:

    

`public static final String PARAM_NAME_HIGH_VALUE_THRESHOLD = "highValueThreshold"`

Step 3. Add @RuleInfo and @ParamString annotations

Param parameters are inputs required to configure Rule in the ruleset. These parameters are set for every execution.

Event-based parameters are optional and are Context-specific at run time.

As per the Solution Design, we need to provide the data about the constant "highValueThreshold" to the Rule as below: 

`@ParamInteger(name = Constants.PARAM_NAME_HIGH_VALUE_THRESHOLD, description = "The value threshold of which Orders should be marked as High Value")`

Use accepts property to list which Entity type is accepted by the rule. Some Rules can accept only some specific entities if we don't use accepts then Rule can accept any Orchestration entity.

No alt provided
  • RuleInfo: Name will include the name of the Rule class (which will be the class you have created) 
  • description in @RuleInfo: It is a brief description that what is rule doing and what parameters it is using
  • accepts: In the case scenario , the Rule accepts only ORDER entity
  • @ParamInteger: Shows the name, description and default value of parameter.

⚠️  After Steps 1- 3 your code should look like given below. Refer to the code below to make sure you have imported correct packages.

1package com.training.rule;
2
3import com.fluentretail.rubix.event.Event;
4import com.fluentretail.rubix.foundation.graphql.type.UpdateOrderInput;
5import com.fluentretail.rubix.rule.meta.EventInfo;
6import com.fluentretail.rubix.rule.meta.ParamInteger;
7import com.fluentretail.rubix.rule.meta.RuleInfo;
8import com.fluentretail.rubix.v2.context.Context;
9import com.fluentretail.rubix.v2.rule.Rule;
10import com.training.util.Constants;
11
12@RuleInfo(name = "MarkOrderHighValueRule"
13        , description = "Mark the Order as HIGH_VALUE when the Order " +
14        "Total Price is greater than {" + Constants.PARAM_NAME_HIGH_VALUE_THRESHOLD + "}"
15        , accepts = {
16        @EventInfo(entityType = "ORDER")
17                    }
18        )
19@ParamInteger(name = Constants.PARAM_NAME_HIGH_VALUE_THRESHOLD, description = "The value " +
20        "threshold of which Orders should be marked as High Value", defaultValue = 1000)
21
22
23public class MarkOrderHighValueRule implements Rule
24{
25    @Override
26    public <C extends Context> void run(C context)
27    {
28
29    }
30}

Language: plain_text

Name: MarkOrderHighValueRule.java

Description:

Refer to the code to make sure you have imported the correct packages.

👁‍🗨 Video Demonstration for Steps 2 & 3

This video illustrates how to:

✅ Create a constant in util folder.

✅ Use @RuleInfo annotation

 Use @ParamString annotation

Configure the run method

In this lesson, you will learn how to configure the run method in the Rule Class

Remember this client?

In this lesson, you will learn how to configure the run method in the MarkOrderHighValueRule class.   You will write the five stages (phases) of the run method to get the desired solution,  based on the Client Scenario — Implement Fraud Check covered in the previous lesson.

Run method — Validation

The Validation stage (phase) lets you validate all the required inputs to the Rule. If parameters or attributes are not provided then you either fail early or exit early. If proper validation is not done then 'NullPointerException' or 'ClassCastException' occurs.  If any required Validation fails, your Rule should exit immediately. To do this, you can either:

  • Use a return statement to exit immediately but continue processing the Ruleset, or
  • Throw an Exception, and stop processing the Ruleset.

Note that both options are dependent on the behaviour of the Rule Validation logic.  

There is a 'RuleUtils' class in the Plugin project.  The class facilitate  the validation process by providing boolean responses and exception management

Steps to validate your Rule

Follow the steps below to validate your rule.  Use the checkboxes to track your progress as you complete each step:

You may also choose to watch the Video Demo below to see how each step is performed/executed.

  • context.getProp (Constants. CONSTANT NAME, TYPE.class) is used to get the local constant — save the retrieved constant in a variable.
  • Validate the value retrieved and throw the exception if 'not valid' or 'null'.
No alt provided
Run method — Retrieve data/query

The Retrieve Data / Query stage (phase) is optional and is dependent on business needs. This stage helps you to get additional data that you need to execute your Rule.  Please note that you will be using the query created in the 'GraphQL within Java IDE'

Steps to execute your Rule

Follow the steps below to execute your rule.  Use the checkboxes to track your progress as you complete each step:

Reminder: You may also choose to watch the Video Demo below to see how each step is performed/executed.

  • Use  context.getEvent().getEntityId() to retrieve the Order ID from the context
  • In the pervious section "PLUGIN STRUCTURE & GRAPHQL" you have run a query "GetOrderByIdQuery " and have created a query Object . Now use  GetOrderByIdQuery.builder().id(orderId).build( )  method to create an instance of the created "GetOrderByIdQuery "GraphQl Query Object.
  • Execute the GraphQL Query using the GraphQL API Client provided by the context by using  context.api().query() 
  • Create a method that validates the retrieved data by asserting it with expected data. The code snippet for this method is provided below.
  • Call the above method in the run method to validate the retrieved data.

Given below is the validation method code snippet . This method throws an exception if the  retrieved Order or the Order attribute is null. 

1 /*
2     * Query Result Validation Code extracted into Private method, but should be a Util method.    
3     */
4    private void validateQueryResult(GetOrderByIdQuery.Data data, String orderId, Context context) {
5
6        if (data.orderById() == null) {
7            throw new RuleExecutionException(String.format("Unable to process Rule: %s - No Order Found for Id: %s, Order Ref: %s",this.getName(),orderId, context.getEntity().getRef()), context.getEvent());
8        }
9
10        if (data.orderById().totalPrice() == null) {
11            throw new RuleExecutionException(String.format("Unable to process Rule: %s - No TotalPrice Found for Order Id: %s, Order Ref: %s",this.getName(),orderId, context.getEntity().getRef()), context.getEvent());
12        }  
13    }

Language: plain_text

Name: Validation method

Description:

This method throws an exception if the  retrieved Order or the Order attribute is null. 

👁‍🗨 Video Demonstration — Steps 1 and 2

This video illustrates how to:

✅ Include validation stage in the run method of the Rule class.

✅ Include stage - Retrieve and validate retrieved in the run method of the Rule class.

Run method — Write conditional logic

This phase performs any conditional logic required before building and producing action.   Use a simple if statement to write condition logic.

In the Client Scenario,  the Rule's action is executed on the below condition:

 'If totalPrice of the Order is greater than a threshold parameter' code snippet:

1// Simple Logic:
2if (data.orderById().totalPrice() <= threshold) {
3return;
4}

Language: plain_text

Name: Rule condition

Description:

If totalPrice of the Order is greater than a threshold parameter.

Reminder:  You may also choose to watch the Video Demo below to see how each step is performed/executed.

Run method — Build action data

The data needed for the action is prepared and action is built in this stage. A Rule will produce an output action like:

  • Mutation (update or save some new or changed data) 
  • SendEvent (send an event to trigger workflow)
  • SendWebhook (send an event to an external system)

Reminder: You may choose to watch the Video Demo below to see how each step is performed/executed.

Steps to build an action

In the Client scenario, let's say we want to save a new attribute to the Order indicating the Order is 'High Value'. To do so we can do the following:

  • Define your GraphQL Mutation query in the src/main/graphql/mutations folder.
  • Run a maven build to generate the Mutation Java Object.
1mutation updateOrderAttributes($input: UpdateOrderInput) {
2 updateOrder(input: $input) {
3     ref
4 }
5}

Language: plain_text

Name: Mutation query

Description:

GQL to run an updateOrder mutation 

  •  Add a constant to hold the Attribute key in the Constants class. i.e create a new boolean AttributeInput named IS_HIGH_VALUE with a value of TRUE.
  • Write a method that creates and returns a List <AttributeInput>. This attribute list is passed to the instance of UpdateOrderInput.  
1/*
2     * Extracted to private method, but should be a Util method.
3     */
4    private List<AttributeInput> createNewAttributeInputAsList(String attrName, Class type, Object attrValue) {
5
6        AttributeInput attrInput = AttributeInput.builder().name(attrName).type(type.getSimpleName().toUpperCase()).value(attrValue).build();
7        List<AttributeInput> attributeInputList = new ArrayList<>();
8        attributeInputList.add(attrInput);
9        return attributeInputList;
10    }

Language: plain_text

Name: Method

Description:

Method to create an attributes list

  • Build the mutation query Object in preparation for producing a Mutation Action as below:
1// Prepare for Action:
2        List<AttributeInput> attributeInputList = createNewAttributeInputAsList(IS_HIGH_VALUE_ORDER_ATTRIBUTE_NAME, Attribute.Type.BOOLEAN.getValueClass(), Boolean.TRUE);
3
4        UpdateOrderInput updateOrderInput =  UpdateOrderInput.builder()
5                                                                .id(orderId)
6                                                                .attributes(attributeInputList)
7                                                                .build();
8        UpdateOrderAttributesMutation updateOrderAttributesMutation = UpdateOrderAttributesMutation.builder().input(updateOrderInput).build();

Language: plain_text

Name: Mutation query object

Description:

Prepare the action by setting the orderId and attributesInputList to the updateOrderInput object

Run method — Produce action

The final stage of the run method is to produce the output action , action which you have built in the Build Action data.   

For our example , you can use context.action to produce action and mutate action by using the following code:

`context.action().mutation(updateOrderAttributesMutation);`

👁‍🗨 Video Demonstration — Steps 3 to 5

This video illustrates how to:

✅ Write the stage - write conditional logic in the run method

✅ Build the action data stage in the run method

✅  Produce the required action in the run method


Copyright © 2025 Fluent Retail Pty Ltd (trading as Fluent Commerce). All rights reserved. No materials on this docs.fluentcommerce.com site may be used in any way and/or for any purpose without prior written authorisation from Fluent Commerce. Current customers and partners shall use these materials strictly in accordance with the terms and conditions of their written agreements with Fluent Commerce or its affiliates.

Fluent Logo