FilterBuilder
This guide explains how to use the `F` object to build flexible, type-safe OData v3 queries in a Pythonic way. This feature uses operator overloading to replace manual string manipulation, making your query logic cleaner and less error-prone.
Importing the Helper
To get started, import the `F` factory object from the `easy_acumatica.models` module.
from easy_acumatica.models.filter_builder import F
The `F` Object: Your Gateway to Filtering
The `F` object is a factory for creating filter expressions. You can refer to any field in your Acumatica entity by simply accessing it as an attribute on `F`. These `F` objects can then be combined using standard Python operators to build your filter.
F.FieldName
creates an expression for a standard field.F.MainContact.Email
creates an expression for a field on a linked entity, which translates to the OData path `MainContact/Email`.
Building Filters with Operators
You can use familiar Python operators to create your filter logic. The library automatically translates them to the correct OData syntax.
# OData: Status eq 'Active'
filter1 = F.Status == 'Active'
# OData: Amount gt 100
filter2 = F.Amount > 100
Because Python's `and`, `or`, and `not` keywords cannot be overloaded, we use the bitwise operators `&`, `|`, and `~` for logical operations. Always wrap individual clauses in parentheses `()` when combining them to ensure correct precedence.
# OData: (Status eq 'Open') and (Amount gt 1000)
filter1 = (F.Status == 'Open') & (F.Amount > 1000)
# OData: (Country eq 'USA') or (Country eq 'CAN')
filter2 = (F.Country == 'USA') | (F.Country == 'CAN')
# OData: not (startswith(CustomerID, 'TEMP'))
filter3 = ~(F.CustomerID.startswith('TEMP'))
Using OData Functions
For OData functions like `tolower`, `substringof`, or `round`, you can chain methods directly onto your `F` object expressions.
# Find customers whose name contains 'Corp'
f1 = F.CustomerName.contains('Corp')
# Find customers with a .com email address (case-insensitive)
f2 = F.MainContact.Email.tolower().endswith('.com')
# Find invoices due in December
f1 = F.DueDate.month() == 12
# Find items where the rounded freight cost is greater than 10
f2 = F.Freight.round() > 10
Filtering on Custom Fields
You can easily filter on custom fields using the special `F.cf()` helper method.
# Find records where the custom string field UsrRepairType is 'Battery'
cf_filter = F.cf("String", "ItemSettings", "UsrRepairType") == 'Battery'
# Use it in a larger query
full_query = (F.IsActive == True) & cf_filter