&
|
>
=
OData Filter Builder

Filters & F Factory

Build type-safe OData filters with Python-like syntax

PythonF.Amount > 1000
ODataAmount gt 1000

Filter Translator

Convert OData syntax to Python F factory syntax

Try these:
CustomerID eq 'ABC123' and Amount gt 100...
Status eq 'Active' or Priority eq 1...
startswith(CustomerName, 'ABC') and cont...
year(CreatedDate) eq 2024 and month(Crea...
Price mul Quantity gt 500...
CustomerClass in ('WHOLESALE', 'RETAIL')...
Translation will appear here...

The F Factory

The F factory is your gateway to building type-safe, readable OData filters using familiar Python syntax. Instead of writing error-prone OData strings, you can use Python operators and methods that get automatically translated to proper OData syntax.

python
from easy_acumatica import F

# Import the F factory
from easy_acumatica import F

# Create simple filters
active_filter = F.Status == "Active"
high_value_filter = F.Amount > 1000

# Combine filters with logical operators
combined_filter = (F.Status == "Active") & (F.Amount > 1000)

# Use the filter with QueryOptions
from easy_acumatica import QueryOptions

options = QueryOptions(filter=combined_filter)
results = client.customers.get_list(options)

Common Filter Patterns

Basic Comparisons
Use standard Python operators for comparisons
python
# Equality
filter = F.CustomerID == "ABCDE"

# Inequality
filter = F.Status != "Deleted"

# Greater than / Less than
filter = (F.Amount > 1000) & (F.Amount <= 5000)

# Null checks
filter = F.DeletedDate == None
filter = F.Description != None
Logical Operations
Combine filters with &, |, and ~
python
# AND operation
filter = (F.Status == "Active") & (F.Balance > 0)

# OR operation
filter = (F.Priority == "High") | (F.DueDate < datetime.now())

# NOT operation
filter = ~(F.Status == "Deleted")

# Complex combination
filter = (
    (F.CustomerClass == "WHOLESALE") & 
    ((F.CreditLimit >= 10000) | (F.PrepaymentRequired == False))
)
String Functions
Built-in string manipulation functions
python
# String matching
filter = F.CustomerName.startswith("ABC")
filter = F.Email.endswith("@company.com")
filter = F.Description.contains("urgent")

# String transformation
filter = F.CustomerName.tolower() == "acme corp"
filter = F.Code.toupper().startswith("US")

# String length
filter = F.Description.length() > 100
filter = F.Code.trim().length() == 5
Date Functions
Extract date components for filtering
python
# Date component extraction
filter = F.CreatedDate.year() == 2024
filter = F.DueDate.month() == 12
filter = F.OrderDate.day() <= 15

# Date range filters
filter = (F.Date.year() == 2024) & (F.Date.month() >= 6)

# Time components
filter = F.Timestamp.hour() >= 9
filter = F.Timestamp.minute() == 0
Arithmetic Operations
Perform calculations in filters
python
# Basic arithmetic
filter = (F.Price * F.Quantity) > 1000
filter = (F.Total - F.Discount) >= 500

# Percentage calculations
filter = (F.Discount / F.Total) > 0.1
filter = F.Quantity % 10 == 0

# Complex expressions
filter = ((F.Price * 1.1) + F.Tax) <= F.MaxPrice
List Operations (v4)
Check if value is in a list
python
# In operator (OData v4 only)
filter = F.Status.in_(["Active", "Pending", "Processing"])
filter = F.CustomerClass.in_(["WHOLESALE", "RETAIL"])

# Multiple values
customer_ids = ["CUST001", "CUST002", "CUST003"]
filter = F.CustomerID.in_(customer_ids)

Advanced Features

Best Practices

Do's
Use F factory for all field references
Use parentheses for complex expressions
Use type-safe operators (==, !=, >, etc.)
Use in_() for multiple value checks
Chain string functions for complex logic
Test filters with small datasets first
Use meaningful variable names for filters
Don'ts
Writing raw OData strings
Forgetting parentheses in complex filters
Using Python "and", "or" instead of &, |
Hardcoding field names as strings
Building filters with string concatenation
Ignoring null value handling
Creating overly complex single expressions

Complete Function Reference

All available filter operations and their OData equivalents:

Python SyntaxOData OutputDescriptionVersion
F.Field == valueField eq valueEquality check
v3+
F.Field != valueField ne valueInequality check
v3+
F.Field > valueField gt valueGreater than
v3+
F.Field >= valueField ge valueGreater or equal
v3+
F.Field < valueField lt valueLess than
v3+
F.Field <= valueField le valueLess or equal
v3+
filter1 & filter2filter1 and filter2Logical AND
v3+
filter1 | filter2filter1 or filter2Logical OR
v3+
~filternot filterLogical NOT
v3+
F.Field + valueField add valueAddition
v3+
F.Field - valueField sub valueSubtraction
v3+
F.Field * valueField mul valueMultiplication
v3+
F.Field / valueField div valueDivision
v3+
F.Field % valueField mod valueModulo
v3+
F.Field.startswith("val")startswith(Field, 'val')String starts with
v3+
F.Field.endswith("val")endswith(Field, 'val')String ends with
v3+
F.Field.contains("val")contains(Field, 'val')String contains
v4
F.Field.substringof("val")substringof('val', Field)String contains (v3)
v3
F.Field.length()length(Field)String length
v3+
F.Field.indexof("val")indexof(Field, 'val')Find substring index
v3+
F.Field.substring(start)substring(Field, start)Extract substring
v3+
F.Field.tolower()tolower(Field)Convert to lowercase
v3+
F.Field.toupper()toupper(Field)Convert to uppercase
v3+
F.Field.trim()trim(Field)Remove whitespace
v3+
F.Field.replace("a", "b")replace(Field, 'a', 'b')Replace substring
v4
F.Date.year()year(Date)Extract year
v3+
F.Date.month()month(Date)Extract month
v3+
F.Date.day()day(Date)Extract day
v3+
F.Time.hour()hour(Time)Extract hour
v3+
F.Time.minute()minute(Time)Extract minute
v3+
F.Time.second()second(Time)Extract second
v3+
F.Field.in_([1,2,3])Field in (1,2,3)Value in list
v4
F.cf("Type", "View", "Field")cf.Type(f='View.Field')Custom field
v3+

Additional Functions

FunctionExampleDescriptionVersion
round()F.Price.round()Round to nearest integer
v3+
floor()F.Price.floor()Round down to integer
v3+
ceiling()F.Price.ceiling()Round up to integer
v3+
has()F.Field.has(Enum.Value)Check enum flag
v4
cast()F.Field.cast("Edm.String")Type cast
v4
isof()F.Field.isof("Type")Type check
v4
divby()F.Total.divby(12)Decimal division
v4
matchesPattern()F.Email.matchesPattern(".*@.*")Regex match
v4