FlexFields are custom fields you can add to any transaction in PanatrackerGP. This guide walks through how to configure a FlexField with a dropdown list and optional validation using the Portal.
By default, a FlexField is a free-text field — users can type anything into it. A lookup adds a dropdown list so users can pick from a predefined set of values instead of typing. You can also add validation to check that the entered value is correct before the transaction continues.
Both features are powered by SQL stored procedures that you create in your GP company database:
You can use either one independently, or both together on the same field.
FlexField settings are managed in the PanatrackerGP Portal under Configure → FlexField Configuration. The grid shows every FlexField for every transaction type.
| Column | What It Controls |
|---|---|
| Transaction Name | The transaction type this FlexField belongs to (e.g. Add Adjustment, Fulfill Order, Assemble Unit) |
| Field Type | Which FlexField slot (FlexField1, FlexField2, etc.). Each transaction has multiple slots. |
| Tracking Type | Transaction (appears once per transaction) or Unit (appears per scanned unit) |
| Field Name | The label the user sees on the device screen. Change this to something meaningful (e.g. "Employee Name", "Date", "Pallet No."). |
| Behavior | Disabled — hidden from usersOptional — visible, can be left blankRequired — must be filled before continuing |
| List Mode? | Set to true to show a dropdown button on the field. Requires a List Stored Procedure. |
| List Stored Procedure | Name of the Populate stored procedure that supplies the dropdown list. |
| Validation Stored Procedure | Name of the stored procedure that checks the entered value. |
Optional or Required so the field is visible to users.true and enter the name of your procedure in the List Stored Procedure field.Here is what a configured FlexField row looks like in the Portal. This example sets up FlexField1 on the Add Adjustment transaction as an Item Code lookup with validation:
A Populate procedure is useful when you want users to select from a defined list of values at a specific point in the transaction, rather than typing freehand. This reduces data entry errors, speeds up the workflow, and ensures consistency. For example, you might present a list of valid item numbers, lot numbers, or department codes so the user doesn't have to remember or look up the value themselves.
A Populate procedure is a SQL stored procedure in your GP company database. When the user taps the dropdown button, Panatracker runs this procedure and displays the results as a selectable list.
Your procedure must return a result set with these column names:
| Column | Purpose |
|---|---|
Code |
The value placed into the FlexField when the user selects a row |
Description |
A description shown alongside the code to help the user choose |
PrimaryKey, Item1, Item2, … Item10 instead of Code/Description. PrimaryKey is the selected value; Item1–Item10 are display columns.
This procedure returns lot-tracked items matching what the user has typed so far:
CREATE PROCEDURE [dbo].[PanatrackerGPV7_ItemPopulate]
@FlexField1 NVARCHAR(31)
AS
BEGIN
SELECT DISTINCT
RTRIM(ITEMNMBR) AS Code,
RTRIM(ITEMDESC) AS Description
FROM IV00101
WHERE RTRIM(ITEMNMBR) LIKE @FlexField1 + '%'
AND ITMTRKOP = 3
END
The @FlexField1 parameter receives whatever the user has typed so far, so the list narrows as they type. The LIKE @FlexField1 + '%' pattern enables this type-ahead filtering.
When one FlexField depends on another, add the other field as an input parameter. Panatracker fills it in automatically. Here, FlexField2 (Lot) is filtered by the item already entered in FlexField1:
CREATE PROCEDURE [dbo].[PanatrackerGPV7_LotPopulate]
@FlexField1 NVARCHAR(31), -- Item (from FlexField1)
@FlexField2 NVARCHAR(31) -- Lot typed so far (this field)
AS
BEGIN
SELECT DISTINCT
RTRIM(LOTNUMBR) AS Code,
RTRIM(LOTNUMBR) AS Description
FROM IV00300
WHERE RTRIM(LOTNUMBR) LIKE @FlexField2 + '%'
AND ITEMNMBR = @FlexField1
ENDYou can chain multiple FlexFields. Here, the bin list is filtered by what was entered in FlexField1 and FlexField2:
CREATE PROCEDURE [dbo].[PanatrackerGPV7_BinPopulate]
@FlexField1 NVARCHAR(31), -- Item
@FlexField2 NVARCHAR(31), -- Site
@FlexField3 NVARCHAR(31) -- Bin typed so far
AS
BEGIN
DECLARE @LOCNCODE VARCHAR(20) = 'WAREHOUSE'
SELECT DISTINCT
RTRIM(BIN) AS Code,
RTRIM(BIN) AS Description
FROM IV40701
WHERE RTRIM(BIN) LIKE @FlexField3 + '%'
AND LOCNCODE = @LOCNCODE
ENDRTRIM() on GP columns. Dynamics GP stores character fields padded with trailing spaces, which will appear in your dropdown if not trimmed.
A Validate procedure enforces business rules at the point of entry — before the transaction is submitted. This catches mistakes early, while the user is still at the device and can correct them. For example, you might verify that an item number actually exists in GP, check that a container ID hasn't already been used, or warn the user if a value looks unusual. Without validation, bad data flows into GP and has to be corrected after the fact.
A Validate procedure checks the value after the user enters or selects it. It tells Panatracker whether to accept the value, reject it, show a warning, or substitute a different value.
Every Validate procedure must declare these output parameters:
| Parameter | Type | Purpose |
|---|---|---|
@ValidationResult |
NVARCHAR(50) |
The outcome (see table below) |
@ValidationMessage |
NVARCHAR(200) |
Message shown to the user |
@SubstituteValue |
NVARCHAR(200) |
Replacement value (required for Substitute results) |
Set @ValidationResult to one of these values:
| Result | What Happens |
|---|---|
Valid |
Value accepted. Transaction continues. |
Invalid |
Value rejected. User sees your message and must correct. |
Warning |
User sees a Yes/No prompt with your message. Yes = accept, No = correct. |
SubstituteSilent |
Value is silently replaced with @SubstituteValue. |
SubstituteConfirm |
User sees a Yes/No prompt to accept the substituted value. |
CREATE PROCEDURE [dbo].[PanatrackerGPV7_ItemValidate]
@FlexField1 NVARCHAR(30),
@ValidationResult NVARCHAR(50) OUTPUT,
@ValidationMessage NVARCHAR(200) OUTPUT,
@SubstituteValue NVARCHAR(200) OUTPUT
AS
BEGIN
DECLARE @count INT
SELECT @count = COUNT(DISTINCT ITEMNMBR)
FROM IV00101
WHERE RTRIM(ITEMNMBR) = @FlexField1
AND ITMTRKOP = 3
IF (@count = 0)
BEGIN
SET @ValidationResult = 'Invalid'
SET @ValidationMessage = 'Must enter a valid lot-tracked item'
SET @SubstituteValue = ''
END
ELSE
BEGIN
SET @ValidationResult = 'Valid'
SET @ValidationMessage = ''
SET @SubstituteValue = ''
END
ENDThis procedure lets the user proceed but warns them if the value has been used before. The Warning result shows a Yes/No dialog:
CREATE PROCEDURE [dbo].[PanatrackerGPV7_Container_Validate]
@FlexField1 NVARCHAR(30),
@ValidationResult NVARCHAR(50) OUTPUT,
@ValidationMessage NVARCHAR(200) OUTPUT,
@SubstituteValue NVARCHAR(200) OUTPUT
AS
BEGIN
DECLARE @count INT
-- Check if this container ID has been used in a prior transaction
SELECT @count = COUNT(*)
FROM PanatrackerGP7_TrxGeneric
WHERE FlexField1 = @FlexField1
AND TransactionStatus = 4
IF (@count > 0)
BEGIN
SET @ValidationResult = 'Warning'
SET @ValidationMessage = 'Duplicate Container ID.'
SET @SubstituteValue = ''
END
ELSE
BEGIN
SET @ValidationResult = 'Valid'
SET @ValidationMessage = ''
SET @SubstituteValue = ''
END
ENDA common pattern: use a small custom table to enforce a fixed set of allowed values. For example, restricting a field to "Y" or "N":
CREATE PROCEDURE [dbo].[PanatrackerGPV7_YesNoListValidate]
@FlexField2 NVARCHAR(30),
@ValidationResult NVARCHAR(50) OUTPUT,
@ValidationMessage NVARCHAR(200) OUTPUT,
@SubstituteValue NVARCHAR(200) OUTPUT
AS
BEGIN
DECLARE @count INT
SELECT @count = COUNT(DISTINCT Code)
FROM Panatracker_YesNo
WHERE Code = @FlexField2
IF (@count = 0)
BEGIN
SET @ValidationResult = 'Invalid'
SET @ValidationMessage = 'Must be Y or N'
SET @SubstituteValue = ''
END
ELSE
BEGIN
SET @ValidationResult = 'Valid'
SET @ValidationMessage = ''
SET @SubstituteValue = ''
END
ENDYou don't need to manually pass values to your procedures. Panatracker automatically discovers each procedure's parameters and fills them with current values from the transaction:
@FlexField1 receives the current value of FlexField1@FlexField2 receives the current value of FlexField2This is how cascading lookups work — if your FlexField2 Populate procedure declares @FlexField1 as a parameter, it automatically receives whatever the user entered in FlexField1.
@FlexField1, @flexfield1, and @FLEXFIELD1 all work the same way.
GRANT EXECUTE ON [dbo].[PanatrackerGPV7_ItemPopulate]
TO [DYNGRP]Always test your procedures in SSMS before configuring them in the Portal.
EXEC [dbo].[PanatrackerGPV7_ItemPopulate]
@FlexField1 = 'ITEM' -- simulates user typing "ITEM"You should see a result set with Code and Description columns.
DECLARE
@Result NVARCHAR(50),
@Message NVARCHAR(200),
@Substitute NVARCHAR(200)
EXEC [dbo].[PanatrackerGPV7_ItemValidate]
@FlexField1 = 'TEST-ITEM-001',
@ValidationResult = @Result OUTPUT,
@ValidationMessage = @Message OUTPUT,
@SubstituteValue = @Substitute OUTPUT
SELECT
@Result AS ValidationResult,
@Message AS ValidationMessage,
@Substitute AS SubstituteValuetrue in the Portal.Code and Description (or PrimaryKey/Item1).@ValidationResult and @ValidationMessage are declared with the OUTPUT keyword. Without it, the values never reach Panatracker.Valid, Invalid, Warning, SubstituteSilent, or SubstituteConfirm.If your procedure has a SQL error (wrong column name, missing table, permission denied), the device will show a generic error. The actual SQL error details are in the Panatracker server logs. Check there if things aren't working as expected.
SubstituteSilent or SubstituteConfirm, the @SubstituteValue output parameter is required. Omitting it will cause the substitution to silently fail — the field will appear to validate but the value won't be replaced.
Questions? Contact Panatrack Support.