Booking filters
PaxFlow Customer Support avatar
Written by PaxFlow Customer Support
Updated over a week ago

Activity filters are powerful tools that let you customize your PaxFlow experience deeper than with any other method. They can be used to change activities according to custom rules and filter for activities to display on custom reports. With these filters, you can automate and customize PaxFlow to implement your business logic as closely as possible.

Note on terminology used throughout this article and inside PaxFlow:
Activity: An activity is one booked tour inside a booking.

Booking: The whole cart with all activities that a customer booked at once is called a booking.

Filter Basics

Filters are written in the JSON data format. If you are new to JSON, please refer the guide Working with JSON to get started. (This is a great introduction to JSON by Mozilla).

To create a filter, the JSON object needs to have at least an if block and then, depending on the use case, a then block (to be used as a filter) and optionally a report block, if used in a report. An if block defines the condition when the filter applies. A then block defines what happens when the condition applies. For example, the filter shown below states that if an activity has the departure_id equal to 12345 and the customer_email field is not set, set it to [email protected].

{
  "if": {
    "departure_id": 12345,
    "customer_email": null
  },
  "then": {
    "customer_email": "[email protected]"
  }
}

Activity filters are applied when displaying & working with activities. The modifications made by applying filters are not persistent (not saved to the database). This implies, if the data is altered in the filters, no original information is lost. Filters can also have any additional data in them. In case it is a valid JSON, the additional information is ignored. However, if a filter has invalid JSON, it is treated as an inactive filter.

Please note that using filters can slow down PaxFlow if many are applied at the same time.

How to use the filter UI

Although the effects of activity filters are applied throughout the PaxFlow system, there are two main user interfaces for using filters: the Booking filter UI and Custom reports.

Filter Settings

Under Booking filters you can create and edit filters. You can also configure filter properties like if it should be applied automatically as a filter or use it to filter activities for a report or both.

Also, you can look up an activity to see all the variables that it has and the fields you can use to filter for or which you can possibly modify.

For an activity, you can view the 'Filter pipeline' which shows all the filters applied to an activity one after the other and how those filters modify the activity before it is displayed.

Creating and Editing a Filter

Go to Bookings and click Booking filters. It shows the custom rules page which lists the existing filters, if any.

To create a new filter, click the Add button on the top right corner of the page.

The simple interface is only for custom reports, therefor the advanced editor needs to be selected to create filters.

Enter the filter properties on the following page and click Save.

Following table explains the filter properties required to create a new filter.

  • Title: Name of the filter

  • Order: This field defines the order in which filters are applied. Lower ordered filters are applied before higher ordered ones. For example, if there are three filters with orders 35,20 and 100 respectively, then first of all the one with order number 20 will be applied followed by the one with number 35 and in the end, the filter with order number 100 will be applied.

  • Is active as a filter: Select Yes, if the rule is to be used as a filter.

  • Is active as a report: Select Yes, if the rule is to be used for a report.

  • Filter code: The JSON code for the filter, which defines the condition and result or reporting rules for the filter. Details on how to write filter codes are provided in the sections below.

Please note that the JSON code added to filter code is always automatically validated. If it is a valid JSON code, it marks it as Valid JSON with a green tick mark at the bottom right of the form. Else, a red cross mark is shown and view details link shows the errors.

To edit an existing filter, go to the list of rules and select the rule to be edited. Modify the fields as required and click Save.

Looking up an Activity

When creating or editing a filter, the user can look up an activity to view all the fields of the activity and their values. This helps the users identify all the fields of an activity and use them in the code. Get the activity ID from the booking information. Enter the activity ID into the field at the end of the page and click Show Code as shown in the sample below.

Viewing the Filter pipeline for an activity

Filter pipeline shows all the active and valid filters in a sequence based on their individual order values. For example, the following filter pipeline shows two filters of which one is applied to the activity and the other isn't.

When different filters are applied to an activity, activity data changes. Filter pipeline shows the effect of each filter on an activity data.

Provide activity ID for the activity on which filters are to be applied and click Go. The activity data changes after shown after each filter as shown in the example below.

To view the activity data, click the expand icon.

Syntax

If block

The if block is used to specify the conditions that define the filter. Activity fields are matched against this condition and selected or shown in the reports. A condition is specified as a "key": "value" pair where the key is the column / field to be matched and value is what it should match against. Value can be a single value or an array of values.

For example, the following if block specifies match all the activities where the customer_name variable is exactly "Eru".

"if": {
  "customer_name":"Eru"
}

Another example where the key can match any of values from an array,

"if": {
  "tour_id":[2, 3, 4]
}

In the above case, tour_id can take any of the values from 2, 3 or 4 (similar to IN() function in SQL).

You can also use OR, AND, XOR or NOT to specify complex conditions.

Example 1: Using NOT - select if customer_name is not Melkor.

"if": {
  "customer_name": {
    "not": "Melkor"
  }
}

Example 2: Using OR - select if customer_first_name is Manwe or customer_last_name is Ulmo

"if": {
  "or": {
    "customer_first_name": "Manwe",
    "customer_last_name":"Ulmo"
  }
}

Example 3: Using AND - select if customer_first_name is Aule and customer_last_name is Orome.

"if": {
  "and": {
    "customer_first_name": "Aule",
    "customer_last_name": "Orome"
  }
}

Example 4: Using XOR - select if either customer_first_name is Namo or customer_last_name is Irmo but not both.

"if": {
  "xor": {
    "customer_first_name": "Namo",
    "customer_last_name": "Irmo"
  }
}

Numerical values can also be compared using keywords less and more. For example,

"if": {
  "tour_id": {
    "less": 50
  }
}

The above condition matches all activities where tour_id is less than 50. Similarly, 'more' can also be used for numerical comparisons.

Nested ifs

Multiple if blocks can be nested as shown below.

"if": {
  "and": [
    {
      "or": {
        "customer_first_name": "Tulkas",
        "customer_first_name": "Varda"
      }
    },
    {
      "or": {
        "customer_last_name": "Yavanna",
        "customer_last_name": "Nienna"
      }
    }
  ]
}

Then block

The then block specifies the action to be taken when an activity matches the condition specified in the if block. It is also a JSON object and the variables are set in the order you write them down in the filter code.

The most simple example is to set a fixed value to a variable. For example, in the below example, customer name is set to "Gwaihir".

"then": {
  "customer_name": "Gwaihir"
}

See the Advanced section below learn more about referencing values from other variables.

Special functions

Additionally to setting variables in the then block, you can also use special functions that do more complex ways:

pickup_inherit & dropoff_inherit: those can take the value from_pickup, from_dropoff and from_dropoff_or_pickup. Refer "Using filters with combo products" below for more information.

paxlist_custom can be used to highlight activities in the passenger list. It accepts an object with details as an argument:

"paxlist_custom": {
  "title": "Last minute booking",
  "text": "New!",
  "icon": "rocket",
  "color": "warning",
  "desktop": true,
  "tablet": false
}

The icon is one of the fontawesome 4.7 icons, the color can be one of the Bootstrap color codes mainly: primary, secondary, success, warning, danger, info. The icon and/or the text are shown in this color.

The text will be shown in the passenger list itself, it is just as the icon optionally (it doesn’t make sense to have none of them though). The title will be the tooltip of the icon / text on the desktop passenger list.

With desktop/tablet you control if this icon / text are shown on the desktop, tablet or both.

Report block

In the report block, you can define some options or fields to be used in a custom report.

Example of all possible settings:

{
  "title": "My Little Report - filters are magic",
"based_on": "booking_date",
"date_from": "-2weeks",
"date_to": "tomorrow",
"statuses":["ARRIVED", "NO_SHOW"],
"columns": ["start_date", "customer_name", "customer_email"]
}

You can define a title that’s used for the report instead of the filter title itself. The statuses define an array of statuses (see in your booking system’s documentation about possible statuses) that are selected by default.

Valid values for the based_on parameter are:

  • booking_date - The date when the booking was created

  • cancellation_date - The date when a cancelled booking was cancelled

  • start_date - The date when an activity starts to be operated

  • no_shows - The date when an activity was marked as no_show

date_from and date_to support all valid PHP date formats including relative formats as shown above. Refer the PHP documentation and References section below for more help.

With the based_on and date options you can build reports like “Show all bookings cancelled last week” or “show all bookings due to be operated in the last week of May”.

The columns option defines the columns that will be exported when downloading the data of a report as CSV. By default the columns exported are the ones shown in the user interface.

Advanced

Nested variables

Some variables in the activities are nested, use dotted notation to refer to such variables. For example,

"opdb": {
  "notes": {
    "booking": "X"
  }
}

You can address such variables as shown below:

"if": {
  "opdb.notes.booking": ...
}"then":{
  "opdb.notes.booking": ...
}

Referencing value from another variable

If you want to copy the value of one variable into another or compare two variables, you can substitute any constant value (e.g. 50 or "Este") by referring to another variable using the from command. For example,

"if": {
  "height": {
    "less": {
      "from": "max_height"
    }
  }
}"then": {
  "my_variable": {
    "from": "customer_name"
  }
}

Regular expression matching

It is possible to match a value against a regular expression. For example,

"if": {
  "customer_name": {
    "regex": "/^Gand/i"
  }
}

The above condition returns all customer names that start with "Gand", case insensitive. Please note that filters use PCRE syntax for regular expressions.

Replacing from a template

It is possible to replace a text in three different ways. All of them need a template. Basic example:

"then": {
  "greeting": {
    "template": "Aiya, {customer_name}!",
    "replace_vars": ["customer_name"]
  }
}

This will use the template "Aiya, {customer_name}!", replace "{customer_name}" by the content of the variable "customer_name" in it and store it into "greeting".

Replacing variables

To replace variables, put the names of the variables you want to replace into replace_vars as shown above.

Replacing text

Replacing text works similar, except for that you use replace_text:

{
  "template": "Hello",
  "replace_text": {
    "e":"a"
  }
}

This will give you "Hallo".

Replacing with regular expressions

For more advanced replacing, you can switch from text matching to regular expression matching. In this case, use replace_regex. It uses the PCRE regex engine. Example:

{
  "template": "We pick up people from all downtown hostels",
  "replace_regex": {
    "/hos?tel/i": "accommodation"
  }
}

This will replace both "hotel" and "hostel" with the word "accommodation".

Combining replacing with referenced variables

Using these replacing techniques is most useful when combined with fetching the value where you want to replace in from another variable. Example:

"ticket_number": {
  "template": {
    "from": "external_booking_reference"
  },
  "replace_regex": {
    "[ABC]-": "X-"
  }
}

This replaces all "A-", "B-" and "C-" in the external booking reference by X- and stores the result in "ticket_number".

Using filters with combo products

It is possible to structure your combo products using PaxFlow filters. This is especially useful when it comes to pickup & drop off locations.

Imagine there are two tours, a Sheep Petting Tour (departure ID 42) and a Dolphin Watching Tour (departure ID 23). There also exists a combo of both, a Sheep Petting And Dolphin Watching Combo Tour (departure ID 1312). Pickup for the Sheep Petting Tour is at the activity’s pickup location, drop-off at the Harbour, an hour later the Dolphin Watching Tour picks up at the Harbour and drops off later on at the activity's drop-off location.

The filters to set this up would be:

{
  "if": {
    "departure_id": 42,
    "combo_parent_departure_id": 1312
  },
  "then": {
    "pickup_inherit": "from_pickup",
    "dropoff_place_id": null,
    "dropoff_place_title": null,
    "dropoff_place_custom": "Harbor",
    "is_supported_dropoff": true,
    "dropoff_filtered": true,
    "dropoff_filtered_always_custom": true,
    "dropoff_filtered_message": "Drop-Off is always at the Harbor",
  }
}{
  "if":{
    "departure_id": 23,
    "combo_parent_departure_id": 1312
  },
  "then": {
    "pickup_place_id": null,
    "pickup_place_title": null,
    "pickup_place_custom": "Harbor",
    "is_supported_pickup": true,
    "pickup_filtered": true,
    "pickup_filtered_always_custom": true,
    "pickup_filtered_message": "Pickup is always at the Harbor",
    "dropoff_inherit": "from_dropoff_or_pickup"
  }
}

References

Regular Expressions Search and Replacement - https://www.php.net/manual/en/function.preg-replace.php

Did this answer your question?