> For the complete documentation index, see [llms.txt](https://docs.in8sync.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.in8sync.com/client-admin-guide/getting-started/transaction-components.md).

# Transaction Components

Browse transactions, build orders, and view transaction detail. The largest category — split between Order Form entry blocks and Page-module browse / detail blocks.

Transaction components fall into two distinct contexts:

* **Order Form context** — building or editing an order. Order Lines, Payments, Customer Field, Discount Header, Summary, etc.
* **Page module context** — searching, listing, and inspecting existing transactions. Transaction Search, Transaction List, Transaction Record, etc.

Each block's page calls out which context it belongs to.

{% hint style="info" %}
**How these fit together:** these blocks rarely work alone — see [Common Patterns](/client-admin-guide/getting-started/common-patterns.md) for the recommended arrangement (e.g. a checkout page) and [Cashier Workflow](/client-admin-guide/workflow-builder-overview/workflow-examples/cashier-workflow.md) for a full real-world example.
{% endhint %}

> **Naming overlap:** Two blocks share names with their Order Form counterparts. *Transaction Record — Order Lines View* and *Transaction Record — View Field* both display in the palette as **Order Lines** and **Record Field** respectively — but they are read-only display blocks for Page modules, distinct from the editable Order Form versions.

## Order Lines

The central line-item table for any Order Form. It holds the items the user is ordering, with editable quantities, rates, discounts, and per-line custom columns. Items are added by **Add to Order Button**, **Scan Items**, **CSV Import**, **Saved Orders**, or directly from the Catalog Display.

The block also handles bin auto-assignment, kit components, partial fulfilment quantity caps, and exchange-mode (separate refund/sale lines).

![Order Lines table with several rows showing item, quantity, rate, amount, plus per-line action buttons](https://229581143-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAG04Mxmhw6PLRAZBvhtK%2Fuploads%2Fgit-blob-f39774cb9b76fdf4733483055042adade176116b%2Fpb-order-lines.png?alt=media)

### Available in

* Order Form modules
* Public Page modules

### When to use

* Every Order Form page that creates or edits a transaction. There's typically only one Order Lines block per page.

### Settings

| Setting                                  | Description                                                                                                         |
| ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| **Configure**                            | Opens the configuration modal — columns, pricing, discounts, bin assignment, search behaviour, and behaviour flags. |
| **Product image / content / tabs slots** | Slots for customising how product info renders within line items.                                                   |

The configuration modal supports:

* **View Mode** — table (default) or list view.
* **Price Level** — which NetSuite price level to apply. Empty = use the customer's default price level (or session variable); select *Workflow* to use the workflow's configured default.
* **Price Field** — *priceLevels* (default), *baseprice*, *cost*, *transferprice*, or a NetSuite custom price field.
* **Quantity Adjusts Rate** — when on (default), changing quantity recalculates the line rate using configured pricing effects (volume tiers, etc.). Turn off to keep the rate fixed when quantity changes.
* **Show Kit Components** — expand kit items and item groups to show their components.
* **Display Refresh Button** + **Refresh Button Label** — show a button to manually re-fetch stock levels.
* **Auto-Refresh Stock** — re-fetch stock levels automatically whenever items are added or removed.
* **Display Item Details / Thumbnail** — show extra item info per row.
* **Item Column Field / Char Limit** — which field to show in the item column and how long.
* **Item Column View Only** — make the item column read-only and hide the Add Line button (items can only be added via scan, click, or import).
* **Per-Column View Only** — in the **Columns** tab of the configuration modal, individual columns (including Rate, Quantity, and custom columns) can each be set to read-only independently. When a column is read-only, that specific field cannot be edited on any line, though other columns remain editable.
* **Hide Item Column** — hide the item column entirely (and exclude it from the saved payload).
* **Searchable Fields** + **Search Match Mode** — which item fields the in-line item search checks, and whether matches are *contains* or *starts with*.
* **Custom Columns** — add extra editable columns (text, number, dropdown, etc.) to capture per-line data beyond NetSuite's standard fields.
* **Column Links** — turn a column's value into a clickable link (e.g. open a related record from the item code).
* **Dropdown Sort Fields** — control how items in the in-line dropdown are sorted (by name, code, custom field).
* **Separate Line Items / Exchange Items** — exchange-mode behaviour (separate sale and refund lines).
* **Bin Auto-Assignment Strategy** — for items with bin tracking: *Preferred Bin First*, *Highest Quantity Available*, *Preferred Bin Cascade*, *Highest Quantity Cascade*.
* **Confirm Delete** — confirmation dialog before removing a line.
* **Receive or Fulfill All** — one-click action that fills every line's quantity to its remaining amount. Only appears for receipt and fulfilment transaction types.
* **Sublist ID** — the NetSuite sublist the lines save to. Default fits Sales Order; change for fulfilment, receipt, or transfer order use cases.
* **Tally Pricing** — when on, a **Tally Price** action appears per line. Clicking it opens the Tally Pricing modal where the user can break down a line's price into quantity-tiered or component-based pricing before confirming the rate. Per-line **Enable Printing** — full printing configuration: choose per-line, table, or both modes; pick a template; and set a custom print button label.

The configuration modal also includes these additional settings:

* **Allow Zero Rate** — when off (default), a zero rate triggers recalculation from the pricing hierarchy. Turn on to preserve $0.00 rates as-is.
* **Show Row Numbers** — adds a row counter (1, 2, 3…) as the first column.
* **Show Item Count** — shows the total line count in the block header.
* **Confirm Before Changing an Item** — shows a confirmation prompt before replacing the item on an existing line.
* **Add New Items to Top** — new lines land at the top of the list instead of the bottom.
* **Vendor Purchase Price Selector** — adds a per-line vendor selector; choosing a vendor sets the line rate to that vendor's purchase cost.
* **Enable Unit of Measure** — adds a UOM selector per line; pricing uses the converted quantity for quantity-break calculations.
* **Enable Line Item Discount** — shows an inline discount control below each line; requires a NetSuite discount item to be configured.
* **Gift Certificate Defaults** — pre-fills the gift certificate modal (from name, recipient name, recipient email). Enable *Auto Populate* to skip the modal and apply defaults automatically.
* **PIN Settings tab** — protect specific custom columns behind a PIN or manager override. Column mode unlocks all protected columns at once; row mode unlocks per-row.
* **Rules tab** — per-column conditional rules: min/max validation, default values, and visibility conditions evaluated against catalog item data and session context.

### How it works

1. Items added from any source (catalog click, scan, CSV, manual) land here.
2. Each line resolves its price using the configured price level (with workflow default as fallback).
3. The user can edit quantities, rates, and discounts inline.
4. For bin-tracked items, the configured **Bin Auto-Assignment Strategy** runs to assign stock bins.
5. Group items auto-expand to show their components.
6. On line removal or location change, the block triggers a stock-level refresh.
7. When a gift certificate item is added, the Gift Certificate modal opens to capture the certificate code and validate its balance before the line is confirmed.

In exchange mode, the block separates lines into *sale* and *refund* groups and computes credit accordingly.

{% hint style="info" %}
Bin Auto-Assignment runs only when bin tracking is enabled in NetSuite. The cascade strategies fill multiple bins in priority order; if total available stock is still short, a warning toast appears and the remainder lands on the last bin (NetSuite validates at submit).
{% endhint %}

### Examples

**Standard cashier register.** Order Lines with default settings, paired with Customer/Vendor Selection, Scan Items, and Payments. Cashier scans items in, adjusts quantity if needed, takes payment.

**B2B bulk entry.** Order Lines with View Mode = list view, Show Kit Components = off. Buyers enter dozens of items quickly via CSV Import.

**Exchange-flow POS.** Order Lines with Exchange Items enabled. Returns and new purchases sit in the same transaction with separate line groups.

### Related

* [Scan Items](#scan-items) — Add items via barcode scan.
* [Payments](#payments) — Take payment for the order — reads the Order Lines total.
* [Summary](#summary) — Subtotal, tax, shipping, discount, total.

## Payments

The block that collects payment for an order. It loads available payment methods from the subsidiary settings, shows tender buttons, integrates with the Registers block for terminal-level orchestration, and supports refund and adjustment flows.

When Payments is on the page, **Submit Button** hides itself automatically — Payments drives the submission once payment is collected.

![Payments block showing tender buttons (Cash / Card / Gift Card), an amount field, and a confirm button at the bottom](https://229581143-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAG04Mxmhw6PLRAZBvhtK%2Fuploads%2Fgit-blob-3bf2de6f71d229de9f909486f1f2b9f888743210%2Fpb-payments.png?alt=media)

### Available in

* Order Form and Return Form modules
* Transaction record view pages (when using Pay Existing Transaction mode)

### When to use

* Every POS workflow that takes payment at time-of-sale.
* Cashier registers, retail POS pages, walk-in service order pages.
* Anywhere the order should be tendered before submission rather than invoiced for later payment.

For order forms where the order is invoiced rather than paid in full at submit, skip Payments and use Submit Button alone.

### Settings

| Setting                   | Description                                                                                                                                          |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Payment Configuration** | Opens the configuration modal — payment method selection, processor mapping, and additional options. All Payments configuration lives in this modal. |

The configuration modal covers:

* **Payment methods** — available tenders (Cash, Card, Gift Card, Credit Memo, Check, and others) come from your subsidiary's Payment Settings. The block reads them from the subsidiary and can selectively hide specific methods on this block using per-method on/off toggles, independent of subsidiary configuration.
* **Card Present processors** — Fortis, 8Q, and Datacap. Processor credentials and NetSuite payment method mapping are managed at the subsidiary level in Payment Settings.
* **Card Not Present processors** — Accept Blue and PayStand. Saved card (Payment Instruments) settings are also managed at the subsidiary level.
* **Payment Mode** — how the block handles payment: *Order summary* (default, cart-backed), *Standalone payment* (collects a payment against a customer without an active order; see [#standalone-payment-mode](#standalone-payment-mode) for full details), or *Pay existing transaction* (applies tenders to a loaded invoice or sales order).
* **Amount-first checkout** — when on (the default for new blocks), the Pay button opens a single amount-entry modal where the cashier enters a value, picks a method, and repeats until the balance reaches zero. Overrides the inline tender-button grid.
* **Gift Certificate** — enable a gift certificate button, set a custom button label, and choose whether customer selection is required before redemption.
* **Terms** — lets cashiers place an order on payment terms, capturing the due date and early-pay discount.
* **Receipt and invoice templates** — assign a custom template, enable auto-print on completion, or allow download and email.
* **Email Settings** — shows a *Send Invoice by Email* checkbox on the order completion screen.
* **Stock validation** — optionally blocks payment if line item quantities exceed available stock.
* **Click-to-pay** — when on, selecting a tender jumps straight to the payment flow, skipping the amount entry step.
* **Print before payment** — optionally prints a receipt or invoice preview before the cashier collects payment.
* **Visible order types** — limit the block to specific order types; it hides for all others.
* **Allow zero-dollar orders** — lets a $0 order submit without requiring payment.
* **Allow partial payment** — lets an order complete before the full balance is collected.
* **Keyboard shortcut** — assign a hotkey (e.g. Ctrl+P) to open the payment modal. A **Hotkey Target** option directs the key to a specific tender method (e.g. straight to the Cash button) instead of the general Pay button.
* **Transaction Polling** — after order submission, polls for the created NetSuite transaction and surfaces a *View Transaction* button once the record is found. The link destination is configurable.
* **Redirect After Submission** — configures where *Finish & New Order* navigates: a custom workflow page or a custom URL.

### How it works

1. Loads payment methods from the subsidiary's Card Present + Card Not Present processor configuration.
2. Reads the order total from the Summary block.
3. Renders tender buttons for the available methods.
4. For card payments, communicates with the configured terminal or processor (often via the Registers block, which manages the active terminal).
5. For cash, shows a change calculator.
6. For gift card and credit memo, validates the available balance.
7. When the collected total meets the order amount, shows an order completion screen. Payment submits after the cashier confirms.
8. If **Email Settings** is enabled and the cashier opts in, emails a PDF invoice to the configured recipient.

PIN entry is supported when the processor requires it. Refunds and adjustments use the same payment flow.

{% hint style="info" %}
**Standalone payment mode** — when configured as standalone, the block takes a payment against a customer's account without an active order. It requires customer selection and records the payment immediately on confirmation. Use this for taking ad-hoc payments outside of an open cart. See [#standalone-payment-mode](#standalone-payment-mode) for a complete guide on setup and usage.
{% endhint %}

{% hint style="warning" %}
Payment methods come from the subsidiary's Payment Settings, configured by your NetSuite Admin. If a method you expect isn't showing, check the subsidiary's Payment Settings (or the legacy Card Present / Card Not Present screens) first.
{% endhint %}

### Examples

**Standard POS register.** Customer/Vendor Selection at top, Order Lines, Summary, Payments at bottom. Cashier scans items, taps Cash or Card, takes payment, confirms on the order completion screen, transaction submits.

**Card-only terminal.** Subsidiary configured with only card processors. Payments shows the Card tender and integrates with the in-store payment terminal.

**Multi-tender split.** Customer pays partly cash, partly card. Payments handles the split flow, accumulates the collected total, and submits when the full balance is met.

### Related

* [#standalone-payment-mode](#standalone-payment-mode) — Collect payments outside an active order against a customer's account.
* [Submit Button](/client-admin-guide/getting-started/action-components.md#submit-button) — Hides automatically when Payments is present.
* [#registers](#registers) — Manages the active register and cash drawer that Payments works with.
* [#summary](#summary) — The block that calculates the total Payments collects against.

## Payment PIN Authorization

An optional security gate on the Payments block's **Pay** button. When enabled, every click of the Pay button prompts the employee for a PIN before the payment screen opens. The employee whose PIN is accepted is recorded as the order's **Authorized User**, and each authorization is logged for audit.

This gate applies only to the Pay button — not click-to-pay tiles, processor buttons, the payment hotkey, or Complete Order. The PIN prompt appears on every Pay click; it does not remember previous entries.

### When to use it

* High-security POS workflows where payment authorization must be traced to a specific employee.
* Reducing accidental or unauthorized payment initiations.
* Compliance scenarios where a manager or senior cashier must approve payment.

### How to configure

1. On the **Payments block**, click **Configure**.
2. Look for the **PIN Authorization** section (an enable toggle).
3. Enable **Require PIN Before Payment**.
4. Choose your validation mode:
   * **Dynamic** — The PIN is checked against the employee's own PIN stored in NetSuite. The admin chooses which employee-record field holds it.
   * **Static** — The admin picks a list of Authorized Employees and gives each their own PIN, stored securely.
5. Set the **PIN Modal Title** (default: *Authorize Payment*).
6. Save your configuration.

### What happens at runtime

1. When a cashier or user clicks to take payment, a PIN entry modal appears.
2. They enter their PIN (or the static PIN if configured).
3. The system validates it immediately.
4. On successful validation, the payment screen opens.
5. The employee's ID (or "static" if static mode) is recorded with the payment transaction for audit purposes.
6. Cancelling the prompt abandons the payment; a wrong PIN can be retried.

**Note:** There is no enforced PIN length, no retry limit, and no timed lockout. If Static mode is enabled with no employees configured, the gate turns itself off.

This feature is separate from the existing cashier PIN override (see [PIN Override](/client-admin-guide/workflow-builder-overview/pin-override.md)).

## Summary

The order summary block. Calculates and shows subtotal, tax, shipping, discount, and grand total. Two calculation modes: **local** (you specify a fixed tax rate and optional flat shipping) or **remote** (NetSuite calculates tax and shipping via SuiteScript).

In remote mode, the active **tax engine** is detected from your subsidiary settings — *legacy* (NetSuite's built-in), *Avalara*, or *Vertex*. Avalara and Vertex run as third-party tax services for advanced multi-jurisdiction calculation. Two manual action buttons are available when the engine supports them: **Calculate Tax** (re-fetches tax from Avalara or Vertex) and **Calculate Shipping** (re-runs the shipping calculation separately). Both require remote mode.

### Available in

* Order Form modules
* Public Page modules

### When to use

* Always include Summary on Order Form pages — it's the running tally users (and Payments) read for the order total.
* Cashier, B2B order entry, B2C checkout, drop-ship, quote — every order context needs Summary.

For non-financial transactions (Purchase Orders, Transfer Orders, Fulfilment Requests), Summary auto-hides the financial breakdown.

### Settings

| Setting       | Description                                                                                              |
| ------------- | -------------------------------------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — calculation mode, tax rate, currency, title, record type, flat shipping. |

The configuration modal supports:

* **Use Local Calculation** — Yes (use Local Tax Rate and Flat Shipping) or No (let NetSuite/Avalara/Vertex calculate via the order summary service). Default: No.
* **Local Tax Rate** — fixed tax percentage (only when Local Calculation = Yes). Default: 0.08 (8%).
* **Currency** — display currency code. Default: USD.
* **Title** — heading shown above the summary. Default: *Order Summary*.
* **Record Type** — which transaction record type the summary represents (salesorder, cashsale, etc.). Default: salesorder.
* **Hotkey** — optional keyboard shortcut to scroll to and focus the order total (e.g. *ctrl+t*).

The active tax engine (legacy / Avalara / Vertex) and Avalara sandbox setting are read from the subsidiary configuration at runtime — they aren't picked here.

### How it works

1. Reads the line items, customer, and address from session state.
2. **Local mode** — applies the configured Local Tax Rate to the subtotal.
3. **Remote mode** — calls the OrderSummaryService for tax and shipping. The actual tax engine depends on the subsidiary's configured engine: legacy (NetSuite built-in), Avalara, or Vertex.
4. **Avalara / Vertex** — if either is enabled in the subsidiary, Summary detects it at mount and uses it for tax. Avalara calculates tax per line item for accurate multi-jurisdiction results. Vertex also re-runs tax automatically when the Payments block collects payment, so the final tax reflects any last-minute changes. For Avalara, the *Avalara Sandbox* subsidiary setting routes calls to the sandbox endpoint when on.
5. When **Use Location Address** is configured on the Address block, Summary uses the location's address for tax jurisdiction calculations on the relevant order types.
6. Recalculation is debounced — changes to line items, customer, or address trigger a fresh calc after a short delay.
7. A **Handling Cost** row appears automatically when the handling amount is greater than zero.
8. For PurchaseOrder, TransferOrder, and FulfillmentRequest record types, the financial breakdown auto-hides (these don't have a customer-facing total).
9. If a Hotkey is configured, pressing it from anywhere on the page scrolls to the total and brings it into focus.

{% hint style="info" %}
Use **Local mode** for simpler workflows where tax is a single fixed rate and shipping is flat. Use **Remote** for anything where NetSuite should calculate (multi-jurisdiction tax, calculated shipping, custom rules). Avalara support is automatic when the subsidiary has it enabled.
{% endhint %}

### Examples

**Standard cashier flow.** Summary with Use Local Calculation = No, Title = *Order Summary*. NetSuite handles tax and shipping; Summary reflects whatever the order resolves to.

**Quick local-tax setup.** Use Local Calculation = Yes, Local Tax Rate = 8.25, Local Flat Shipping = 5. For a single-location workflow with simple tax, no NetSuite tax engine round-trip needed.

**Avalara-enabled retail.** Subsidiary with Avalara configured. Summary auto-detects, uses Avalara for tax, and offers a Recalculate button if the user wants a fresh tax pull (e.g. after changing the shipping address).

### Related

* [#order-lines](#order-lines) — The line items Summary reads from.
* [#payments](#payments) — Reads the Summary total to know what to collect.
* [#discount-header](#discount-header) — Order-wide discounts that flow into the Summary.

## Customer Field

Renders one field from the currently selected customer in the Order Form context. The block auto-detects the field's type (text, select, date, boolean, number, email, etc.) and provides the right input control with required/disabled flags.

### Available in

* Order Form modules **only**

### When to use

* Order Form pages where you want to surface specific customer attributes in context (phone, email, credit limit, balance, custom fields).
* When you need to let the cashier or sales rep edit a customer field inline (notes, custom flags) during order entry.
* For richer multi-section customer detail, use **Entity 360 View** instead.

### Settings

| Setting       | Description                                                                           |
| ------------- | ------------------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — field selection, label, width, type-specific options. |

The configuration modal supports:

* **Field Name** — which customer field. Options come from the customer record's available fields (5-min cache).
* **Field Label** — display label. Defaults to the field name.
* **Width** — input width in pixels. Default: 200.
* **Field Type** — auto-populated from the field's actual type (text, boolean, select, date, longtext, readonly, email, number).
* **Field Options** — for select fields, the available options (auto-populated).
* **Required** — make the field required to submit. Default: No.
* **Disabled** — render read-only. Default: No.
* **Default Value** — pre-fill value if the customer field is empty.

### How it works

1. Reads the selected customer from session state (set by Customer/Vendor Selection).
2. Auto-resolves the field's type and options from the NetSuite customer field definition (cached for 5 minutes).
3. Renders the appropriate input control (text input, select, checkbox, date picker, etc.).
4. Date fields convert between MM/DD/YYYY (display) and YYYY-MM-DD (HTML5 input).
5. Edits write back to the customer record via the order submission flow.

{% hint style="info" %}
**Field Type and Field Options** auto-populate when you pick a Field Name — you don't need to set them manually. They re-resolve when the field changes.
{% endhint %}

### Examples

**Display customer phone on order form.** Customer Field with Field Name = `phone`, Field Label = *Phone*, Disabled = Yes (read-only).

**Editable customer notes.** Customer Field with Field Name = `comments`, Field Label = *Notes*, Required = No. Cashier can update notes during the order.

**Credit limit visibility.** Customer Field with Field Name = `creditlimit`, Field Label = *Credit Limit*, Disabled = Yes. Helps the cashier see the customer's credit at a glance.

### Related

* [#record-field](#record-field) — The general-purpose field block for transaction-level fields.
* [Entity Components](/client-admin-guide/getting-started/entity-components.md) — Customer/Vendor Selection selects the customer this block reads from.
* [Entity Components](/client-admin-guide/getting-started/entity-components.md) — Entity 360 View for richer multi-section customer detail.

## Record Field

Renders one field from the current transaction record. Auto-detects the field type and provides the right input control. Includes built-in handling for two special fields: `order_type` (a fixed 6-option dropdown) and `order_id` (read-only, shows the BRM order ID after submit).

The block also supports a **dynamic default value** — an expression that resolves at render time based on context (user, location, etc.).

### Available in

* Order Form modules
* Public Page modules

### When to use

* Order Form pages where the user needs to set or see specific transaction header fields — order type, memo, custom fields, departments, classes.
* Anywhere you need a single transaction-record field on the page rather than the whole record.

For customer-record fields, use **Customer Field** instead.

### Settings

| Setting       | Description                                                                   |
| ------------- | ----------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — field selection, label, width, type, default. |

The configuration modal supports:

* **Field Name** — which transaction field. Includes hardcoded `order_type` and `order_id` plus all standard / custom fields from the record type.
* **Field Label** — display label.
* **Width** — input width in pixels. Default: 200.
* **Field ID** — internal field identifier (auto-resolved).
* **Field Type** — auto-populated: text, boolean, select, date, longtext, readonly, number, email, url.
* **Field Options** — for select fields (auto-populated).
* **Required** — make the field required to submit. Default: No.
* **Disabled** — render read-only. Default: No.
* **Hidden** — hide the block from rendering. Default: No.
* **Record Type** — which record this field belongs to (`salesorder`, `cashsale`, etc.). Default: salesorder.
* **Default Value** — static pre-fill value.
* **Is Dynamic Default** — when enabled, **Dynamic Default Value** is an expression evaluated at render time.

### How it works

1. Reads the field type and options for the configured Field Name (5-min cache by record type).
2. Renders the right input control.
3. For `order_type`, surfaces the fixed list of 6 order types.
4. For `order_id`, renders read-only and shows the BRM order ID (or hides if no order ID exists yet).
5. For dates, converts between MM/DD/YYYY display and YYYY-MM-DD HTML5 input.
6. Stores the value in `recordFields` on the order state via `setRecordField`.

{% hint style="info" %}
Use **Hidden = Yes** when you want to populate a field via Dynamic Default but not let the user see it (e.g. capture the location into a hidden header field).
{% endhint %}

### Examples

**Order type picker.** Record Field with Field Name = `order_type`. Drives the rest of the form's behaviour (e.g. Address visibility based on order type).

**Memo field.** Record Field with Field Name = `memo`, Field Label = *Memo*, Required = No.

**Hidden default location.** Record Field with Field Name = `location`, Hidden = Yes, Is Dynamic Default = Yes, Dynamic Default Value = a session-variable expression resolving to the user's home location.

**Order-source custom field.** For businesses that track *where an order came from* separately from *which location fulfills it* (for example, a showroom with no inventory that sends every order to a central warehouse), add a Record Field pointing at a custom "Store" or "Source" field on the transaction, independent of the Location field. This keeps reporting on order origin separate from fulfillment logistics.

### Related

* [#customer-field](#customer-field) — For customer-record fields rather than transaction fields.
* [#location](#location) — The dedicated location-picker block.
* [Workflow Variables](/client-admin-guide/workflow-builder-overview/module-variables.md) — Source values for Dynamic Default expressions.

## Discount Header

Applies an order-level discount (as opposed to per-line discounts in Order Lines). Supports both percentage and dollar amount with bidirectional toggle, validation against the subtotal, and an optional PIN-override flow for read-only contexts where only managers can apply discounts.

### Available in

* Order Form modules **only**

### When to use

* Order Form pages where the cashier or sales rep applies an order-wide promotional, employee, or loyalty discount.
* POS workflows that need PIN-gated discount authorisation.
* Anywhere you want a single visible discount control on the order header.

For per-line discounts, use the per-line Discounts setting on **Order Lines** instead.

### Settings

| Setting       | Description                                                                                                             |
| ------------- | ----------------------------------------------------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — title, percentage/dollar toggles, default amount, override behaviour, authorised users. |

The configuration modal supports:

* **Title** — heading text. Default: *Discount*.
* **Enable Percentage** — allow percentage-based discounts. Default: Yes.
* **Enable Dollar** — allow flat-dollar discounts. Default: Yes.
* **Discount Item ID** — the NetSuite discount item used to apply the discount.
* **Read Only** — render as read-only, with override button to unlock. Default: No.
* **Default Amount** — pre-fill value. Auto-detects format: `10%` (percentage) or `10` (dollar).
* **Enable Override** — when read-only mode is on, show an override button.
* **Override Button Text** — custom text. Default: *Request Manager Override*.
* **Authorized Users** — list of users authorised to enter the override PIN.

### PIN override — two parts to configure

PIN-gated discounts require setup in two places. The Client Admin sets up the component; a NetSuite Admin sets up the actual PIN values on user records.

| Part                                                        | Where                                                                         | Who                |
| ----------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------ |
| Turn on *Read Only* and *Enable Override* on this component | Page Builder → Discount Header → Configure                                    | **Client Admin**   |
| Add users to *Authorized Users* list on this component      | Same — Configure modal                                                        | **Client Admin**   |
| Set each manager's PIN value on their NetSuite record       | NetSuite user record → *PIN Code* field (`custentity_brm_pincode` by default) | **NetSuite Admin** |

If the override button appears but PIN entry always fails, the most likely cause is that the manager's PIN hasn't been set on their NetSuite record. See [PIN Override](/client-admin-guide/workflow-builder-overview/pin-override.md).

### How it works

1. Renders the discount input(s) for percentage and/or dollar — the user picks one.
2. Bidirectional toggle: switching from % to $ recalculates the equivalent and vice versa.
3. Validation prevents discounts that exceed the subtotal.
4. In **read-only mode**, the input is locked. A click on the override button opens a PIN pad.
5. PIN is validated against the configured Authorized Users list — each authorized user's PIN is stored on their NetSuite employee record.
6. Successful PIN entry unlocks the discount input for that session.
7. Input is debounced (300ms) to avoid excessive recalcs as the user types.
8. Discount flows into **Summary's** discount line — the order total updates in real time.

{% hint style="info" %}
Use **Default Amount** to pre-fill a common discount (e.g. `5%` for an employee rate). The user can change it inline if allowed, or override via PIN if locked.
{% endhint %}

### Examples

**Cashier with employee discount.** Discount Header with Default Amount = `10%`, Read Only = No. Cashier applies the standard employee rate.

**Promotional dollar-off.** Discount Header with Enable Percentage = No, Enable Dollar = Yes, Default Amount = `25`. Limits the input to dollar values only.

**PIN-gated manager discount.** Discount Header with Read Only = Yes, Enable Override = Yes, Authorized Users = \[list of managers]. Cashier sees the field but needs a manager PIN to enter a value.

### Related

* [#summary](#summary) — Where the applied discount appears in the totals.
* [Entity Components](/client-admin-guide/getting-started/entity-components.md) — PIN Pad: The PIN entry block used in override flows.
* [PIN Override](/client-admin-guide/workflow-builder-overview/pin-override.md) — The full PIN-protection model.

## Discount Item

A dropdown that lets the user apply one of a pre-approved list of NetSuite discount items to the current order. The block reads the available rate from the selected item and applies it to the order's discount total — visible immediately in **Summary**.

Unlike a free-form discount entry, Discount Item locks the user to discounts you (the Client Admin) have explicitly allowed — useful for keeping cashiers on policy while still letting them apply approved discounts.

### Available in

* Order Form modules

### When to use

* POS register pages where cashiers can apply manager-approved discounts (e.g. *10% Loyalty*, *Employee Discount*, *Damaged Goods*).
* B2B order pages where reps can apply pre-negotiated promotional discounts from a fixed list.
* Anywhere you want discount application to be controlled — only specific NetSuite discount items can be picked.

For free-form discount headers (any rate, any percentage), use **Discount Header** instead. For percentage promotions tied to product rules, use **Promotions**.

### Settings

The block opens a configuration modal:

| Setting                    | Description                                                                                                                                                                               |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Title**                  | Label shown above the dropdown. Default: *Discount*.                                                                                                                                      |
| **Allowed Discount Items** | The list of NetSuite discount items the user can select from. Multi-select. Required.                                                                                                     |
| **Is Fee**                 | If on, the selected item is treated as a fee (positive amount) rather than a discount (negative). Useful for surcharge items configured in NetSuite as the same record type as discounts. |

### How it works

1. On mount, the block loads every NetSuite discount item via the Discount Service.
2. Filters to only those in **Allowed Discount Items**.
3. Renders a dropdown showing each allowed item with its label and rate.
4. When the user selects an item, the block reads the item's rate and description from NetSuite (e.g. *-10%*, *-$5*) and pushes both into the order's discount state — the description appears on the discount line in the transaction.
5. **Summary** picks up the change immediately and recalculates the order total.
6. Selecting *None* clears any applied discount.

### Examples

**Manager-approved POS discounts.** Allowed Discount Items: *10% Loyalty*, *Employee Discount*, *Damaged Goods (15% off)*. Cashiers can pick any of these mid-sale; PIN gate the page or pair with **PIN Pad** to require manager approval.

**B2B promotional discounts.** Allowed: *Volume Discount Tier 1*, *Volume Discount Tier 2*, *New Customer Welcome*. Reps apply the right one based on the customer.

### Common issues

* **Dropdown is empty** — no items in *Allowed Discount Items* yet, or none of them exist in NetSuite. Open the configuration modal and pick at least one.
* **Selected discount doesn't appear in Summary** — confirm Summary is also on the page. Discount Item only writes to order state; Summary is what reads it.

### Related

* [#discount-header](#discount-header) — Free-form discount header — any rate, no allowlist.
* [#promotions](#promotions) — Auto-apply promotional discounts based on NetSuite promotion rules.
* [#summary](#summary) — Where the discount appears in the running order total.

## Promotions

Connects the order to NetSuite's native promotion engine. When this block is present, configured promotion rules can apply automatically as line items are added (or be manually evaluated, depending on the toggle).

The block has minimal UI — in the Page Builder canvas it shows a small status indicator. At runtime it operates in the background, applying any matching promotions to the order without the user having to think about discount codes or manual entry.

### Available in

* Order Form modules

### When to use

* POS or B2C order pages where qualifying NetSuite promotions should apply automatically (buy-X-get-Y, percentage off, customer-tier discounts).
* Any order page that's expected to honour active promotional campaigns set up in NetSuite.
* B2B order pages where promotional pricing is rule-driven rather than manually applied.

For a discount the user picks from a fixed list, use **Discount Item**. For a free-form discount header, use **Discount Header**.

### Settings

The block opens a configuration modal:

| Setting                                | Description                                                                                                                                                                                                                 |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Automatically Apply Promotions**     | When on, qualifying promotions apply each time a payment method is selected. When off, promotions are evaluated only on a manual trigger. Default: off.                                                                     |
| **Button to Calculate Promotions**     | When on, a **Calculate Promotions** button appears on the page. Clicking it evaluates all qualifying promotions at once — a visible one-click trigger when *Automatically Apply* is off. Default: off.                      |
| **Require Calculation Before Payment** | When on, the order cannot proceed to payment until promotions have been calculated. Useful in workflows where promotion qualification must be explicitly confirmed before payment. Default: off.                            |
| **Coupon Code Entry**                  | When on, a coupon-code input field appears on the order, allowing customers or cashiers to manually enter a promotional or loyalty code. The code is validated and applied if it matches an active promotion. Default: off. |

### How it works

1. The block writes its *Auto Apply* setting into the order state on mount.
2. When the user adds, removes, or modifies line items, the order state is evaluated against NetSuite's active promotion rules.
3. If *Auto Apply* is on and a promotion qualifies, it's applied to the order automatically — visible in **Summary** as a discount line.
4. If *Auto Apply* is off, the order state still tracks qualifying promotions but doesn't apply them; you'd add an Action Button or similar to trigger application manually.
5. The block doesn't render visible UI at runtime (only in the editor as a status indicator).

### Examples

**Automatic POS promotions.** Drop Promotions onto the cashier's Order Form with *Automatically Apply Promotions* on. Active NetSuite promotions apply as the cashier rings items — no extra steps.

**Manual review of promotions.** Set *Automatically Apply Promotions* off and pair with an Action Button labelled *Apply Promotions*. The user clicks once after building the order to see all qualifying promotions applied at the same time.

### Common issues

* **No promotions appear** — verify NetSuite has active promotions configured and the customer qualifies. Promotions block only applies what NetSuite says is valid.
* **Automatic promotions disappear** — modifying line items can change which promotions qualify; the block re-evaluates on every change. Check whether the order still meets the promotion's conditions.

### Related

* [#discount-item](#discount-item) — Apply a manually-selected discount from an admin-curated list.
* [#discount-header](#discount-header) — Free-form discount on the order header.
* [#summary](#summary) — Where applied promotions show up in the running total.

## Shipping Method

A dropdown for selecting the shipping method on an order. Filters automatically by order type (so Pickup orders don't see Delivery shipping methods). Optionally lets a user override the shipping or handling cost.

### Available in

* Order Form modules **only**

### When to use

* Order Form pages where physical goods ship (delivery, drop-ship, special-order).
* Anywhere the user needs to pick how the order will be fulfilled.

For pickup-only or in-store transactions where shipping doesn't apply, configure the block's order-type filter to hide it.

### Settings

| Setting       | Description                                                                                           |
| ------------- | ----------------------------------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — title, allowed shipping items, order-type visibility, cost overrides. |

The configuration modal supports:

* **Title** — heading text. Default: *Shipping Method*.
* **Allowed Shipping Items** — restrict the dropdown to specific NetSuite shipping items. Empty = show all.
* **Visible Order Types** — only show the block when the order type matches one of the listed types. Empty = always show.
* **Override Shipping Cost** — let the user override the calculated shipping cost.
* **Shipping Cost Override** — the override value when enabled.
* **Override Handling Cost** — let the user override handling cost.
* **Handling Cost Override** — the override value when enabled.

### How it works

1. Loads available shipping items from the ShippingService at mount.
2. Filters the dropdown by **Allowed Shipping Items** if configured.
3. Checks the current order type against **Visible Order Types** — hides the block if no match.
4. User picks a shipping method; the cost is calculated and added to the order total.
5. If override is enabled, the user can manually adjust shipping or handling cost.
6. Cost flows into Summary.

{% hint style="info" %}
Use **Visible Order Types** to keep Shipping Method out of pickup or in-store flows. Pair with the Address block's order-type filter for a coherent configurable form.
{% endhint %}

### Examples

**Standard delivery flow.** Shipping Method with Visible Order Types = `[Delivery, Drop Ship]`. Hides for Pickup, Cash & Carry, and Quote.

**Drop-ship with cost override.** Shipping Method with Override Shipping Cost = Yes. Sales rep can adjust the cost when negotiating with the customer.

**Restricted shipping items.** Allowed Shipping Items = `[FedEx Ground, FedEx Express]` only. Locks the workflow to specific carriers.

### Related

* [Entity Components](/client-admin-guide/getting-started/entity-components.md) — Address: The shipping address that pairs with the shipping method.
* [#summary](#summary) — Where shipping cost flows into the totals.

## Location

A location picker for the order header. Shows locations available to the user's subsidiary, with smart defaults driven by order type — e.g. Pickup auto-selects the user's location, Delivery picks from session variable hierarchy.

The block tracks whether the user manually edited the selection so auto-defaults don't fight the user.

### Available in

* Order Form modules **only**

### When to use

* Multi-location operations where the order needs to be associated with a specific business location.
* Order Form pages for retail with multiple stores, or wholesale with multiple warehouses.
* Anywhere the order's location matters for stock, accounting, or fulfilment.

For single-location workflows, set the location once on the workflow and skip this block.

### Settings

| Setting       | Description                                                                                        |
| ------------- | -------------------------------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — label, width, available locations, order-type-to-location mapping. |

The configuration modal supports:

* **Field Label** — display label.
* **Width** — input width in pixels. Default: 200.
* **Available Locations** — restrict the dropdown to specific locations. Empty = all locations available to the subsidiary.
* **Order Type Mapping** — per-order-type rules for auto-selecting a location:
  * *Pickup* → user's location.
  * *Delivery* → session variable priority: user > workflow > location > subsidiary.
  * Other types → custom mapping.

### How it works

1. Reads the active subsidiary from session storage.
2. Fetches the location list filtered by subsidiary.
3. Resolves the current location with this priority:
   * User edits (if the user changed the selection manually).
   * `transactionFields` (if loaded for an existing transaction).
   * Dynamic data (if pre-set elsewhere on the page).
   * Order-type mapping (auto-default).
   * Fallback to the first available location.
4. Auto-clears the selection if the order type changes and the new mapping is empty.
5. Tracks a `userEdited` flag — once the user manually picks, auto-defaults stop running.
6. Writes the selected value to `recordFields.location` via `setRecordField`.

{% hint style="info" %}
Use **Order Type Mapping** to make the workflow smart: a Pickup order auto-defaults to the cashier's home location; a Delivery order picks from a configured session variable. Less typing, fewer errors.
{% endhint %}

{% hint style="info" %}
When a workflow uses **live inventory sync**, changing the location here instantly updates the stock quantities displayed by the Product Locations block — no page reload needed.
{% endhint %}

### Examples

**Multi-store retail.** Location with Available Locations = all subsidiary locations, Order Type Mapping configured so each order type defaults sensibly.

**Restricted warehouse.** Location with Available Locations = `[Warehouse A, Warehouse B]`. Cashiers can only fulfil from those two warehouses.

**Pickup-defaulting POS.** Location with Order Type Mapping for Pickup = user's location. Cashier creates a pickup order and the location auto-fills.

### Related

* [#record-field](#record-field) — The general-purpose field block — Location is a dedicated picker for this specific field.
* [Workflow Variables](/client-admin-guide/workflow-builder-overview/module-variables.md) — Source values for Order Type Mapping defaults.

## Signature Pad

A canvas where the user can draw a signature with finger, mouse, or stylus — or capture from an external signature device (PIN pad, dedicated signature pad, DeviceBridge). The captured signature uploads automatically as an attachment to the transaction.

![Signature Pad canvas with a drawn signature, a Clear button, and a Save button below](https://229581143-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAG04Mxmhw6PLRAZBvhtK%2Fuploads%2Fgit-blob-af4462a089c8906f31159221130fc3ee5a618955%2Fpb-signature-pad.png?alt=media)

### Available in

* Order Form modules **only**

### When to use

* Order confirmation flows where the customer signs to acknowledge receipt or terms.
* Delivery acknowledgement screens.
* Service-order workflows that require a signed authorisation.
* Any process that needs proof-of-acceptance.

### Settings

| Setting             | Description                                                                                                                                                                                                                                                     |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Title**           | Heading text shown above the pad. Default: *Signature*.                                                                                                                                                                                                         |
| **Instruction**     | Helper text shown below the title. Default: *Please sign below*.                                                                                                                                                                                                |
| **Capture Methods** | both (touch + device), touch (canvas only), or device (external pad only). Default: both.                                                                                                                                                                       |
| **Auto Upload**     | Yes — auto-upload on device capture. No — require manual save. Default: Yes.                                                                                                                                                                                    |
| **Show Preview**    | Show a preview of the captured signature. Default: Yes.                                                                                                                                                                                                         |
| **Target Fields**   | One or more transaction fields the captured signature is written to (in addition to attaching as a file). Configure this when a downstream workflow or SuiteScript reads the signature from a specific transaction field rather than from the attachments list. |

### How it works

1. Renders a high-DPI canvas for touch/mouse input.
2. If capture method = device or both, also offers an external-device capture path via PIN pad / external signature pad / DeviceBridge APIs.
3. **Auto Upload** on device capture sends the signature directly without an extra confirm step. Touch capture requires a manual Save click.
4. Saves as a PNG attachment named `{brmOrderId}_signature_{timestamp}.png`.
5. Attaches to the transaction via `setAttachmentsData` so it submits with the order.
6. Clears automatically on `formResetAfterSubmission`.

{% hint style="info" %}
For card-present POS terminals with built-in signature capture, configure Capture Methods = device and Auto Upload = Yes — the cashier doesn't need to touch the screen at all.
{% endhint %}

### Examples

**Customer signature on POS receipt.** Signature Pad with Capture Methods = both, Auto Upload = Yes. Customer signs on the cashier's tablet or the EMV terminal; signature attaches to the order.

**Delivery confirmation.** Signature Pad with Title = *Sign for Delivery*, Capture Methods = touch, Auto Upload = No. Driver hands tablet to recipient who signs and confirms.

**Service authorisation.** Signature Pad on a quote-acceptance flow. Captures customer agreement before submitting the work order.

### Related

* [#attachments](#attachments) — The general-purpose attachment block — Signature Pad uses the same attachment store.
* [Action Components](/client-admin-guide/getting-started/action-components.md) — Submit Button: The block that submits the order with attached signature.

## Registers

The block that ties a POS workflow to a physical register and cash drawer. Loads the user's register and location from the subsidiary settings, drives Payments' available tender list, and manages cash drawer open/close with opening and closing balance flows.

The block also blocks new drawer sessions if a previous-day drawer is still open — enforcing close-out before new business.

### Available in

* Order Form modules **only**

### When to use

* Every cashier register workflow.
* POS pages where cash handling needs to be tracked at the register level.
* Anywhere multiple cashiers share a single physical register and the system needs to know who's using it.

### What it depends on

Registers reads the employee's register assignment and location from the **subsidiary settings** — configuration managed by your **NetSuite Admin** in NetSuite, not in the Client Admin Portal.

| What your NetSuite Admin must set up                         | Effect on Registers                                              |
| ------------------------------------------------------------ | ---------------------------------------------------------------- |
| Register records created and linked to locations in NetSuite | Registers can find the employee's register at login              |
| Each employee record linked to a register / location         | The block maps the logged-in user to the correct register        |
| Payment methods configured on the register                   | The **Payments** block's tender list reflects these methods      |
| Currency set on the subsidiary                               | Registers and Payments both read currency from subsidiary config |

If a cashier sees "no register found" or can't open a session, the most likely cause is that their NetSuite employee record isn't linked to a register. Ask your NetSuite Admin to verify the register and location assignment on the employee record.

### Settings

| Setting       | Description                                                               |
| ------------- | ------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — payment methods and cash drawer settings. |

The configuration modal supports:

* **Payment Methods** — which methods the register accepts.
* **Enable Cash Drawer** — whether this register has a physical cash drawer. Default: Yes.
* **Cash Drawer settings:**
  * **Enable Auto Open** — auto-open the drawer at the start of cash transactions. Default: Yes.
  * **Require Opening Balance** — prompt for opening cash balance at drawer-open. Default: Yes.
  * **Require Closing Balance** — prompt for closing cash balance at drawer-close. Default: Yes.
  * **Allow Discrepancy** — permit closing without resolving variance between expected and counted cash. Default: No.

### How it works

1. Loads register and location settings from the subsidiary settings API.
2. Maps the current user to a register/location using employee ID matching.
3. Stores location, register, and currency settings in session state — Payments and Order Lines read from there.
4. At workflow start, checks for an existing open cash drawer:
   * If today's drawer is open, use it.
   * If a previous-day drawer is still open, block the new session and require close-out.
5. **Drawer-open modal** — collects opening balance (if required).
6. **Drawer-close modal** — collects closing balance, computes expected vs counted variance, requires confirmation if discrepancy isn't allowed.
7. Dispatches `cashDrawerOpened` / `cashDrawerClosed` events for navigation integration (e.g. update the sidebar status indicator).

{% hint style="warning" %}
**Allow Discrepancy = No** is the safe default — cashiers must reconcile the till before closing. Set to Yes only for low-cash environments where forcing reconciliation is more friction than value.
{% endhint %}

### Examples

**Standard cashier shift.** Registers with default settings. Cashier opens drawer with starting balance, takes transactions, closes drawer with counted cash; system computes variance and requires confirmation.

**No-cash register.** Registers with Enable Cash Drawer = No. Card-only terminal — register association is tracked but no drawer flow.

**Tight reconciliation policy.** Allow Discrepancy = No. Cashier can't close without resolving any variance between expected and counted cash.

### Related

* [#payments](#payments) — The payment-collection block that uses the register's configured methods.
* [Report Components](/client-admin-guide/getting-started/report-components.md) — EOD Reports: The end-of-day reconciliation report that summarises drawer activity.

## File Processor

A file upload and processing block that lives in the Order Form header. Handles file upload + custom processing logic tied to the transaction payload — distinct from the simpler **Attachments** block which just attaches files without processing.

The exact processing behaviour depends on how your implementation team has configured it for your workflow.

### Available in

* Order Form modules **only**

### When to use

* Workflows where uploaded files need processing before becoming attachments — for example, parsing a CSV of items, validating a vendor invoice, or transforming a document.
* Custom upload flows specific to your business that go beyond simple file attachment.

For straightforward "attach this file to the order" use cases, use **Attachments** instead.

### Settings

Configuration depends on your implementation. Common options include:

| Setting              | Description                                                                    |
| -------------------- | ------------------------------------------------------------------------------ |
| **File types**       | Accepted file formats.                                                         |
| **Processing rules** | What the block does with uploaded files (parsing, validation, transformation). |
| **On complete**      | What happens after processing finishes.                                        |

### How it works

The block is a wrapper around custom processing logic. At a high level:

1. The user uploads a file.
2. The block runs the configured processing logic against it.
3. The result is written to the order's payload (e.g. parsed line items, validated metadata, attached document IDs).
4. Downstream blocks read the processed result.

Because the processing rules are implementation-specific, ask your implementation team how File Processor is configured for your workflow.

{% hint style="info" %}
File Processor and **CSV Import** overlap in some scenarios — both can ingest a file. Use CSV Import for the standard "import line items from CSV" path; use File Processor for custom processing that doesn't fit that shape.
{% endhint %}

### Related

* [#attachments](#attachments) — For simple file attachment without custom processing.
* [#csv-import](#csv-import) — For importing line items from a CSV file.

## Attachments

A multi-file upload block for Order Form headers. Validates file type, size, and count, uploads each file to NetSuite, and ties the resulting attachment IDs to the order so they're saved with the transaction.

### Available in

* Order Form modules **only**

### When to use

* Order Form pages where users need to attach supporting documents — purchase orders, receipts, signed forms, photos.
* Quotation flows where a customer's RFQ document gets attached to the quote.
* Returns workflows where users attach photos of damage.

For signature capture, use **Signature Pad** — it uses the same attachment store but is purpose-built for signatures. For uploaded files needing processing, use **File Processor**.

### Settings

| Setting   | Description                           |
| --------- | ------------------------------------- |
| **Title** | Heading text. Default: *Attachments*. |

The block has additional internal config defaults:

* **Allowed file types** — `.pdf, .doc, .docx, .jpg, .jpeg, .png, .txt`.
* **Max file size** — 10 MB per file.
* **Max files** — 5.

### How it works

1. User picks or drags files into the upload area.
2. Each file is validated against allowed types, max size, and max count.
3. Valid files are converted to base64 and uploaded via the NetSuite RPC `uploadAttachment`.
4. Files are stored at `/SuiteApps/com.in8sync2.brm/brm_restricted_temp/attachments`.
5. The resulting file IDs are written to `attachmentsData` in session state.
6. Filenames get prefixed with the BRM order ID for traceability.
7. On submission, the attachment IDs are linked to the transaction.
8. After successful submission, the block clears (`formResetAfterSubmission`).

Upload progress and error badges are shown inline. Only errors prevent the form from submitting.

{% hint style="info" %}
**Errors prevent submission, but warnings don't.** A file that's too large blocks submit. A successfully uploaded file with a non-blocking warning lets the order through.
{% endhint %}

### Examples

**Customer-supplied PO attachment.** Attachments block on a B2B order form. Customer attaches their own PO PDF; it ships with the sales order.

**Damage photos on returns.** Attachments on a returns workflow. Customer or staff uploads photos as evidence; attached to the return record.

**Signed agreement attachment.** Attachments alongside a Signature Pad — Signature Pad captures the signature, Attachments handles any supporting docs.

### Related

* [#signature-pad](#signature-pad) — For signature attachments.
* [#file-processor](#file-processor) — For uploads that need custom processing.
* [#csv-import](#csv-import) — For importing line items from a CSV.

## Saved Orders

Lets the cashier save an in-progress order and resume it later. Loads the saved-orders list filtered by current location (or all locations) and the active user, with optional column customisation. Includes navigation guards that block tab close / page navigation when an unsaved order is in progress.

### Available in

* Order Form modules **only**

### When to use

* Cashier registers where a customer steps away mid-sale and the cashier needs to handle other customers in the meantime.
* Multi-shift workflows where one cashier starts an order and another finishes it.
* Anywhere "save this for later" is part of the natural flow.

### Settings

| Setting       | Description                                                                      |
| ------------- | -------------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — button labels, column selection, location scope. |

The configuration modal supports:

* **Saved Orders Button Label** — text on the *open saved orders* button. Default: *Saved Orders*.
* **New Button Label** — text on the *new order* button. Default: *New*.
* **Save Button Label** — text on the *save current order* button. Default: *Save*.
* **Columns** — which columns to show in the saved-orders list. Available: Order Name, Order Number, Date, Customer Name, Logged-in User, Authorized User, Quantity, Total. All enabled by default.
* **Show All Location Orders** — show saved orders from all locations (Yes) or only the current location (No). Default: No.

### How it works

1. Loads saved orders via SuiteQL, filtered by:
   * Current location (or all locations if Show All Location Orders = Yes).
   * Subsidiary.
   * Module name (so the list is workflow-specific).
2. Parses each order's `custrecord_brm_order_items` JSON to compute item count and total.
3. The user clicks *Save* — a modal appears asking for an optional order name.
4. The user clicks *Saved Orders* — sees the list, picks one to load.
5. **Loading** clears the current order state, then restores the entire saved order: customer, header fields, line items, discounts, shipping method, addresses, and any payment or tender data. Line items are marked as `source: 'savedOrder'`.
6. **Deleting** soft-inactivates the saved-order record (no hard delete).
7. **Navigation guard** — if the user has an in-progress order with unsaved changes, navigation is blocked (with a confirm prompt) via `beforeunload` + the TanStack Router blocker.

{% hint style="info" %}
Use **Show All Location Orders = Yes** in environments where cashiers move between registers and need to pick up where they left off regardless of which physical location they're at.
{% endhint %}

### Examples

**Standard cashier hand-off.** Saved Orders with default settings. Cashier saves a sale, walks away, another cashier opens the saved orders list, picks it up, and completes the transaction.

**Multi-location warehouse.** Saved Orders with Show All Location Orders = Yes. Pick from any saved order across all warehouses.

**Compact saved-list view.** Columns trimmed to just Order Name, Customer Name, Total — for a tighter list on small screens.

### Related

* [#order-lines](#order-lines) — The block that holds the items being saved or resumed.
* [Entity Components](/client-admin-guide/getting-started/entity-components.md) — Customer/Vendor Selection: The customer that's saved alongside the order.

## Gift Cards & Gift Certificates <a href="#gift-cards" id="gift-cards"></a>

SphericalBRM supports two gift-related flows. Neither is a standalone Page Builder block — both are built into **Order Lines** (for selling) and **Payments** (for redeeming):

* **Sell a gift certificate** — a customer purchases a gift certificate item. The Gift Certificate modal opens in Order Lines to configure the certificate amount and code.
* **Redeem a gift card** — a customer pays for their order (in whole or in part) using a gift card code. Handled as a **Gift Card** tender in the Payments block.

### Available in

* Order Form modules

### When to use

* **Sell a gift certificate** — when a customer wants to buy a gift card/certificate to give to someone else. The cashier adds the gift certificate item to Order Lines.
* **Redeem a gift card** — when a customer is paying and uses a gift card code to cover all or part of the balance. The cashier selects Gift Card as a tender in Payments.

### Selling a gift certificate (Order Lines)

1. The cashier adds the gift certificate item to Order Lines by scan, search, or catalog.
2. The **Gift Certificate modal** opens.
3. The cashier enters (or the system auto-generates) the certificate code and confirms the value.
4. The line is added to the order. The gift certificate record is created in NetSuite on submission.

### Redeeming a gift card (Payments)

1. On the Payments screen, the cashier selects **Gift Card** as the tender.
2. The **Gift Card modal** opens. The cashier scans or types the gift card code.
3. The system looks up the card in the gift certificate records and validates the balance. Expired cards and zero-balance cards are rejected before the cashier sees any balance.
4. The card number is masked — only the last four digits display.
5. The cashier enters the payment amount (capped at the card's remaining balance and the order total).
6. The cashier clicks **Apply**. If the card doesn't cover the full balance, a second tender can be added to cover the remainder.

### Before you start

* The `customrecord_brm_giftcertificate` custom record type must be installed by your NetSuite Admin.
* The Gift Card tender must be enabled in the subsidiary's payment processor settings.
* Gift certificate items must exist in your NetSuite item list before cashiers can add them to orders.

### Common issues

* **Gift Card tender doesn't appear** — it isn't enabled in the subsidiary's Card Present / Card Not Present configuration. Check with your NetSuite Admin.
* **"Card not found" error** — the code was entered incorrectly, or the certificate record hasn't been created in NetSuite yet.
* **Card shows as expired** — the gift certificate's expiration date has passed. Issue a new certificate.
* **Zero balance** — the card has already been fully redeemed. The system rejects it at lookup.

### Related

* [#payments](#payments) — The payment block where Gift Card appears as a tender option.
* [#order-lines](#order-lines) — Where gift certificate items are added and the issuing modal opens.

## Gift Card Status

A read-only lookup block that displays the current status and balance of a gift card without applying it to an order. The user types or scans a gift card number and immediately sees whether the card is Active, Expired, or has No Balance, along with its remaining funds.

This block is useful for customer-service workflows, gift-card support inquiries, or any context where an employee needs to check a card's status before the customer decides what to do (redeem, replace, or reload).

### When to use it

* Customer-service pages where staff help customers check their gift card balance.
* Support workflows where you need to verify a card's status before processing a return or exchange.
* Display screens showing available store credit or gift card balances.

### Before you start

* The `customrecord_brm_giftcertificate` custom record type must be installed.
* Gift certificate items must exist in NetSuite.

### Settings

| Setting              | Description                                                                                   |
| -------------------- | --------------------------------------------------------------------------------------------- |
| **Title**            | Heading text displayed above the lookup. Default: *Gift Card Status*.                         |
| **Placeholder**      | Input placeholder text. Default: *Enter gift card number...*.                                 |
| **Button Label**     | Text on the lookup button. Default: *Check Status*.                                           |
| **Mask Card Number** | When on, the displayed card number shows only the last four digits for privacy. Default: Yes. |

### How it works

1. The user enters or scans a gift card number.
2. Clicks **Check Status** (or presses Enter).
3. The block looks up the card in the gift certificate records.
4. The result displays:
   * **Status badge** — Active / Expired / No Balance.
   * **Remaining balance** — the funds available on the card.
   * **Card number** — displayed in full or masked per the setting.
5. If no matching card is found, a "Card not found" message appears.

### What success looks like

* The user sees the card's current status (Active, Expired, or No Balance).
* The remaining balance is clearly displayed.
* The card number is shown with or without masking as configured.
* If expired or zero-balance, the block shows the status clearly so the employee and customer know the card cannot be used.

### Common issues

* **"Card not found"** — the number was entered incorrectly, or the certificate hasn't been created yet.
* **Shows as "No Balance"** — the card has already been fully redeemed.
* **Shows as "Expired"** — the certificate's expiration date has passed.

### Related

* [#payments](#payments) — Where Gift Card appears as a tender for redemption.
* [#order-lines](#order-lines) — Where gift certificates are sold.

## Topaz Signature Pad

A Page Builder block that lets customers sign using a physical Topaz signature pad connected to the cashier's computer. The SigWeb browser plugin communicates with the hardware to capture a high-quality signature, convert it to a PNG image, and attach it to the transaction. Use this block when a hardware signature device is available; for touch-screen or mouse-drawn signatures, use [#signature-pad](#signature-pad) instead.

### When you'd use it

* POS workflows where a Topaz signature pad is deployed at the checkout counter.
* Service-order screens where a customer signature is proof of acceptance.
* Any order flow that requires a legal-quality signature captured directly from a physical device.

### Before you start

* A **Topaz signature pad** must be physically connected to the cashier's computer.
* The **SigWeb** plugin or service must be installed and running on that machine (this is what allows the browser to communicate with the device). Your NetSuite Admin or IT team handles the SigWeb installation.
* The block is available in **Order Form modules only**.

### Step by step

#### Set up the block settings

1. Click the **Configure** button next to the block in Page Builder.
2. In the **General** tab, enter the **Title** and **Instruction** text that will appear to the customer (defaults are provided, but customize if needed).
3. Optionally choose a **Target Field** from the dropdown — this is a NetSuite transaction field that will store the file ID of the signature. Leave blank if you only want the signature attached to the Files tab.
4. Click the **Signature Rules** tab if you want to make the signature mandatory only under certain conditions. An optional **PIN Override** tab allows managers to skip a signature requirement by entering their PIN when conditions would normally require one.
5. Click **Save Configuration**.

#### Capture a signature at runtime

1. When the customer reaches the signature pad block on the order form, they see the signing instructions.
2. The **Sign** button is active only if SigWeb is connected to the hardware. If it's disabled, the SigWeb service isn't running — see [Common issues](#common-issues) below.
3. The customer clicks **Sign** to activate the pad.
4. They sign on the physical Topaz device. A preview of their signature appears on screen as they write.
5. Once they've finished signing, they click **Done**. To start over, they click **Clear** and sign again.
6. The signature is automatically uploaded to NetSuite and attached to the transaction. If a **Target Field** was configured, the file ID is also written to that field.
7. If **Required Rules** are set and the conditions are met, the Submit Button is blocked until a signature is captured. Once a valid signature is attached, Submit becomes active.

#### Signature Rules tab

The **Signature Rules** tab (in the Configure modal) lets you define the conditions under which a signature is required. Rules are evaluated at runtime — if the conditions match, the signature becomes mandatory before the order can be submitted.

**Common rule examples:**

* Require signature only for orders over a certain amount.
* Require signature for specific order types (e.g. exchanges).
* Require signature when customer payment terms are used.
* Require signature for any order containing a specific item or category.

**Manager override:** If a signature rule would otherwise require a signature, a manager with the proper PIN can bypass the requirement by entering their manager PIN. The signature is then marked as "PIN-authorized" in the audit trail rather than requiring a pen-and-ink capture.

### What success looks like

After a customer signs:

* The signature appears as a preview image on the form.
* A green confirmation badge shows **Signature attached (File ID: ...)**.
* The signature file is available in the transaction's **Files** tab.
* If a target field was set, that field now contains the file ID.
* The customer can click **Re-sign** to replace the signature if needed.
* The order can be submitted (assuming all other validation passes).

### Common issues

* **Sign button is disabled** — SigWeb is not running. Check that the SigWeb service is active in the system tray or Services panel on the cashier's computer. Ask your IT team to restart it if needed.
* **"SigWeb not found" error appears** — SigWeb isn't installed on this machine. Your IT team needs to install it from the Topaz support site before the block will work.
* **Signature captures but doesn't attach** — The user may not have permission to attach files to transactions in their NetSuite role. Ask your NetSuite Admin to check the user's permissions.
* **Canvas shows "Press Sign to activate" but nothing happens when I click Sign** — Confirm SigWeb is running and the Topaz device is powered on and connected via USB. Try restarting the browser.

### Related

* [#signature-pad](#signature-pad) — For touch-screen, mouse, or other external device signatures.
* [#attachments](#attachments) — How signatures and other files are stored with the transaction.
* [Action Components](/client-admin-guide/getting-started/action-components.md) — Submit Button: The block that submits the order; can be gated by signature required rules.

## Vendor Portal

A workflow configuration that gives vendors access to a dedicated purchase-order workflow. This is not a Page Builder block — it is an **audience mode** you set on a workflow, combined with standard blocks (such as Transactions Advanced) configured to scope records to the vendor entity.

Vendors log in, see the purchase orders issued to them, and can take configured actions — such as acknowledging receipt or confirming fulfilment.

### Available in

* Workflows configured with the **Vendor** user restriction (set on the Transactions Advanced block)

### When to use

* You want vendors to have a self-service portal where they can see their open purchase orders.
* Your purchase-order workflow needs a vendor-facing view separate from your internal team's view.
* You need vendors to confirm, acknowledge, or update the status of POs without contacting your team directly.

### Before you start

* **Who can do this:** Client admins who can edit workflows and page builder configurations.
* Vendor users must have NetSuite login credentials with the appropriate vendor role.
* The **Transactions Advanced** block on the page must have the **Vendor** user restriction enabled.
* Your NetSuite Admin must confirm the workflow's order type is set to Purchase Order and that vendor records exist in NetSuite.

### How it works

1. The vendor logs in to the SphericalBRM portal with their NetSuite credentials.
2. The workflow loads scoped to that vendor's records. Each vendor sees only their own purchase orders — records belonging to other vendors are not accessible.
3. The vendor can filter and search by PO number, date, or status using the Transactions Advanced block, and drill into any order for line-item detail.
4. Any Action Buttons configured on the page give the vendor self-service actions such as confirming receipt or requesting a change.

{% hint style="info" %}
Vendor scoping is controlled by enabling the **Vendor** restriction on the Transactions Advanced block. This automatically limits record lookups to the vendor entity that is logged in.
{% endhint %}

### What to configure

A vendor portal uses standard Page Builder blocks — the key setting is enabling vendor scoping on the Transactions Advanced block:

* **Transactions Advanced — Vendor restriction** — open the Transactions Advanced block settings and enable the **Vendor** option under User Restrictions. This scopes the transaction list to the logged-in vendor's records only.
* **Order type** — set the workflow's order type to Purchase Order so vendors see POs rather than sales orders.
* **Page layout** — design the page using standard blocks (Order Lines, Transaction Record, Action Button, etc.) as you would for any audience, scoped to purchase-order fields.
* **Actions** — use Action Button to add vendor-facing actions (for example, "Confirm Receipt" or "Request Change").

### Common issues

* **Vendor sees no orders** — confirm the vendor's NetSuite record is linked correctly and the **Vendor** restriction is enabled on the Transactions Advanced block.
* **Wrong orders appearing** — check that the workflow's order type is set to Purchase Order (not Sales Order or Cash Sale).

### Related

* [#transactions-advanced](#transactions-advanced) — The transaction list block used to display purchase orders in a vendor portal.
* [#transaction-record](#transaction-record) — For displaying the detail of a single purchase order.

## CSV Import

Imports line items from a CSV file into the current order. The block matches CSV columns to item identifiers (SKU, UPC, Item ID, Display Name) and adds matched items to Order Lines. The CSV file itself also uploads to NetSuite as an audit trail.

### Available in

* Order Form modules **only**

### When to use

* B2B order entry where buyers paste or upload a procurement spreadsheet.
* Bulk re-order workflows ("here's last quarter's order, run it again").
* Migration scenarios where new orders are seeded from external systems.

For attaching a CSV to an order without parsing it as items, use **Attachments**. For custom file processing logic, use **File Processor**.

### Settings

| Setting           | Description                                      |
| ----------------- | ------------------------------------------------ |
| **Title**         | Heading text. Default: *CSV Import*.             |
| **Max File Size** | Upper limit for the uploaded CSV. Default: 5 MB. |

### How it works

1. The user uploads a CSV file.
2. The block parses the CSV (simple comma split — no quoted-field escape handling).
3. For each row, it tries to match the item by:
   * Exact match on the column headers *Item*, *SKU*, *Product*, or *UPC*.
   * Fuzzy fallback against the catalog's `itemid`, `displayname`, `upc`, and `sku` fields.
4. Matched items are added to Order Lines with `source: 'csv'`. Unmatched rows are flagged.
5. **Custom fields** map automatically when the CSV column label or field ID matches a known item field.
6. Items combine with any existing Order Lines (the import doesn't replace).
7. The CSV file uploads to NetSuite as part of the order's audit trail.
8. A preview shows the first 5 rows so the user can sanity-check before confirming.
9. The `imported` flag is set on the order after success.

{% hint style="info" %}
The CSV parser is intentionally simple — comma splits, no embedded-comma escaping. For files with quoted commas or special characters, clean them up first or use a tab-separated export.
{% endhint %}

### Examples

**B2B reorder.** CSV Import with default settings. Buyer pastes their reorder spreadsheet, the block matches each row to the catalog and populates Order Lines.

**Procurement integration.** CSV Import paired with Attachments — the CSV import handles the items, Attachments holds the original PO PDF.

**Mass quote build.** CSV Import on a quote workflow. Sales rep loads a starter CSV from a templated tool and adjusts in Order Lines before sending the quote.

### Related

* [#order-lines](#order-lines) — Where imported items land.
* [#scan-items](#scan-items) — The barcode-scan alternative for adding items.
* [#file-processor](#file-processor) — For custom file-processing flows beyond CSV import.

## Scan Items

A barcode and search input for adding items to the current order. Type or scan an item identifier (UPC, SKU, item ID) and the matching item is added to Order Lines. Supports continuous scanning, audio feedback, and a virtualised search dropdown for large catalogs.

For serialised, lot-controlled, or bin-tracked items, the block opens the appropriate Order Lines modal flow rather than adding directly.

### Available in

* Order Form modules

### When to use

* Cashier registers with barcode scanners.
* Warehouse pick / pack workflows where speed matters.
* Order entry pages where users know item identifiers and want to skip catalog browsing.

### Settings

| Setting                      | Description                                                                                     |
| ---------------------------- | ----------------------------------------------------------------------------------------------- |
| **Scan Items Configuration** | Opens the configuration modal — scannable fields, audio feedback, placeholder, success message. |

The configuration modal supports:

* **Scannable Fields** — which fields to match against. Default: `[upc, sku, itemid]`.
* **Enable Scan Sounds** — play a confirmation/error sound on each scan. Default: Yes.
* **Placeholder** — input placeholder text. Default: *Scan or enter item SKU/UPC...*.
* **Show Success Message** — display a transient confirmation after a successful scan. Default: Yes.
* **Display Fields** — optional list of fields shown in the search dropdown.
* **Search Mode** — how the dropdown filters: *Fuzzy* (contains, default), *Exact*, or *Combo* (all words match). Use Exact for high-accuracy environments where partial matches cause errors.
* **Sort By** — sort dropdown results by any catalog field, ascending or descending. For example, sort by quantity available to surface best-stocked items first.
* **Success Volume / Error Volume** — independent loudness sliders (0–100%) for the success and error audio cues.
* **Add Separate Line Items** — when on, each scan creates a new order line instead of incrementing quantity on an existing matching line.
* **Scan Field Mappings** — map catalog item fields to order line properties on scan. For example, set the rate from a custom price field or populate a custom line column automatically. Each mapping supports a transform (parse as number, uppercase, lowercase) and a default value.
* **Keyboard Shortcut** — a keyboard shortcut that focuses the scan input from anywhere on the page.
* **Add Path-Based Field** (under Scannable Fields) — add a dot-notation path to scan against nested item data, for custom sublist or object field structures.

### How it works

1. On mount, loads the workflow's catalog items, pre-computes a search index, and auto-focuses the input so scanning can begin immediately without clicking.
2. The user types or scans an identifier.
3. **Exact match** runs first against `internalId` (typical for barcode reads).
4. **Partial match** runs next against the configured Scannable Fields — the dropdown appears after 2+ characters.
5. The dropdown is virtualised (Tanstack Virtualizer) so even very large catalogs render quickly.
6. On selection or Enter:
   * **Serialised / lot / numbered / bin items** — emits a `scanItemsEvent` to open the Order Lines modal flow for serial/lot capture.
   * **Standard items** — adds the item to Order Lines immediately.
7. A `scanItems-itemScanned` JavaScript hook fires on every successful scan.
8. Audio feedback plays on success or error (when enabled).
9. After a successful add, the input clears and re-focuses for continuous scanning.

{% hint style="info" %}
For high-throughput scanning, leave **Enable Scan Sounds = Yes** — the audio cue confirms the scan registered without the cashier having to look at the screen.
{% endhint %}

### Examples

**Standard cashier register.** Scan Items at top of the Order Lines area. Cashier scans each item; the order builds row by row.

**Warehouse picking.** Scan Items with Display Fields = `[itemid, displayname, location]`. Picker scans, sees the item and bin, confirms the pick.

**Post-scan validation.** Scan Items paired with a JavaScript block on the `scanItems-itemScanned` hook to validate the item against custom rules (e.g. weight check, age verification).

### Related

* [#order-lines](#order-lines) — Where scanned items land.
* [#csv-import](#csv-import) — The bulk-import alternative for adding many items at once.
* [Advanced Components](/client-admin-guide/getting-started/advanced-components.md) — JavaScript: Hook into the scan event for custom validation or side effects.

## Transaction Search

The block for finding an existing transaction. Configure which transaction types it searches (Sales Order, Cash Sale, Invoice, Estimate, etc.), which fields the user can search against, and which fields appear in the results.

It runs in one of two modes:

* **Load** — when the user picks a result, the full transaction (with line items) is published to the page so other blocks like Transaction Record can render it.
* **Filter** — lighter mode that just sets filter state for a downstream Transaction List, without loading a single transaction.

### Available in

* Page modules
* Dashboard modules
* Reports modules
* Order Form modules

### When to use

* Customer-service workflows where the agent needs to look up a past order.
* Order History pages where users browse their own past transactions.
* Edit-existing-order flows on Order Form pages (load an existing order back into the form).
* Reports pages where a user picks a date range or transaction type for the report below.

### Settings

| Setting       | Description                                                                                                      |
| ------------- | ---------------------------------------------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — title, default record types, button labels, displayed fields, searchable fields. |

The configuration modal supports:

* **Title** — heading shown above the search.
* **Default Record Types** — which transaction types are searched by default (e.g. *salesorder, cashsale, invoice*).
* **Default Transaction** — pre-load a specific transaction by ID when the page opens (handy for *edit existing order* flows).
* **Search Button Label / Clear Button Label / Change Button Label** — text on the action buttons.
* **Display Fields** — fields shown in the result row.
* **Searchable Fields** — fields the search query checks.

The block also has a top-level **Mode** prop (Load or Filter) that's set when the workflow is built.

### How it works

1. The user chooses a transaction type (or accepts the defaults), enters a search term, and clicks Search.
2. Matching transactions appear in a card layout.
3. The user picks a result.
4. **Load mode** — the transaction's header fields and line items are loaded into the page's session state. Transaction Record (and any other reading block) renders the data.
5. **Filter mode** — the picked criteria flow as filter state to a downstream Transaction List block.

### Examples

**Customer-service order lookup.** Transaction Search in Load mode at the top of a Page module, with Transaction Record below it. Agent finds an order by ID; the record loads.

**Order edit.** Transaction Search in Load mode on an Order Form page, used at the start of an "edit existing order" flow.

**Report filter.** Transaction Search in Filter mode on a Reports page, driving a Report Widget that re-queries when the filter changes.

### Related

* [#transaction-record](#transaction-record) — The detail block that renders the transaction Transaction Search loads.
* [#transactions-advanced](#transactions-advanced) — The list block that responds to Filter-mode search criteria.
* [#transaction-list-filter](#transaction-list-filter) — Standalone filter controls that pair with Transaction List.

## Transaction Search By Item

A search input that filters the page's transaction list by the items inside those transactions. Type an item ID, UPC, name, or display name and the transaction list narrows to only transactions that contain matching items.

Pair it with a **Transaction List** or **Transaction Search** block on the same page — this block doesn't render its own list; it filters the one already on the page.

### Available in

* Page modules
* Order Form modules
* Dashboard modules
* Reports modules

### When to use

* Reporting pages where users need to find every transaction that included a specific item (e.g. for warranty lookup, recall handling, or sales analysis).
* Order-history pages where the user knows the item but not the transaction number.
* Audit and reconciliation flows that work back from item to transaction.

For a generic transaction-field filter (date range, customer, status), use **Transaction List Filter** instead.

### Settings

The block opens a configuration modal:

| Setting                  | Description                                                                                          |
| ------------------------ | ---------------------------------------------------------------------------------------------------- |
| **Title**                | Heading shown above the search input. Default: *Search Transactions by Item*.                        |
| **Placeholder**          | Input placeholder text. Default: *Enter item name, ID, or UPC...*.                                   |
| **Search Button Label**  | Default: *Search*.                                                                                   |
| **Clear Button Label**   | Default: *Clear*.                                                                                    |
| **Search Fields**        | Which item fields to search across — Item ID, Item Name, UPC Code, Display Name. Toggle each on/off. |
| **Default Record Types** | Which transaction types the search returns (Sales Order, Invoice, Return Authorization, etc.).       |

### How it works

1. The user types a search term and clicks **Search**.
2. The block runs a SuiteQL query to find every transaction internal ID that contains an item matching the search term across the enabled search fields.
3. The matching transaction IDs are pushed into the page's transaction filter state.
4. The Transaction List or Transaction Search block on the page automatically narrows to those transactions.
5. Clicking **Clear** removes the filter and the list returns to its unfiltered state.

### Examples

**Recall lookup.** Configure search fields to *Item Name* and *Item ID*. When a recall is announced, the user pastes in the affected SKU and instantly sees every customer order that included it.

**Cross-sell analysis.** Search by item name to see every order that included a popular product — useful for spotting bundling patterns.

### Common issues

* **No results when results are expected** — verify the search term matches one of the enabled search fields. Some catalogs use UPC heavily and Item Name rarely; toggle accordingly.
* **Slow search on large datasets** — narrow the *Default Record Types* to only the types you care about (e.g. just Sales Orders, not all transaction types).

### Related

* [#transaction-search](#transaction-search) — Search transactions by transaction-level fields.
* [#transaction-list-filter](#transaction-list-filter) — Filter the transaction list by date, status, type, and other transaction-level fields.

## Transactions Advanced

The flexible transaction-list block. Configure which transaction types are listed, which columns to show, what filters apply, and which row-level actions users can take. The data source can be the standard transaction tables, a NetSuite saved search, or a custom query — with priority *query > saved search > standard*.

The block also supports user-restriction filtering — automatic visibility filters based on the signed-in user's vendor / customer / partner / employee record.

> **Note on naming:** The palette label is **Transaction List**. The block file is `TransactionsAdvanced`.

### Available in

* Page modules
* Dashboard modules

### When to use

* Order History pages where users browse their past transactions.
* Customer-service queues where agents work through open orders.
* Operations dashboards listing transactions by status, location, or type.
* Anywhere a richer, configurable list is needed — beyond what Report Widget provides.

For a simpler tabular report driven by a single saved search, **Report Widget** is often a better fit.

### Settings

| Setting       | Description                                                                                  |
| ------------- | -------------------------------------------------------------------------------------------- |
| **Title**     | Heading text. Default: *Transactions Advanced*.                                              |
| **Configure** | Opens the configuration modal — types, columns, filters, actions, restrictions, data source. |

The configuration modal supports:

* **Transaction Types** — which types to include (e.g. *SalesOrd*, *CashSale*, *Invoice*).
* **Columns** — which fields to show. Each column has a field ID, label, visible toggle, optional width, and a format (*text*, *number*, *currency*, *badge*, or *avatar*). Default fields: tranid, trandate, entity, status, total.
* **Filters** — pre-applied filters that always run. Each filter can be static (a fixed value) or dynamic — when dynamic is on, the filter value is resolved from a session expression at runtime.
* **Actions** — per-row buttons. Each action has a label, icon, and one of three types:

  * **Navigate** — sends the user to another page (e.g. an order detail page).
  * **Modal** — opens a modal on the current page.
  * **Custom script** — runs a script when the user clicks the button.

  Each action has an optional **Action visibility** setting that controls when the button appears for a given row:

  * **Always** (default) — the button shows on every row.
  * **Rules** — show or hide based on the row's data. Pick a column, choose an operator (equals, not equals, greater than, and others), and enter a value. Multiple rules combine with AND or OR logic. Enable **Use Display Text** to compare against the human-readable label instead of the raw field value. Values also support dynamic expressions — for example `{{currentUser.id}}` for the signed-in user's ID.
  * **Script** — enter a script that receives the row data and returns *true* to show the button or *false* to hide it. If the script errors or returns something other than *true*, the button is hidden. For Related Records actions, the script also receives a `parentRow` variable with the parent transaction's data.
* **Items Per Page** — pagination size. Default: 100.
* **Saved Search** — NetSuite saved search ID. Higher priority than the default columns.
* **SuiteQL** — raw query for full data control. Highest priority. Filter values support session tokens like `{USER_ID}` and `{CONTACT_ID}` for dynamic, per-user conditions. For more complex runtime values, `{{expression}}` syntax is also supported — for example `{{sessionData.key}}`.
* **User Restrictions** — automatic filters based on the signed-in user's entity. Toggle per entity type (vendor, customer, partner, employee), with per-user overrides.
* **Filter by Current User's Location** — when enabled, the transaction list displays only transactions where at least one line item is associated with the signed-in user's assigned location. Useful in multi-location operations where employees should see only their location's transactions. Default: off.
* **Display Mode** — *Full* (paginated table, default) or *Snapshot* (compact dashboard variant showing only the top *Snapshot Limit* rows).
* **Snapshot Limit** — number of rows to show in Snapshot mode. Default: 6.
* **Subtitle** — supporting copy beneath the title (Snapshot mode).
* **Show Filter Tabs** + **Filter Tabs** — render a tab strip above the table where each tab applies a saved filter set.
* **Status Color Config** — colour-code rows or status badges by transaction status.
* **Related Records** — an additional tab that shows records linked to each transaction row. When enabled, configure a query (use `{TRANSACTION_ID}` as a placeholder for the row's internal ID), set which columns to display, and add optional row-level actions with the same visibility options as the main Actions tab.

### How it works

1. Resolves the data source in priority order:
   * **SuiteQL** (highest) — runs the custom query.
   * **Saved Search** — runs the named saved search.
   * **Default** — runs a standard search filtered by the configured Transaction Types.
2. Applies filters from three sources combined: configured (from the modal), dynamic (from upstream Transaction List Filter blocks — which can include runtime-resolved values that auto-filter by the signed-in user's location or other session data), and user-restriction-based.
3. Renders results in a paginated table with the configured columns.
4. Per-row actions appear as buttons. Depending on the action type configured, they navigate to another page, open a modal, or run a script. Actions with visibility rules are shown or hidden based on the row's data.
5. On row hover, the destination page pre-fetches for snappier navigation.
6. Date filters use the workflow's configured date format for display.

In edit mode, the block limits to 10 records to keep the canvas responsive.

{% hint style="warning" %}
**SuiteQL** gives you full data-source control but bypasses the standard column / filter logic. Use it when the standard search isn't enough — and document your query carefully so future maintainers know what it returns.
{% endhint %}

### Examples

**Customer order history.** Transactions Advanced with Transaction Types = `[SalesOrd, Invoice]`, User Restrictions = customer (so each customer sees only their own orders), Actions = `[View → /order-detail?id={id}]`.

**Operations queue.** Transaction Types = `[SalesOrd]`, Filters = `status = Pending Fulfillment`, columns include *Date*, *Customer*, *Total*. Refreshes via the workflow's standard refresh cycle.

**Custom-query report.** SuiteQL set to a multi-table query joining transactions with custom records. Items Per Page = 50.

### Related

* [#transaction-list-filter](#transaction-list-filter) — Standalone filter inputs that drive Transactions Advanced.
* [Layout Components](/client-admin-guide/getting-started/layout-components.md) — Transaction List (layout): The layout shell with Filters + Table slots, designed to wrap this block.
* [Report Components](/client-admin-guide/getting-started/report-components.md) — Report Widget: The simpler saved-search-driven alternative.

## Transaction List Filter

A single filter input for a transaction list. Each Transaction List Filter block is one filter (text, date, or select). Drop multiple instances side-by-side or in a sidebar to build a full filter panel above a Transaction List.

The block writes its value into the page's transaction filter state, which Transaction List reads and re-queries against.

### Available in

* Page modules
* Dashboard modules

### When to use

* Above any Transaction List block where users need to narrow results.
* Inside the **Transaction List** layout's *Filters* slot.
* For multi-criteria browsing (e.g. *Date range + Status + Customer*) — drop one filter block per criterion.

### Settings

| Setting       | Description                                                               |
| ------------- | ------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — pick the field, operator, and field type. |

The configuration modal supports:

* **Field** — the transaction field this filter targets (e.g. *trandate*, *status*, *entity*).
* **Operator** — comparison: contains, equals, greater than, less than, between (depends on field type).
* **Field Type** — text, date, or select. Affects which input control is rendered.
* **Selected Options** — for select-type filters, the available values.
* **Padding** — spacing around the filter input. Default: 16.
* **Dynamic Value** (lightning bolt toggle) — when turned on, the filter's value is resolved at runtime from the current session instead of being set by the user. Use this to pre-filter the list automatically — for example, to always show only orders for the signed-in user's location. Enter a variable expression as the value (e.g. the current user's location or a session variable). Ask your Client Admin or In8Sync contact for the available variable names for your setup.

### How it works

1. On render, the block displays the configured input (text input, date picker, or dropdown).
2. As the user types or picks a value, the filter writes to the page's transaction-filter state.
3. Downstream Transaction List re-queries automatically with the new filter applied.
4. If no filter is configured yet, the block shows a placeholder reminder for the page builder.

The block reads the workflow's date format from session state for date fields, so a filter set up in MM/DD/YYYY input format renders correctly for users with a different display preference.

### Examples

**Date + status filter pair.** Two Transaction List Filter blocks in a Row above a Transaction List: one for *trandate* (date), one for *status* (select with the relevant statuses).

**Customer-search filter.** A single filter block on *entity* (text, contains operator) at the top of an Order History page. As the user types, the list narrows.

### Related

* [#transactions-advanced](#transactions-advanced) — The list block this filter drives.
* [Layout Components](/client-admin-guide/getting-started/layout-components.md) — Transaction List (layout): The layout block that has a Filters slot designed for these filter blocks.
* [#transaction-search](#transaction-search) — An alternative search-driven approach for finding specific transactions.

## Transaction Record

A container that displays one transaction in full. Provides four slots — *Page Header*, *Header Fields*, *Line Items*, *Related Records* — that you fill with other blocks to build the layout you want.

By default the *Header Fields* slot starts with a 2-column Row layout so you can immediately drop **Record Field** blocks into it. The other slots are empty until you populate them.

![Transaction Record showing a 2-column header field grid at the top, line items table in the middle, and a related records section at the bottom](https://229581143-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FAG04Mxmhw6PLRAZBvhtK%2Fuploads%2Fgit-blob-ac41c6d7ef55820647277289dd56a963a3faba55%2Fpb-transaction-record.png?alt=media)

### Available in

* Page modules
* Order Form modules

### When to use

* Customer-service detail pages where the agent inspects a single transaction.
* "Edit existing order" flows on Order Form pages — Transaction Record loads the order and Order Lines edits it.
* Anywhere a single transaction's full detail (header + lines + related records) is the focus.

For multi-transaction list views, use **Transaction List** instead.

### Settings

| Setting                  | Description                                                                                                                  |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------- |
| **Configure**            | Opens the configuration modal — record type, custom form, visibility toggles.                                                |
| **Title**                | Heading text. Default: *Transaction Record*.                                                                                 |
| **Page Header slot**     | Optional — drop a Heading or any block to render above the record.                                                           |
| **Header Fields slot**   | Pre-populated with a 2-column Row + Columns. Drop Record Field blocks (the *Page* version, see Order Lines View doc) inside. |
| **Line Items slot**      | Drop **Order Lines** (the page-context version) here to render the line items.                                               |
| **Related Records slot** | Drop **Transaction Related Records** here to show linked records.                                                            |

The configuration modal supports:

* **Record Type** — which transaction type this block renders (`salesorder`, `cashsale`, etc.). Default: salesorder.
* **Form** — optional NetSuite custom form ID to use.
* **Show Header** — display the header fields slot. Default: Yes.
* **Show Lines** — display the line items slot. Default: Yes.
* **Show Related Records** — display the related records slot. Default: Yes.

### How it works

The block reads the current transaction from session state (typically loaded by **Transaction Search** in Load mode or by URL parameter) and renders the slots configured.

Each slot can hold any blocks — the slot system gives you full control over layout. For most transaction types, drop:

* A **Heading** in Page Header.
* Several **Record Field** (page version) blocks in a Row layout in Header Fields.
* An **Order Lines** (page version) block in Line Items.
* A **Transaction Related Records** block in Related Records.

{% hint style="info" %}
Transaction Record is a *container*. The actual data rendering happens in the blocks you put inside its slots. Empty slots render as empty space.
{% endhint %}

### Examples

**Customer-service order detail.** Transaction Records with a Page Header containing a Heading, Header Fields with Record Field blocks for date / customer / status, Line Items with Order Lines (page version), Related Records with Transaction Related Records showing fulfilments and invoices.

**Read-only invoice view.** Transaction Record with Record Type = invoice. Header Fields shows due date, balance, terms; Line Items shows the invoiced items.

### Related

* [#transaction-search](#transaction-search) — The block that loads a transaction into Transaction Record.
* [#transaction-record-order-lines-view](#transaction-record--order-lines-view) — The page-context line items block that goes in the Line Items slot.
* [#transaction-record-view-field](#transaction-record--view-field) — The page-context field block that goes in the Header Fields slot.
* [#transaction-related-records](#transaction-related-records) — The block for the Related Records slot.

## Transaction Record — Order Lines View <a href="#transaction-record-order-lines-view" id="transaction-record-order-lines-view"></a>

A read-only line-items table designed for the **Line Items** slot of a Transaction Record. Renders the current transaction's lines as a sortable table or list, with configurable columns.

> **Note on naming:** This block's palette label is **Order Lines** — same as the editable [#order-lines](#order-lines) block used in Order Form modules. They're different blocks: the editable Order Lines is for building an order, this one is for displaying an existing transaction's lines.

### Available in

* Page modules **only**

### When to use

* Inside the **Line Items** slot of a Transaction Record block.
* Customer-service order-detail pages where lines are read-only.
* Anywhere you need to *display* a transaction's lines (rather than edit them).

For editable line entry on Order Form pages, use the editable [#order-lines](#order-lines) block.

### Settings

| Setting       | Description                                                         |
| ------------- | ------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — title, view mode, columns, sorting. |

The configuration modal supports:

* **Title** — heading text. Default: *Transaction Line Items*.
* **View Mode** — table (default) or list.
* **Columns** — array of column configs (which field, label, format, width). Defaults: Item (text, 200px), Quantity (number, 100px), Rate (currency, 120px), Amount (currency, 120px).
* **Show Header** — display column headers. Default: Yes.
* **Allow Sorting** — let users click column headers to sort. Default: Yes.
* **Sublist ID** — the NetSuite sublist this block reads from. Default: `item`. Change for non-standard transaction sublists.
* **Enable Printing** — show print actions on each line (or for the whole table). Default: off.
* **Print Mode** — *Line Item* (per-line print) or *Table* (whole-table print). Default: Line Item.
* **Print Template ID** + **Print Table Template ID** — NetSuite template IDs for the per-line and table print views.
* **Print Button Label** — text on the print button.
* **Print Debug** — include resolved variable context in the preview modal (for template authors).

### How it works

1. Reads the current transaction's line items from session state (loaded by Transaction Search or a URL parameter).
2. Renders rows in either table or list view.
3. Each column displays the configured field with the right format (currency, number, text).
4. If sorting is allowed, users click headers to reorder rows.
5. If no columns are configured, a placeholder card appears.
6. The total line count is shown.

{% hint style="info" %}
This block only works when a transaction is loaded into session state. Place it inside a **Transaction Record** that's been populated by a **Transaction Search**.
{% endhint %}

### Examples

**Standard order-detail line items.** Transaction Record — Order Lines View inside the Line Items slot of a Transaction Record, with default columns (Item, Quantity, Rate, Amount), sorting on.

**Compact list view.** View Mode = list, columns trimmed to *Item* and *Amount* only — useful for narrow side-panel layouts.

**Audit-style view.** Add columns for *Tax Amount*, *Discount*, *Custom Field X* for a richer line-by-line audit display.

### Related

* [#transaction-record](#transaction-record) — The container this block lives inside.
* [#order-lines](#order-lines) — The Order Form version for actually entering lines.

## Transaction Record — View Field <a href="#transaction-record-view-field" id="transaction-record-view-field"></a>

A read-only field display designed for the **Header Fields** slot of a Transaction Record. Pick a transaction field — it auto-resolves the field type and renders with the right format (text, currency, date, number, boolean, badge).

> **Note on naming:** This block's palette label is **Record Field** — same as the editable [#record-field](#record-field) used in Order Form modules. They're different blocks: the editable Record Field is for entering values during order entry, this one is for displaying values from an already-loaded transaction.

### Available in

* Page modules **only**

### When to use

* Inside the **Header Fields** slot of a Transaction Record block.
* Building a custom transaction-detail layout where you control which fields appear and where.
* Anywhere a single transaction field needs to be displayed (not edited).

For editable transaction fields on Order Form pages, use the editable [#record-field](#record-field).

### Settings

| Setting       | Description                                                                   |
| ------------- | ----------------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — field selection, label, format, display type. |
| **Title**     | Block title shown above the value. Default: *Transaction View Field*.         |

The configuration modal supports:

* **Field Name** — which transaction field. The field type and options auto-populate when you pick a field.
* **Field Label** — display label.
* **Field ID** — internal identifier (auto-resolved).
* **Field Type** — auto-detected: text, currency, date, number, boolean, badge.
* **Field Options** — for select fields (auto-populated).
* **Display Format** — text (default), currency, date, number, boolean, badge.
* **Display Type** — form-group (label above value) or inline (label and value on the same line). Default: form-group.
* **Decimal Places** — for numeric/currency formats: *auto* (use NetSuite's setting) or a fixed number. Default: auto.
* **Show Preview** — show dummy data in edit mode so you can see what the layout looks like. Default: Yes.

### How it works

1. Reads the current transaction's header fields from session state.
2. Resolves the configured Field Name and applies the configured Display Format.
3. **In edit mode** — shows generated dummy data (when *Show Preview* is on) so the layout is visible without a real transaction loaded.
4. **At runtime** — shows the actual value, or a skeleton loader while data loads.
5. If the field is missing from the loaded transaction, the block doesn't render.

{% hint style="info" %}
The block works only when a transaction is loaded into session state. Place inside a **Transaction Record** that's been populated by a **Transaction Search**.
{% endhint %}

### Examples

**Order header date.** Transaction Record — View Field with Field Name = `trandate`, Display Format = date, Display Type = form-group. Dropped into a Header Fields Column.

**Status badge.** Field Name = `status`, Display Format = badge. Renders the status as a coloured pill — handy at the top of an order detail.

**Customer name (inline).** Field Name = `entity`, Display Format = text, Display Type = inline. Renders compactly alongside other fields.

### Related

* [#transaction-record](#transaction-record) — The container this block lives inside.
* [#record-field](#record-field) — The Order Form version for actually entering field values.

## Transaction Related Records

A list of records linked to the currently loaded transaction — fulfillments, invoices, returns, payments, and other transactions in the same chain. Click a row to navigate to its detail page.

The block is designed for the **Related Records** slot of a Transaction Record but works wherever a transaction is loaded into session state.

### Available in

* Page modules **only**

### When to use

* Inside the Related Records slot of a Transaction Record block.
* Order-detail pages where users navigate from a sales order to its related fulfillment, invoice, or return.
* Any chain-aware workflow (sales → fulfillment → invoice → payment) where a single transaction view should expose links to related records.

### Settings

| Setting       | Description                                                          |
| ------------- | -------------------------------------------------------------------- |
| **Configure** | Opens the configuration modal — visible fields and destination page. |
| **Title**     | Heading text. Default: *Related Transactions*.                       |

The configuration modal supports:

* **Visible Fields** — which fields appear in each related-record row. Defaults: id, tranid, trandate, type, status, total.
* **Destination Page** — the Page module to navigate to when a related record is clicked.

### How it works

1. Reads the current transaction from session state.
2. Fetches related records linked to that transaction.
3. Renders each as a row with the configured visible fields.
4. Clicking a row navigates to the configured Destination Page (typically a Transaction Record page), passing the related record's ID.
5. The destination page can then load and display the related record using its own Transaction Record + Transaction Search blocks.

{% hint style="info" %}
For chain-aware navigation, configure the Destination Page to a generic transaction-detail page in the same workflow. Users can then click through fulfillment → invoice → payment in sequence.
{% endhint %}

### Examples

**Sales order → fulfillment chain.** Transaction Related Records inside the Related Records slot of a sales-order Transaction Record. Visible Fields show id, type, trandate, status. Destination Page = the workflow's transaction-detail page.

**Compact related view.** Visible Fields trimmed to just *id, type, status* — useful in narrow side-panel layouts.

### Related

* [#transaction-record](#transaction-record) — The container this block lives inside.
* [#transaction-search](#transaction-search) — The block that loads the parent transaction.

## Return Lines

The core return-item editor. Return Lines shows the items from the original order (loaded by the **Original Transaction Lookup** block) and lets the user select which ones to return and in what quantity.

### Available in

* Return Form modules only

### When to use

Every Return Form module needs a Return Lines block. It is the primary interface for capturing what the customer is returning.

### Before you start

Place an **Original Transaction Lookup** block above Return Lines on the page. Return Lines reads its items from the transaction loaded by the lookup — without a resolved lookup, the block shows no items.

### Settings

| Setting                | Description                                                                                                                                                                                                                                                                |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Columns**            | Which built-in columns to show — item name, quantity sold, quantity already returned, quantity available, return quantity, rate, amount, reason, restock, UOM, and inventory detail. Custom columns can be added via the Columns tab. Column labels are also customisable. |
| **Show Reason Column** | When on, a reason field appears on every return line. Return reason codes are configured in the **Return Form module settings**, not in this block.                                                                                                                        |
| **PIN Gate**           | When on, certain columns (Return Qty, Restock, and any custom columns marked as protected) require a manager PIN before the operator can edit them. Each cell unlocks individually on PIN entry.                                                                           |
| **Scan Strip**         | When on, users can scan a product barcode to increment the return quantity for the matching line item.                                                                                                                                                                     |

### How it works

1. The block waits for the **Original Transaction Lookup** to resolve with a selected transaction.
2. Once a transaction is loaded, Return Lines displays its line items.
3. The user checks the items to return and sets return quantities.
4. If the **Reason Column** is enabled, a reason field appears on every return line.
5. If **PIN Gate** is on, editing a protected column (Return Qty, Restock, or a custom protected column) opens a PIN prompt for that cell.
6. The selected items, quantities, and reasons are passed automatically to the **Checkout Payment** and **Refund Summary** blocks.

### Common issues

* **No items shown** — the Original Transaction Lookup hasn't resolved yet. Confirm it is placed above Return Lines and that a transaction has been selected.
* **Reason column not showing** — the Show Reason Column setting isn't enabled in the block settings.
* **PIN prompt doesn't appear when editing a cell** — PIN Gate isn't enabled, or the column you're trying to edit isn't marked as protected.

### Related

* [#original-transaction-lookup](#original-transaction-lookup) — Loads the order — must be placed above Return Lines.
* [#checkout-payment](#checkout-payment) — Routes to payment or refund based on the return net value.
* [Workflow Examples](/client-admin-guide/workflow-builder-overview/workflow-examples/return-form-module.md) — Return Form module: How all return blocks fit together.

## Original Transaction Lookup

The starting block for a return workflow. Original Transaction Lookup lets users enter a transaction reference — an order number, invoice number, or custom order ID — and load the original transaction into the return form.

Once the transaction is loaded, the lookup feeds it automatically into the **Return Lines** block below.

### Available in

* Return Form modules only

### When to use

Place this as the first block on a Return Form module page. Without it, Return Lines and the rest of the return flow have no data to work with.

### Settings

| Setting                 | Description                                                                                                                                                                      |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Field label**         | Text displayed above the input field.                                                                                                                                            |
| **Placeholder**         | Hint text shown inside the input when empty.                                                                                                                                     |
| **Helper text**         | Additional explanation shown below the input (visible in the editor only).                                                                                                       |
| **If already returned** | What to do when the transaction has a prior return on file: *Warn* (load the transaction but show a warning banner) or *Block* (reject the lookup with an error). Default: Warn. |

### How it works

1. The user enters a transaction reference (order number, invoice number, or custom order ID).
2. The user clicks the **Lookup** button (or presses Enter).
3. If the transaction is found and eligible, a summary card appears showing the record type, status, and whether it has been paid and fulfilled.
4. The loaded transaction feeds automatically into the **Return Lines** block.

### Prior return detection

If the transaction already has a return on file (a return authorisation or cash refund), the lookup detects it. What happens next depends on the **If already returned** setting:

* **Warn** — Load the transaction, but display a warning banner identifying the prior return and its status. Use this when re-returns are allowed in your workflow.
* **Block** — Reject the lookup with an error message. Use this when duplicate returns should never be allowed.

### Return eligibility

Not every transaction can be returned. The lookup enforces eligibility automatically before loading:

* **Cash Sales** — always eligible.
* **Invoices** — must be paid in full.
* **Sales Orders** — must be billed, and the resulting invoice must be paid in full.

If a transaction isn't eligible, the block shows a plain-language reason (for example, *Invoice INV-123 is not paid in full*) and does not load it.

### Common issues

* **"Not found" error** — the reference doesn't match any transaction. Double-check the order number or try the invoice number.
* **Transaction blocked as ineligible** — the transaction doesn't meet the eligibility rules above. Verify the invoice is paid in NetSuite before retrying.
* **Prior return warning appears** — a return already exists for this transaction. Confirm whether this is expected, or change **If already returned** to *Block* to prevent re-returns.
* **Return Lines stays empty after a successful lookup** — confirm Return Lines is placed below this block on the same page.

### Related

* [#return-lines](#return-lines) — Line-item selection — reads the transaction loaded here.
* [Workflow Examples](/client-admin-guide/workflow-builder-overview/workflow-examples/return-form-module.md) — Return Form module: How all return blocks fit together.

## Refund Payments

Handles the refund transaction on a return. Refund Payments is connected to the **Checkout Payment** block's refund slot — it activates when the return net calculation determines a refund is due to the customer.

### Available in

* Return Form modules only

### When to use

Add Refund Payments to your Return Form whenever a straight return or exchange can result in money back to the customer. Connect it to the **Refund Slot** in the **Checkout Payment** block.

If your return form handles only even exchanges with no cash refunds, you can omit this block.

### Settings

| Setting                                | Description                                                                                                                                                                                                               |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Title**                              | Heading text for the block. Default: *Refund*.                                                                                                                                                                            |
| **Helper text**                        | Descriptive copy shown above the refund method tiles.                                                                                                                                                                     |
| **Allow refund to a different method** | When off (default), the cashier can only refund to the original payment method. Turn on to allow Cash, Check, or other methods regardless of how the original transaction was paid.                                       |
| **NetSuite payment methods**           | When *Allow refund to a different method* is on, select which NetSuite payment methods appear as tiles (e.g. Cash, Check, other configured methods).                                                                      |
| **Enable Credit Memo only**            | Adds a *Credit Memo* tile that issues a credit memo without firing a separate refund record — useful for store account credit without a cash disbursement.                                                                |
| **Enable Gift Certificate**            | Adds a *Gift Certificate* tile. Requires selecting a gift-certificate item via a SuiteQL search; that item is used to generate the certificate.                                                                           |
| **Require PIN for large refunds**      | When on, any refund at or above the configured threshold opens a PIN authorization prompt before processing. Set the threshold amount and choose which employees can authorize (all, specific users, or a SuiteQL query). |

**Refund method tiles available at runtime** depend on the configuration and context:

* **Original payment method** — one tile per tender from the original transaction. Disabled if the processor requires a terminal and no register is currently active.
* **All original payments (proportional split)** — appears when the original transaction had two or more tenders. Splits the refund proportionally across all tenders.
* **Store Credit** — appears automatically when the customer has a store credit balance greater than zero. Shows the available balance.
* **Cash / Check / custom methods** — appear when *Allow refund to a different method* is on and the relevant methods are selected in settings.
* **Credit Memo** — appears when *Enable Credit Memo only* is on.
* **Gift Certificate** — appears when *Enable Gift Certificate* is on.

### How it works

1. **Checkout Payment** activates Refund Payments when the return net is negative (refund due).
2. Refund Payments displays the total refund amount and the available refund method tiles.
3. The cashier selects a refund method and confirms the amount.
4. For large refunds (when the PIN gate is configured), the cashier enters an authorization PIN before the refund is processed.
5. The refund is submitted to NetSuite.
6. The result is passed to the **Refund Summary** block for the confirmation screen.

{% hint style="warning" %}
Refunding to the original payment method via terminal (Datacap, Fortis) requires an active register. If no register is active, the original-payment tiles are disabled with an explanation. Use *Cash*, *Credit Memo*, or another non-terminal method as a fallback.
{% endhint %}

### Common issues

* **Block doesn't activate** — Checkout Payment calculated a positive or zero net (customer owes money or it's an even exchange). Check the return lines and any exchange items.
* **Original payment method tile is disabled** — the processor requires a terminal and no register is currently active. Use Cash, Credit Memo, or Store Credit instead.
* **Store Credit tile not showing** — the customer has no store credit balance. The tile only appears when balance is greater than zero.
* **Gift Certificate tile missing** — Enable Gift Certificate isn't turned on, or no gift-certificate item has been selected in settings.

### Related

* [#checkout-payment](#checkout-payment) — The routing block that activates Refund Payments.
* [#refund-summary](#refund-summary) — The confirmation screen that follows Refund Payments.
* [Workflow Examples](/client-admin-guide/workflow-builder-overview/workflow-examples/return-form-module.md) — Return Form module: How all return blocks fit together.

## Refund Summary

The final step of a return flow. Refund Summary displays a confirmation once the return is complete — the items returned, the total refund or exchange net, and an optional receipt.

### Available in

* Return Form modules only

### When to use

Place Refund Summary as the last block on a Return Form module page. It reads the return outcome — items returned, amounts, payment or refund result — and presents it as a clean confirmation for both staff and customers.

### Settings

| Setting    | Description                                                                                                          |
| ---------- | -------------------------------------------------------------------------------------------------------------------- |
| **Title**  | Custom text displayed at the top of the summary. Default: *Refund summary*.                                          |
| **Layout** | Display orientation — *Vertical* (one stat per row, stacked) or *Horizontal* (multi-column grid). Default: Vertical. |

{% hint style="info" %}
Receipt preview and print buttons are configured in the **Return Form module settings** (Receipt tab), not on this block. When enabled in module settings, the buttons appear here automatically.
{% endhint %}

### How it works

1. Once the return transaction completes — through Return Lines → Checkout Payment → Refund Payments (or even-exchange path) — the summary collects the outcome.
2. It always shows the returned items, refund subtotal, tax, and total. These sections are not toggleable.
3. If the return included outbound exchange items, the summary also shows the exchange items total, exchange tax, and the net result: **Amount due**, **Refund due**, or **Even exchange**.
4. If receipt buttons are enabled in Return Form module settings, **Preview** and **Print** buttons appear. Both are disabled until at least one item has been returned.
5. In queue-mode returns, the receipt renders from the current return snapshot (items, amounts, allocations) rather than from a submitted NetSuite record — since the refund record ID isn't available until the queue processes.

### Common issues

* **Summary shows no items** — Return Lines didn't resolve or no items were selected. Confirm the return was completed before this block rendered.
* **Refund amount shows $0 after a cash refund** — the Refund Payments block may not have submitted yet. Confirm the cashier completed the Refund Payments step.
* **Preview / Print buttons are greyed out** — no items have been returned yet. The buttons enable only once at least one return line is confirmed.
* **Print buttons don't appear at all** — receipt printing isn't enabled. Turn it on in the Return Form module settings under the Receipt tab.

### Related

* [#checkout-payment](#checkout-payment) — Routes to payment or refund — Refund Summary reads the outcome.
* [#refund-payments](#refund-payments) — The refund-path block whose result appears here.
* [Workflow Examples](/client-admin-guide/workflow-builder-overview/workflow-examples/return-form-module.md) — Return Form module: The complete return flow doc.

## Checkout Payment

The routing block for return and exchange forms. Based on the net value of the return, Checkout Payment automatically sends the transaction to the right outcome:

* Customer **owes money** (exchange where new items cost more than what they returned) → activates the **payment path**.
* Customer **is owed a refund** (straight return, or exchange where returned items are worth more) → activates the **refund path**.
* **Even exchange** — no money changes hands → bypasses both paths and completes the transaction.

{% hint style="warning" %}
Checkout Payment is only available inside **Return Form** modules. It does not appear in the block palette for other module types.
{% endhint %}

### Available in

* Return Form modules only

### When to use

Include Checkout Payment in every Return Form that can result in money moving — either a refund to the customer or an additional charge for an exchange. If your return flow always results in an even exchange (no money changes hands), you can omit it.

### Settings

| Setting                 | Description                                                                                                     |
| ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| **Payment Slot**        | The block that handles the case where the customer owes additional money. Connect your **Payments** block here. |
| **Refund Slot**         | The block that handles the refund case. Connect a **Refund Payments** block here.                               |
| **Even Exchange Label** | Text shown when the exchange is even and no money changes hands. Default: *Complete exchange*.                  |

### How it works

1. The block reads the net value from the **Return Lines** block (new items added minus the value of items returned).
2. If the net is **positive** (customer owes money): activates the Payment Slot.
3. If the net is **negative** (refund due): activates the Refund Slot.
4. If the net is **zero**: bypasses both slots and shows the even-exchange confirmation.

The three routing paths (payment / refund / even exchange) only apply when the return includes outbound exchange items. For a straight return with no exchange items, the block always routes to the Refund Slot regardless of the net value.

If no net value is available (Return Lines hasn't resolved), Checkout Payment shows neither slot and waits.

### Common issues

* **Checkout Payment shows nothing** — Return Lines hasn't resolved, or no items have been selected for return. Confirm Return Lines is placed above Checkout Payment and items are checked.
* **Refund path never activates** — check that a Refund Payments block is connected to the Refund Slot. Without it, the refund path has nowhere to go.
* **Payment path activates unexpectedly** — an exchange item with a high value may have been added unintentionally, pushing the net positive.

### Related

* [#refund-payments](#refund-payments) — The refund-path block that connects to the Refund Slot.
* [#return-lines](#return-lines) — Provides the net value Checkout Payment uses to route.
* [Workflow Examples](/client-admin-guide/workflow-builder-overview/workflow-examples/return-form-module.md) — Return Form module: The complete return flow doc.

## Standalone Payment Mode

Standalone Payment Mode is a setting on the Payments block that lets you collect a payment from a customer without an active order or cart. Instead of paying for items in a transaction, the payment is recorded as an unapplied customer payment in NetSuite—useful for deposits, advance payments, or account credits.

### When you'd use it

* Taking a deposit before an order is created.
* Collecting an advance payment or retainer from a customer.
* Recording a customer payment toward their account balance.
* Processing a payment outside a normal POS workflow.

### Before you start

* **Who can do this:** Client admins who can edit page layouts and configure the Payments block.
* **What you need:** The Payments block must be on your page (Order Form or Return Form module).
* **Customer field required:** The page must have a Customer/Vendor Selection field above the Payments block. Customers must select themselves before a payment can be taken.

### Step by step

#### Enable Standalone Payment Mode

1. Open your page in the Page Builder and locate the **Payments block**.
2. Click the block to select it, then click the **Settings** (gear) icon.
3. In the panel on the right, click **Payment Configuration**.
4. A modal opens showing configuration options. Scroll to the **Payment Mode** section.
5. Select **Standalone payment** from the dropdown (the default is "Order summary").
6. Review the other settings on this modal:
   * **Payment Methods** — which tenders to accept (Cash, Card, Gift Card, etc.). These come from your subsidiary's Payment Settings.
   * **Card Processors** — if you want to accept credit cards, make sure your processor is enabled in Payment Settings at the subsidiary level.
   * **Click to pay** — optional; when on, tapping a tender button goes straight to payment (skips amount entry).
   * **Receipt settings** — whether to show a receipt after payment.
7. Click **Save** to apply the changes.

### What happens in Standalone Payment Mode

When a customer opens the form with Standalone Payment Mode enabled:

1. The Summary block does not appear (there's no cart to summarize).
2. The customer selects or confirms their name in the **Customer** field.
3. They tap **Pay** or a specific tender button.
4. A modal appears asking for the **payment amount**. They enter the amount (e.g., $50 deposit).
5. For card payments, they tap the card reader or terminal. For cash, they hand over the money.
6. The payment is recorded immediately as an unapplied customer payment in NetSuite.
7. A confirmation screen appears, and the form resets for the next customer.

There is no order created and no line items — only the payment record.

### What success looks like

* The customer enters a payment amount and the payment method (cash or card).
* The payment submits immediately on confirmation.
* The form shows a success screen and resets for the next transaction.
* In NetSuite, a new **Customer Payment** record appears on that customer's account with the status "Unapplied."

### Common issues

**The Payments block won't save:** Check that a **Customer/Vendor Selection field** is on the page above the Payments block. Standalone mode requires one.

**"Customer required" error appears:** The customer field is empty. Ask the user to select or confirm their name before proceeding.

**Payment doesn't process for card:** Verify that your card processor (Fortis, 8Q, Datacap) is enabled in **Payment Settings** at the subsidiary level, and that the card method is assigned to that processor.

### Related

* [#payments](#payments) — The main payment collection interface; Standalone Mode is one of its operating modes.
* [NetSuite Admin Guide](/netsuite-admin-guide/overview-1/payment-settings.md) — Payment Settings: Where you configure payment processors and methods at the subsidiary level.
* [Entity Components](/client-admin-guide/getting-started/entity-components.md) — Customer/Vendor Selection: The field that collects the customer name; required on any page using Standalone Payment Mode.

## Related

<table data-view="cards"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Cashier Workflow</strong></td><td>The canonical Order Form layout that uses these blocks.</td><td><a href="/client-admin-guide/workflow-builder-overview/workflow-examples/cashier-workflow.md">Cashier Workflow</a></td></tr><tr><td><strong>Entity Components</strong></td><td>Customer/Vendor Selection and other entity-aware blocks for Order Forms.</td><td><a href="/client-admin-guide/getting-started/entity-components.md">Entity Components</a></td></tr><tr><td><strong>PIN Override</strong></td><td>How discount, void, and submit can require manager PIN.</td><td><a href="/client-admin-guide/workflow-builder-overview/pin-override.md">PIN Override</a></td></tr></tbody></table>
