The definitive template for building GFS NetSuite portals, suitelets, dashboards, and operational tools.
Every pattern needed for production NetSuite development -- suitelet page layouts, record forms, saved search displays, dashboard portlets, approval workflows, print templates, email templates, SuiteQL queries, and SuiteScript patterns. Copy directly into your Suitelet.
Click any sidebar item to navigate. Sub-menus expand on click. The breadcrumb and title update dynamically.
■ Sidebar collapses to horizontal on mobile (< 768px). Active item uses inset border-left accent. Sub-menus toggle on click.
03Record FormComplete NetSuite record entry form with validation, line items, and action bar
■ Form validates required fields on submit. "Add Line" appends a new row. All fields use .ns- prefixed classes. Currency fields right-aligned with Plex Mono.
04Record List ViewNetSuite saved search / record list with filters, sorting, pagination, and bulk actions
10 results
Doc # ↕
Date ↕
Entity ↕
Amount ↕
Status
Memo
Actions
SO-24891
05/20/2026
Driscoll Foods
$46,642.49
Pending Fulfillment
Weekly dairy standing order
SO-24890
05/19/2026
Sysco Northeast
$32,180.50
Billed
Frozen foods reorder
SO-24889
05/19/2026
US Foods Philadelphia
$27,445.00
Fulfilled
Deli meats order #3
SO-24888
05/18/2026
Restaurant Depot NYC
$19,830.75
Partially Fulfilled
Cheese blocks multi-ship
PO-10447
05/18/2026
Bongards Creameries
$84,200.00
Open
Barrel cheddar 640# x 30
INV-18842
05/17/2026
FreshMart Distribution
$15,620.00
Billed
Monthly invoice - May
SO-24887
05/17/2026
Baldor Specialty Foods
$42,910.25
Credit Hold
Exceeds credit limit
SO-24886
05/16/2026
Performance Food Group
$56,340.00
Pending Fulfillment
Private label co-pack
PO-10446
05/16/2026
Land O'Lakes
$28,750.00
Closed
Butter 25# blocks received
INV-18841
05/15/2026
Jetro Cash & Carry
$8,775.50
Billed
COD - paid on delivery
Last exported: 05/19/2026 14:30
Saved Filter Presets
Row Expansion for Detail View
Doc #
Date
Entity
Amount
Status
SO-24891
05/20/2026
Driscoll Foods
$46,642.49
Pending Fulfillment
Order Details
PO#: PO-DF-2026-0547 Terms: Net 30 Rep: Mike Reynolds Dept: Dairy & Cheese
Ship To
Driscoll Foods - Warehouse 1 Distribution Way Mount Vernon, NY 10550
Line Items (4)
Barrel Cheddar 640# x12 Process American 5# x200 Mozzarella LMPS 6# x150 Pepper Jack 40# x24
SO-24890
05/19/2026
Sysco Northeast
$32,180.50
Billed
Order Details
PO#: PO-SYS-2026-1184 Terms: Net 60 Rep: Sarah Chen Dept: Frozen Foods
Ship To
Sysco NE Distribution 14 Sysco Court Front Royal, VA 22630
■ Click column headers to sort. Select All checkbox toggles all rows. Hover rows to reveal action buttons. Pagination and page size are configurable. Row expansion shows detail without navigation. Inline editing highlights modified cells in alice blue.
05Dashboard Portlet GridNetSuite dashboard with KPI, chart, list, and reminder portlets
■ Portal login is centered card with cobalt header. Quick actions use 4-col grid. Document downloads link to file cabinet. Support ticket submits to case record.
08NetSuite Print TemplatesInvoice, Packing Slip, Purchase Order, and Bill of Lading HTML print templates
Invoice
Packing Slip
Purchase Order
Bill of Lading
GLOBAL FOOD SOLUTIONS, INC.
131 Heartland Blvd, Edgewood, NY 11717 (877) 728-5550 | globalfoodsolutions.co
INVOICE
#INV-18842
Date: 05/17/2026Due: 06/16/2026Terms: Net 30Rep: Mike Reynolds
Bill To
FreshMart Distribution 450 Commerce Dr Edison, NJ 08817
Ship To
FreshMart Warehouse #2 450 Commerce Dr, Dock B Edison, NJ 08817
Item
Description
Qty
Rate
Amount
GFS-4420
Barrel Cheddar 640#
4
$2,847.50
$11,390.00
GFS-2210
Process American 5# Loaf
80
$14.25
$1,140.00
GFS-3310
Mozzarella LMPS 6#
60
$18.90
$1,134.00
Subtotal$13,664.00
Tax (8.625%)$1,178.02
Shipping$778.00
Total Due$15,620.02
Payment Terms: Net 30 from invoice date. Late payments subject to 1.5% monthly finance charge. Make checks payable to Global Food Solutions, Inc. For ACH/Wire: Chase Bank, ABA 021000021, Acct 8847291034.
GLOBAL FOOD SOLUTIONS, INC.
131 Heartland Blvd, Edgewood, NY 11717
PACKING SLIP
IF-7724 (SO-24891)
Ship From
GFS Warehouse 131 Heartland Blvd Edgewood, NY 11717
Ship To
Driscoll Foods - Warehouse 1 Distribution Way Mount Vernon, NY 10550
GFS Warehouse - Dock 2 131 Heartland Blvd Edgewood, NY 11717
Date: 05/18/2026 | Expected: 05/25/2026 | Terms: Net 30 | Buyer: M. Levine
Item
Description
Qty
Rate
Amount
BC-640
Barrel Cheddar 640# - CME+0.0350
30
$2,806.67
$84,200.00
Total$84,200.00
Delivery Instructions: Refrigerated truck required. Maintain 34-38F. Deliver to Dock 2. Call (631) 555-0142 30 minutes prior to arrival. All product must include lot numbers and production dates on case labels.
BILL OF LADING
Straight / Non-Negotiable
BOL-8847
Date: 05/20/2026
Shipper
Global Food Solutions, Inc. 131 Heartland Blvd Edgewood, NY 11717
Consignee
Driscoll Foods 1 Distribution Way Mount Vernon, NY 10550
Carrier: Heartland Express
PRO #: PRO-4830012
Trailer #: HE-47291
Seal #: S-88471
Pieces
Description
Weight (lbs)
Class
Temp Req
12
Barrel Cheddar 640#
7,680
85
34-38F
200
Process American 5# Loaf
1,000
85
34-38F
150
Mozzarella LMPS 6#
900
85
34-38F
24
Pepper Jack 40# Block
960
85
34-38F
Total Pieces: 386
Total Weight: 10,540 lbs
■ Print templates use @media print styles for proper margins and page breaks. Each includes 3px cobalt top border, company header, and structured layout.
09Email TemplatesOrder confirmation, invoice, shipping notification, and past due reminder email patterns
Order Confirmation
Invoice
Shipping
Past Due
■ GLOBAL FOOD SOLUTIONS
Dear Dave Jordan,
Thank you for your order. We have received SO-24891 and it is being processed. Below is a summary:
Order #: SO-24891 Date: May 20, 2026 Items: 4 line items Total: $46,642.49 Terms: Net 30 Est. Ship: May 22, 2026
Outstanding purchase orders grouped by vendor with ETA
Daily
Sales by Rep - MTD
Month-to-date sales totals by sales rep
Weekly
Margin Analysis by Item
Cost vs. revenue per item with margin percentage
Monthly
Credit Hold Customers
Customers currently on credit hold with outstanding balance
Daily
Lot Traceability
Trace lot numbers from vendor receipt through customer shipment
On demand
Production GFS Queries with Field IDs
Top 20 Customers by YTD Revenue
SELECT
e.companyname AS "Customer",
e.id AS "Internal ID",
SUM(tl.netamount) AS "YTD Revenue",
COUNT(DISTINCT t.id) AS "Order Count",
ROUND(AVG(tl.netamount), 2) AS "Avg Line Amount"
FROM transaction t
JOIN transactionline tl ON t.id = tl.transaction
JOIN entity e ON t.entity = e.id
WHERE t.type = 'SalesOrd'
AND t.trandate >= TO_DATE('2026-01-01','YYYY-MM-DD')
AND tl.mainline = 'F'
AND tl.itemtype != 'Discount'
GROUP BY e.companyname, e.id
ORDER BY "YTD Revenue" DESC
FETCH FIRST 20 ROWS ONLY
AR Aging by Bucket (30/60/90/120)
SELECT
e.companyname AS "Customer",
SUM(CASE WHEN CURRENT_DATE - t.duedate BETWEEN 1 AND 30 THEN t.foreignamountremaining ELSE 0 END) AS "1-30",
SUM(CASE WHEN CURRENT_DATE - t.duedate BETWEEN 31 AND 60 THEN t.foreignamountremaining ELSE 0 END) AS "31-60",
SUM(CASE WHEN CURRENT_DATE - t.duedate BETWEEN 61 AND 90 THEN t.foreignamountremaining ELSE 0 END) AS "61-90",
SUM(CASE WHEN CURRENT_DATE - t.duedate > 90 THEN t.foreignamountremaining ELSE 0 END) AS "90+",
SUM(t.foreignamountremaining) AS "Total AR"
FROM transaction t
JOIN entity e ON t.entity = e.id
WHERE t.type = 'CustInvc'
AND t.status = 'CustInvc:A' -- Open
AND t.foreignamountremaining > 0
GROUP BY e.companyname
ORDER BY "Total AR" DESC
JOIN Pattern: Transaction + Line + Item
SELECT
t.tranid AS "Doc #",
t.trandate AS "Date",
BUILTIN.DF(t.entity) AS "Customer",
i.itemid AS "Item",
i.displayname AS "Description",
tl.quantity AS "Qty",
tl.rate AS "Rate",
tl.netamount AS "Amount",
tl.custcol_gfs_lot AS "Lot #",
tl.custcol_gfs_temp AS "Temp F"
FROM transaction t
JOIN transactionline tl ON t.id = tl.transaction
JOIN item i ON tl.item = i.id
WHERE t.type = 'SalesOrd'
AND tl.mainline = 'F'
AND t.trandate >= TO_DATE('2026-05-01','YYYY-MM-DD')
ORDER BY t.trandate DESC, tl.linesequencenumber ASC
Aggregate: Revenue by Brand (custbody_gfs_brand)
SELECT
BUILTIN.DF(t.custbody_gfs_brand) AS "Brand",
COUNT(DISTINCT t.id) AS "Orders",
SUM(tl.netamount) AS "Revenue",
ROUND(SUM(tl.netamount) / NULLIF(SUM(SUM(tl.netamount)) OVER (), 0) * 100, 1) AS "% of Total"
FROM transaction t
JOIN transactionline tl ON t.id = tl.transaction
WHERE t.type IN ('SalesOrd','CustInvc')
AND tl.mainline = 'F'
AND t.trandate >= TO_DATE('2026-01-01','YYYY-MM-DD')
GROUP BY BUILTIN.DF(t.custbody_gfs_brand)
ORDER BY "Revenue" DESC
Date Functions: Monthly Trend with BUILTIN.DF
SELECT
TO_CHAR(t.trandate, 'YYYY-MM') AS "Month",
COUNT(*) AS "Transactions",
SUM(t.foreigntotal) AS "Total Revenue",
ROUND(AVG(t.foreigntotal), 2) AS "Avg Order Value"
FROM transaction t
WHERE t.type = 'SalesOrd'
AND t.trandate >= ADD_MONTHS(CURRENT_DATE, -12)
AND t.trandate < CURRENT_DATE
GROUP BY TO_CHAR(t.trandate, 'YYYY-MM')
ORDER BY "Month" DESC
CASE WHEN: Classify Orders by Size
SELECT
t.tranid AS "Doc #",
BUILTIN.DF(t.entity) AS "Customer",
t.foreigntotal AS "Total",
CASE
WHEN t.foreigntotal >= 50000 THEN 'LARGE'
WHEN t.foreigntotal >= 25000 THEN 'MEDIUM'
WHEN t.foreigntotal >= 5000 THEN 'STANDARD'
ELSE 'SMALL'
END AS "Order Tier",
CASE
WHEN t.custbody_gfs_temp_zone = 1 THEN 'Refrigerated'
WHEN t.custbody_gfs_temp_zone = 2 THEN 'Frozen'
WHEN t.custbody_gfs_temp_zone = 3 THEN 'Ambient'
ELSE 'Unknown'
END AS "Temp Zone"
FROM transaction t
WHERE t.type = 'SalesOrd'
AND t.trandate >= TO_DATE('2026-05-01','YYYY-MM-DD')
ORDER BY t.foreigntotal DESC
Inventory Below Reorder Point
SELECT
i.itemid AS "Item ID",
i.displayname AS "Item Name",
ib.quantityavailable AS "Available",
ib.quantityonhand AS "On Hand",
ib.quantityonorder AS "On Order",
i.reorderpoint AS "Reorder Point",
i.preferredstocklevel AS "Preferred Level",
(i.reorderpoint - ib.quantityavailable) AS "Shortfall"
FROM item i
JOIN inventorybalance ib ON i.id = ib.item
WHERE i.isinactive = 'F'
AND ib.quantityavailable < i.reorderpoint
AND i.reorderpoint IS NOT NULL
ORDER BY "Shortfall" DESC
Vendor Scorecard: Delivery Performance
SELECT
BUILTIN.DF(t.entity) AS "Vendor",
COUNT(*) AS "Total POs",
SUM(CASE WHEN ir.trandate <= t.expectedreceiptdate THEN 1 ELSE 0 END) AS "On Time",
ROUND(SUM(CASE WHEN ir.trandate <= t.expectedreceiptdate THEN 1 ELSE 0 END) * 100.0 / COUNT(*), 1) AS "OTD %",
SUM(t.foreigntotal) AS "Total Spend"
FROM transaction t
LEFT JOIN transaction ir ON ir.createdfrom = t.id AND ir.type = 'ItemRcpt'
WHERE t.type = 'PurchOrd'
AND t.trandate >= TO_DATE('2026-01-01','YYYY-MM-DD')
GROUP BY BUILTIN.DF(t.entity)
HAVING COUNT(*) >= 3
ORDER BY "OTD %" ASC
Lot Traceability: Receipt to Shipment
SELECT
il.inventorynumber AS "Lot #",
i.itemid AS "Item",
-- Receipt info
po.tranid AS "PO #",
BUILTIN.DF(po.entity) AS "Vendor",
ir.trandate AS "Received Date",
-- Shipment info
so.tranid AS "SO #",
BUILTIN.DF(so.entity) AS "Customer",
ifull.trandate AS "Ship Date"
FROM inventorynumber il
JOIN item i ON il.item = i.id
LEFT JOIN transactionline rl ON rl.item = i.id
LEFT JOIN transaction ir ON rl.transaction = ir.id AND ir.type = 'ItemRcpt'
LEFT JOIN transaction po ON ir.createdfrom = po.id
LEFT JOIN transactionline sl ON sl.item = i.id
LEFT JOIN transaction ifull ON sl.transaction = ifull.id AND ifull.type = 'ItemShip'
LEFT JOIN transaction so ON ifull.createdfrom = so.id
WHERE il.inventorynumber = 'LOT-BC-0520A'
ORDER BY ir.trandate ASC
Margin Analysis by Item
SELECT
i.itemid AS "Item ID",
i.displayname AS "Description",
SUM(tl.quantity) AS "Units Sold",
SUM(tl.netamount) AS "Revenue",
SUM(tl.costestimate) AS "COGS",
SUM(tl.netamount) - SUM(tl.costestimate) AS "Gross Profit",
ROUND((SUM(tl.netamount) - SUM(tl.costestimate)) / NULLIF(SUM(tl.netamount), 0) * 100, 1) AS "Margin %"
FROM transaction t
JOIN transactionline tl ON t.id = tl.transaction
JOIN item i ON tl.item = i.id
WHERE t.type = 'CustInvc'
AND tl.mainline = 'F'
AND t.trandate >= TO_DATE('2026-01-01','YYYY-MM-DD')
GROUP BY i.itemid, i.displayname
HAVING SUM(tl.netamount) > 0
ORDER BY "Margin %" ASC
■ SuiteQL editor runs query on button click. Results display in standard .ns-table. Export CSV extracts table data. All queries use SuiteQL 2.0 syntax. JOIN patterns show transaction+line+item relationships. CASE WHEN enables classification logic.
11Script Patterns & UtilitiesSuiteScript 2.x entry point patterns, client scripts, RESTlets, Map/Reduce, and GFS utilities
■ Click "Copy" on any snippet to copy to clipboard. Paste directly into NetSuite Suitelet HTML or SuiteScript file. All use GFS .ns- class conventions.
13NetSuite Field ReferenceComplete field mapping reference for transactions, entities, items, and addresses
Defaults from item. Can override for custom descriptions
units
List/Record
Units
N
Unit of measure: Each, Case, Pallet, Lb
price
List/Record
Price Level
N
Base Price, Contract, Volume Discount, Promotional
costestimate
Currency
Est. Cost
N
System-calculated COGS estimate. Used for margin analysis
custcol_gfs_lot
Text
Lot Number
N
Lot assignment. Format: LOT-XX-MMDD[A-Z]. Required for USDA items
custcol_gfs_temp
Decimal
Temperature (F)
N
Recorded temperature at pick. Validated against zone requirements
custcol_gfs_weight
Decimal
Actual Weight (lbs)
N
Actual weight for catch-weight items. Used for billing adjustment
custcol_gfs_expiry
Date
Expiration Date
N
Product expiration. Alerts if < 30 days remaining at ship
custcol_gfs_production_date
Date
Production Date
N
Manufacturing date. Used for FIFO allocation
grossamt
Currency
Gross Amount
N
Amount before discounts. Used in rebate calculations
lineuniquekey
Integer
Line Unique Key
N
System-generated. Stable reference for line modifications
isclosed
Checkbox
Closed
N
Close individual lines. Prevents further fulfillment
Address Fields (addressbook subrecord)
Internal ID
Type
Label
Req
GFS Usage Notes
addr1
Text
Address Line 1
Y
Street address. Required for all shipping/billing
addr2
Text
Address Line 2
N
Suite, dock number, building. Include dock # for deliveries
city
Text
City
Y
City name for tax jurisdiction determination
state
List/Record
State
Y
Two-letter code. Drives tax calculation and compliance
zip
Text
Zip Code
Y
5 or 9 digit. Used for route planning and tax nexus
country
List/Record
Country
Y
_unitedStates default. Triggers export docs if international
attention
Text
Attention
N
Contact name at delivery location
addressee
Text
Addressee
N
Company name for delivery label
phone
Phone
Phone
N
Delivery contact phone. Required for refrigerated shipments
Entity Fields (Customer/Vendor)
Internal ID
Type
Label
Req
GFS Usage Notes
companyname
Text
Company Name
Y
Legal entity name. Appears on invoices and legal docs
email
Email
Email
N
Primary contact email. Used for order confirmations
phone
Phone
Phone
N
Main phone. Format: (XXX) XXX-XXXX
category
List/Record
Category
N
Distributor, Restaurant, Retail, Institutional, Government
terms
List/Record
Terms
N
Default payment terms. Inherited by new transactions
creditlimit
Currency
Credit Limit
N
Maximum AR balance. Triggers credit hold when exceeded
balance
Currency
Balance
N
Current AR balance. System-calculated
overduebalance
Currency
Overdue Balance
N
Past-due AR. Used in dunning workflow
custentity_gfs_tier
List/Record
Customer Tier
N
Platinum, Gold, Silver, Bronze. Drives pricing and priority
custentity_gfs_buyer
Text
Primary Buyer
N
Buyer contact name for order communications
custentity_gfs_license
Text
License Number
N
USDA/FDA facility license. Required for compliance
Item Fields
Internal ID
Type
Label
Req
GFS Usage Notes
itemid
Text
Name/Number
Y
GFS item code. Format: GFS-XXXX (e.g., GFS-4420)
displayname
Text
Display Name
N
Friendly name: "Barrel Cheddar 640#"
salesdescription
Text
Sales Description
N
Description for invoices and quotes
purchasedescription
Text
Purchase Description
N
Description for purchase orders to vendors
cost
Currency
Cost
N
Average, FIFO, or standard cost depending on method
baseprice
Currency
Base Price
N
Default selling price. Price level 1
weight
Decimal
Weight
N
Shipping weight in lbs. Used for BOL and freight calculations
reorderpoint
Integer
Reorder Point
N
Minimum stock level before reorder alert triggers
custitem_gfs_shelf_life
Integer
Shelf Life (days)
N
Product shelf life in days from production
custitem_gfs_case_count
Integer
Case Count
N
Units per case. Used for pallet calculations
custitem_gfs_temp_req
List/Record
Temp Requirement
Y
Storage/transport temperature zone requirement
custitem_gfs_allergens
Multi-Select
Allergens
N
Milk, Soy, Wheat, Eggs, etc. For labeling compliance
■ Field IDs are case-sensitive in SuiteScript. Custom fields use custbody_ (transaction), custcol_ (line), custentity_ (entity), custitem_ (item) prefixes. Required fields validated in beforeSubmit user event.
14Record Type ReferenceEvery NetSuite record type GFS uses with internal IDs, status values, required fields, and workflows
Bill of Materials > Work Order > Assembly Build > Inventory Adjustment
Inventory
Transfer Order > Inventory Adjustment > Inventory Count > Bin Transfer
Financial
Journal Entry > Deposit > Bank Transfer > Intercompany Journal
■ Record type internal IDs are case-sensitive in SuiteScript. Status internal IDs use the format Type:Letter. Use record.Type enum in 2.1 scripts for type-safe references. Transaction cycles flow left-to-right; each step creates from the previous.
15NetSuite Status FlowsVisual status flow diagrams for each transaction type showing progression from creation to close
Sales Order Status Flow
Pending Approval
Pending Fulfillment
Partially Fulfilled
Fulfilled
Pending Billing
Billed
Closed
Purchase Order Status Flow
Pending Supervisor
Pending Receipt
Partially Received
Received
Pending Bill
Billed
Closed
Invoice Status Flow
Open
Paid In Full
Vendor Bill Status Flow
Open
Paid In Full
Work Order Status Flow
Planned
Released
In Process
Built
Closed
Transfer Order Status Flow
Pending Approval
Pending Fulfillment
Partially Fulfilled
Pending Receipt
Received
Closed
Return Authorization Status Flow
Pending Approval
Pending Receipt
Received
Pending Refund
Refunded
Closed
Item Fulfillment Status Flow
Picked
Packed
Shipped
■ Status flows show the standard progression. Records can skip statuses (e.g., direct to Billed). Closed status is terminal -- records cannot be reopened. Use status internal IDs (SalesOrd:B) in search filters and scripts.
16Saved Search Patterns15 essential GFS saved searches with full column/filter definitions and SuiteQL equivalents
1. Open Sales Orders by Customer
Type: Sales Order
Filters:
Status = Pending Fulfillment, Partially Fulfilled, Pending Billing
Date >= beginning of this month
Main Line = F
Columns:
Document Number | Date | Entity | Item | Quantity | Amount | Status | Memo
Sort: Entity (A-Z), Date (newest)
Summary: Group by Entity, SUM Amount
SuiteQL Equivalent:
SELECT BUILTIN.DF(t.entity) AS "Customer", COUNT(*) AS "Orders",
SUM(t.foreigntotal) AS "Total"
FROM transaction t
WHERE t.type = 'SalesOrd'
AND t.status IN ('SalesOrd:B','SalesOrd:D','SalesOrd:C')
GROUP BY BUILTIN.DF(t.entity)
ORDER BY "Total" DESC
2. AR Aging Summary (30/60/90/120)
Type: Invoice
Filters:
Status = Open
Amount Remaining > 0
Main Line = T
Columns:
Entity | Document Number | Due Date | Amount Remaining | Days Overdue
Formula (Numeric): CASE WHEN {daysoverdue} <= 30 THEN {amountremaining} ELSE 0 END -- "1-30"
Formula (Numeric): CASE WHEN {daysoverdue} BETWEEN 31 AND 60 THEN {amountremaining} ELSE 0 END -- "31-60"
Formula (Numeric): CASE WHEN {daysoverdue} BETWEEN 61 AND 90 THEN {amountremaining} ELSE 0 END -- "61-90"
Formula (Numeric): CASE WHEN {daysoverdue} > 90 THEN {amountremaining} ELSE 0 END -- "90+"
Sort: Days Overdue (descending)
Summary: Group by Entity, SUM all amount columns
3. Inventory Below Reorder Point
Type: Item
Filters:
Is Inactive = F
Type = Inventory Item, Assembly
Formula (Numeric): {quantityavailable} < {reorderpoint} -- equals 1
Columns:
Name | Display Name | Quantity Available | Quantity On Hand | Quantity On Order
Reorder Point | Preferred Stock Level
Formula (Numeric): {reorderpoint} - {quantityavailable} -- "Shortfall"
Sort: Shortfall (descending)
Summary: None (detail view)
4. Purchase Orders Pending Receipt
Type: Purchase Order
Filters:
Status = Pending Receipt, Partially Received
Main Line = T
Columns:
Document Number | Date | Vendor | Total | Expected Receipt Date
Formula (Numeric): {expectedreceiptdate} - TODAY -- "Days Until Expected"
Memo
Sort: Expected Receipt Date (ascending)
Summary: Group by Vendor, COUNT, SUM Total
5. Revenue by Brand (custbody_gfs_brand)
Type: Sales Order
Filters:
Date = this year
Main Line = F
Status != Closed, Cancelled
Columns:
custbody_gfs_brand (Group) | Amount (SUM) | Quantity (SUM)
Formula (%): SUM({amount}) / (SELECT SUM({amount}) FROM ...) * 100 -- "% of Total"
Sort: Amount SUM (descending)
Summary: Group by Brand, SUM Amount
6. Top 20 Customers by YTD Revenue
Type: Invoice
Filters:
Date = this year | Status = Open, Paid In Full | Main Line = T
Columns:
Entity (Group) | Amount (SUM) | Document Number (COUNT)
Formula (Numeric): ROUND(SUM({amount}) / [total revenue] * 100, 1) -- "% Share"
Sort: Amount SUM (descending)
Max Results: 20
7. Items Without Activity (90 days)
Type: Item
Filters:
Is Inactive = F | Type = Inventory Item
Formula (Date): NVL({lastquantityavailablechange}, TO_DATE('2000-01-01','YYYY-MM-DD'))
before daysago90
Quantity Available > 0
Columns:
Name | Display Name | Quantity On Hand | Last Sale Date | Location | Cost | Total Value
Sort: Total Value (descending)
8. Credit Holds Report
Type: Customer
Filters:
Credit Hold = On | Is Inactive = F
Columns:
Company Name | Balance | Overdue Balance | Credit Limit
Formula (Numeric): {balance} - {creditlimit} -- "Over Limit By"
Sales Rep | Phone | Email
Sort: Overdue Balance (descending)
9. Open Work Orders by Location
Type: Work Order
Filters:
Status = Planned, Released, In Process
Columns:
Document Number | Assembly Item | Quantity | Location | Status | Start Date
custbody_gfs_priority
Sort: Location (A-Z), Start Date (ascending)
Summary: Group by Location, COUNT
10. Margin Analysis by Item
Type: Invoice
Filters:
Date = this year | Main Line = F | Type = CustInvc
Columns:
Item (Group) | Quantity (SUM) | Amount (SUM) | Cost (SUM)
Formula (Currency): SUM({amount}) - SUM({costestimate}) -- "Gross Profit"
Formula (%): ROUND((SUM({amount}) - SUM({costestimate})) / NULLIF(SUM({amount}),0) * 100, 1) -- "Margin %"
Sort: Margin % (ascending) -- show lowest margins first
11. Lot Traceability Search
Type: Inventory Number
Filters:
Inventory Number contains [search input]
Columns:
Inventory Number | Item | Quantity Available | Quantity On Hand
Status | Expiration Date | custrecord_gfs_vendor_lot | custrecord_gfs_received_date
Join:
Transaction (via inventoryDetail) -> tranid, trandate, type, entity
Sort: Received Date (descending)
12. Temperature Exception Log
Type: Custom Record: Temperature Log (custrecord_gfs_temp_log)
Filters:
custrecord_gfs_temp_status = Exception
Date = last 7 days
Columns:
Date | Location | Item | Lot # | Recorded Temp | Required Range
Deviation | Logged By | Action Taken | Related Transaction
Sort: Date (descending), Deviation (descending)
13. Delivery Performance Scorecard
Type: Item Fulfillment
Filters:
Ship Date = this quarter | Status = Shipped
Columns:
Entity (Group) | COUNT (total shipments)
Formula (Numeric): SUM(CASE WHEN {shipdate} <= {custbody_gfs_promised_date} THEN 1 ELSE 0 END) -- "On Time"
Formula (%): On Time / Total * 100 -- "OTD %"
Formula (Numeric): AVG({shipdate} - {custbody_gfs_promised_date}) -- "Avg Days Late"
Sort: OTD % (ascending) -- show worst performers first
14. Vendor Scorecard
Type: Purchase Order
Filters:
Date = this year | Status = Fully Billed, Closed | Main Line = T
Columns:
Vendor (Group) | COUNT POs | SUM Total
Related Item Receipts -> AVG(Receipt Date - Expected Date) -- "Avg Days Variance"
Formula (%): On-Time % (receipts on or before expected date)
Quality Score (from custrecord_gfs_vendor_score join)
Sort: Total Spend (descending)
15. Commission Calculator
Type: Invoice
Filters:
Date = this month | Status = Paid In Full | Main Line = T
Columns:
Sales Rep (Group) | Entity (Group) | Amount (SUM)
Formula (Currency): SUM({amount}) * 0.03 -- "Commission @ 3%"
Formula (Currency): SUM({amount}) * CASE
WHEN SUM({amount}) > 500000 THEN 0.04
WHEN SUM({amount}) > 250000 THEN 0.035
ELSE 0.03 END -- "Tiered Commission"
Sort: Sales Rep, Amount (descending)
■ All saved searches can be converted to SuiteQL using the patterns shown. Use N/search for UI-based approaches, N/query (SuiteQL) for complex joins. Formula fields use Oracle SQL syntax within NetSuite.
17Suitelet Best PracticesArchitecture patterns, HTML injection, session management, governance, and deployment checklists
Architecture Patterns
Pattern
When to Use
GFS Example
Complexity
Single Page
Simple data display, read-only dashboards, portlet-style views
GFS Pricing Dashboard, CME Price Display
Low
Multi-Tab
Related views in one Suitelet, settings panels, record detail with tabs
GFS Operations Center, Customer 360 View
Medium
Wizard (Multi-Step)
Complex data entry, guided workflows, import tools
Powerful but costs more. Cache results when possible
email.send()
10
All
Batch emails when possible. Daily limit: 10 per trigger
http.get() / .post()
10
All
External API calls. Cache responses in session/record
file.load()
1
All
Load from File Cabinet. Use for templates, configs
file.create()
5
All
Create in File Cabinet. CSV exports, PDF generation
render.xmlToPdf()
10
All
PDF generation from XML/HTML template
record.submitFields()
2
All
Update specific fields without loading full record
record.attach() / .detach()
5
All
Link/unlink records (e.g., file to transaction)
Governance limits per script type: Client=1,000 | User Event=1,000 | Suitelet=1,000 | RESTlet=5,000 | Scheduled=10,000 | Map/Reduce=10,000 per stage
Deployment Checklist
Testing Checklist
■ Use HTML injection for customer-facing portals (brand consistency). Use serverWidget for internal tools (faster dev). Always validate URL parameters server-side. Cache expensive operations.
18RESTlet & API PatternsAuthentication, request/response formats, pagination, batch operations, and endpoint inventory
Authentication Methods
Method
Use Case
Security
GFS Status
Token-Based Auth (TBA)
Production API access. Server-to-server. Cloudflare Workers.
Recommended
Active - all endpoints
NLAuth
Legacy scripts. Manual testing only.
Deprecated
Migrating to TBA
OAuth 2.0
User-context integrations. Web app delegated access.
■ All GFS RESTlets use TBA authentication. Standard response envelope includes success, data, and meta. Pagination maxes at 100 per page. Rate limit: 10 concurrent requests per deployment. Webhook receivers should validate signatures before processing.
19Custom Record ReferenceAll GFS custom records with field definitions, usage patterns, and linked record relationships
Percentage of POs received on or before expected date
custrecord_gfs_vs_quality_pct
Percent
Quality Score %
Percentage of receipts passing QC inspection
custrecord_gfs_vs_price_var
Currency
Price Variance
Actual vs. contracted price variance
custrecord_gfs_vs_total_spend
Currency
Total Spend
Total PO value for the period
custrecord_gfs_vs_overall
List/Record
Overall Rating
A (Excellent), B (Good), C (Needs Improvement), D (At Risk), F (Unacceptable)
custrecord_gfs_vs_notes
Text Area
Notes
Reviewer comments and action items
Lot Trace (custrecord_gfs_lot_trace)
Field ID
Type
Label
Description
custrecord_gfs_lt_lot_number
Text
Lot Number
GFS lot identifier. Format: LOT-XX-MMDD[A-Z]
custrecord_gfs_lt_item
List/Record
Item
Product item reference
custrecord_gfs_lt_vendor
List/Record
Source Vendor
Vendor who supplied this lot
custrecord_gfs_lt_vendor_lot
Text
Vendor Lot #
Vendor's own lot number for traceability
custrecord_gfs_lt_received
Date
Received Date
Date lot was received at GFS warehouse
custrecord_gfs_lt_production
Date
Production Date
Manufacturer's production date
custrecord_gfs_lt_expiry
Date
Expiration Date
Product expiration. Triggers alerts at 30/15/7 days
custrecord_gfs_lt_qty
Integer
Quantity
Total quantity in lot (base units)
custrecord_gfs_lt_parent_po
List/Record
Source PO
Purchase order that received this lot
custrecord_gfs_lt_status
List/Record
Status
Available, On Hold, Allocated, Shipped, Expired
Delivery Route (custrecord_gfs_route)
Field ID
Type
Label
Description
custrecord_gfs_rt_name
Text
Route Name
e.g., "NE-Metro-AM", "LI-East-PM"
custrecord_gfs_rt_driver
List/Record
Assigned Driver
Employee assigned to route
custrecord_gfs_rt_vehicle
Text
Vehicle ID
Truck/trailer identifier
custrecord_gfs_rt_day
Multi-Select
Delivery Days
Mon, Tue, Wed, Thu, Fri delivery schedule
custrecord_gfs_rt_window
List/Record
Window
AM (6-12), PM (12-6), Evening (6-10)
custrecord_gfs_rt_stops
Integer
Max Stops
Maximum delivery stops per route run
custrecord_gfs_rt_capacity
Decimal
Capacity (lbs)
Maximum weight capacity for the vehicle
custrecord_gfs_rt_temp
List/Record
Temp Capability
Refrigerated, Frozen, Dual-Temp, Ambient
Rebate Program (custrecord_gfs_rebate)
Field ID
Type
Label
Description
custrecord_gfs_reb_customer
List/Record
Customer
Customer entity eligible for rebate
custrecord_gfs_reb_type
List/Record
Rebate Type
Volume, Growth, Promotional, Year-End
custrecord_gfs_reb_rate
Percent
Rebate Rate %
Percentage of qualifying purchases rebated
custrecord_gfs_reb_threshold
Currency
Volume Threshold
Minimum purchase volume to qualify
custrecord_gfs_reb_start
Date
Start Date
Program effective start
custrecord_gfs_reb_end
Date
End Date
Program expiration. Triggers renewal review
custrecord_gfs_reb_accrued
Currency
Accrued Amount
Current period accrued rebate. Updated by scheduled script
custrecord_gfs_reb_status
List/Record
Status
Active, Pending Approval, Expired, Paid Out
Production Run (custrecord_gfs_production)
Field ID
Type
Label
Description
custrecord_gfs_pr_work_order
List/Record
Work Order
Link to NetSuite work order
custrecord_gfs_pr_item
List/Record
Assembly Item
Finished product being produced
custrecord_gfs_pr_qty_planned
Integer
Planned Qty
Target production quantity
custrecord_gfs_pr_qty_actual
Integer
Actual Qty
Actual produced quantity
custrecord_gfs_pr_yield_pct
Percent
Yield %
Actual / Planned percentage
custrecord_gfs_pr_start
Date/Time
Start Time
Production run start
custrecord_gfs_pr_end
Date/Time
End Time
Production run completion
custrecord_gfs_pr_lot
Text
Lot Assigned
Lot number assigned to finished goods
custrecord_gfs_pr_status
List/Record
Status
Scheduled, In Progress, Complete, QC Hold
Quality Hold (custrecord_gfs_quality_hold)
Field ID
Type
Label
Description
custrecord_gfs_qh_item
List/Record
Item
Item placed on quality hold
custrecord_gfs_qh_lot
Text
Lot Number
Affected lot number
custrecord_gfs_qh_reason
List/Record
Hold Reason
Temperature Excursion, Foreign Material, Label Error, Customer Complaint, Recall
custrecord_gfs_qh_date
Date
Hold Date
Date hold was placed
custrecord_gfs_qh_placed_by
List/Record
Placed By
Employee who initiated hold
custrecord_gfs_qh_qty
Integer
Quantity Held
Quantity of product on hold
custrecord_gfs_qh_disposition
List/Record
Disposition
Pending, Released, Destroyed, Returned to Vendor, Reworked
custrecord_gfs_qh_released_by
List/Record
Released By
QA manager who approved release
custrecord_gfs_qh_released_date
Date
Released Date
Date hold was released
custrecord_gfs_qh_notes
Text Area
Investigation Notes
Root cause analysis and corrective actions
■ Custom records use custrecord_ prefix. All custom records have Include Name Field enabled for search display. Parent/child relationships use List/Record fields with Record Type sourcing. Permissions set at record type level.
20Print Template FreeMarkerNetSuite Advanced PDF/HTML template patterns with FreeMarker syntax, conditionals, and loops
■ FreeMarker templates use ${} for output and <#> for directives. Use ?has_content for null checks and ! for defaults. Barcode generation requires codetype attribute. Test in PDF Preview before deploying to production.
21Workflow & Approval PatternsMulti-level approval matrix, conditional routing, escalation rules, and workflow state diagrams
GFS Approval Matrix
Amount Range
Approval Level
Approver
SLA
Escalation
$0 - $4,999
Auto-Approved
System (no human)
Instant
N/A
$5,000 - $24,999
Level 1
Department Manager
24 hours
Auto-escalate to L2 after 48h
$25,000 - $99,999
Level 2
VP Operations + CFO
48 hours
Email reminder at 24h, escalate to CEO at 72h
$100,000+
Level 3
VP + CFO + CEO
72 hours
Board notification for > $250K
Conditional Routing Rules
Condition
Route To
Additional Action
Department = Production
Production Manager (before standard chain)
Add QC checklist requirement
Department = Dairy & Cheese
Dairy Operations Lead
Verify USDA compliance fields
Vendor = new (first PO)
Purchasing Director
Require W-9 and insurance verification
Item = hazmat classified
Safety Compliance Officer
Attach SDS documentation
Ship Country != US
Export Compliance
Generate customs documentation
Customer on credit hold
Credit Manager
Block fulfillment until released
Rush order (priority = Rush)
Skip L1, direct to L2
Add $150 surcharge, alert warehouse
PO Approval Workflow State Diagram
Draft
Submitted
L1 Review
L2 Review
Approved
Reject at any stage -- returns to Draft with rejection reason
Delegate -- forward to alternate approver, preserves SLA clock
■ Approval workflows use SuiteFlow (Customization > Workflows). Amount thresholds configured in the workflow itself. Escalation uses scheduled workflow actions. All approval events logged for audit trail. Delegation preserves the original SLA clock.
// 1. Inline field error (highlight field + message below)
function showFieldError(fieldId, msg) {
const field = document.getElementById(fieldId);
if (field) {
field.classList.add('ns-input-error');
const errEl = document.getElementById('err-' + fieldId);
if (errEl) { errEl.textContent = msg; errEl.style.display = 'block'; }
}
}
// 2. Banner warning (top of form, dismissible)
// Uses N/ui/message module in SuiteScript
const banner = message.create({
type: message.Type.ERROR,
title: 'Save Failed',
message: 'Unable to save record. ' + errorDetails,
duration: 10000 // auto-dismiss after 10s
});
banner.show();
// 3. Modal alert (blocking, requires user action)
dialog.alert({
title: 'Critical Error',
message: 'This operation cannot be completed.\n\n' + errorDetails
}).then(() => {
// User clicked OK -- redirect or reload
window.location.reload();
});
// 4. Toast notification (non-blocking, auto-dismiss)
// Using GFS custom toast (from this design system)
nsShowToast('Record saved successfully.', 'ns-toast-success');
nsShowToast('Unable to save. Try again.', 'ns-toast-error');
nsShowToast('Unsaved changes detected.', 'ns-toast-warning');
■ Always wrap record operations in try/catch. Use specific error code checks before generic catch. Log full error details (name, message, stack) for debugging. Show user-friendly messages -- never expose raw error objects.
23Deployment & GovernanceScript deployment checklist, sandbox promotion, rollback, version control, and go-live procedures
Script Deployment Checklist
Governance Budget Table (All Operations)
Operation
Units
Category
Optimization Tip
record.load()
5
Record
Use lookupFields() for 1-5 fields (cost: 1)
record.save()
10
Record
Use submitFields() for field-only updates (cost: 2)
record.create() + save()
15
Record
Batch creates in Map/Reduce for volume
record.delete()
10
Record
Consider inactivation instead
record.submitFields()
2
Record
Best for updating specific fields
search.lookupFields()
1
Search
Cheapest way to read record data
search.create().run()
5
Search
Each getRange(start,end) adds 10 units
search.run().getRange()
10
Search
Max 1000 results per getRange call
query.runSuiteQL()
10
Query
Powerful but expensive -- cache results
email.send()
10
Email
10 emails per script trigger max. Batch if possible
1.Complete all testing in Sandbox (see testing checklist)
2.Document all script files, deployment IDs, and configuration changes
3.Create SDF (SuiteCloud Development Framework) project or manual promotion list
4.Back up existing production scripts to /SuiteScripts/archive/YYYYMMDD/
5.Upload new script files to production File Cabinet
6.Update script records to point to new file versions
7.Set deployment status to "Testing" first -- verify with one user
8.Change deployment status to "Released" for full audience
9.Monitor execution logs for first 24 hours
10.Confirm with stakeholders and close deployment ticket
Rollback Procedure
Emergency Rollback Steps
1. Set deployment status to "Not Released" (immediately stops execution)
2. Restore previous script file from /SuiteScripts/archive/
3. Update script record to point to restored file
4. Set deployment back to "Released"
5. Verify functionality with test transaction
6. Notify affected users of rollback and estimated fix timeline
7. Document root cause and create fix ticket
Go-Live Checklist
■ Always deploy to Testing status first. Monitor execution logs for 24h after release. Keep archived versions in File Cabinet for instant rollback. Governance budgets are per-execution, not cumulative.
24GFS NetSuite Do / Don't30+ NetSuite-specific best practice pairs covering scripting, search, workflow, deployment, and security
Do
Use dynamic mode for interactive records (forms, suitelets with user input)
Use SuiteQL (N/query) for complex queries with 3+ table joins
Cache search results in Map/Reduce getInputData stage
Use log.audit for business events (approvals, record changes)
Handle all error paths in RESTlets with typed error responses
Use field internal IDs (not labels) in all scripts
Batch record operations with governance checks between each
Use N/query for readonly data retrieval (reporting, dashboards)
Use custbody_ / custcol_ / custentity_ for custom fields
Test with all affected roles before deployment
Use record.submitFields() for simple field updates (cost: 2)
Use search.lookupFields() to read 1-5 fields from a record (cost: 1)
Use paged execution for searches returning 4000+ results
Validate URL parameters server-side in Suitelets
Use N/runtime to check governance before expensive operations
Use Map/Reduce for batch processing of 100+ records
Log full error objects: name, message, stack trace
Use Promise patterns in client scripts for async operations
Archive previous script versions before overwriting
Use the N/format module for date and number formatting
Use N/email with templates for consistent branded communications
Set deployment status to Testing before full release
Use N/record.Type enum for type-safe record type references
Implement retry logic for RCRD_HAS_BEEN_CHANGED errors
Use FETCH FIRST N ROWS ONLY in SuiteQL for pagination
Use FreeMarker ?has_content for null-safe field access in templates
Set concurrency limits appropriate for the script's workload
Use N/url.resolveScript() for dynamic Suitelet URLs
Include version comments in script headers (@version 1.0.0)
Use TBA authentication for all API integrations
Use comments (not messages) for record communication notes
Monitor execution logs for 48h after any production deployment
Don't
Use standard mode for user-facing forms (loses field validation)
Use N/search for joins across 4+ tables (use SuiteQL instead)
Run searches inside map() -- they execute per record (use getInputData)
Use log.debug in production (clutters logs, wastes governance)
Return raw NetSuite error objects to external clients
Hardcode internal IDs -- use script parameters or custom records
Save records in a loop without checking remaining governance
Load full records just to read 1-2 field values
Repurpose standard fields for custom data (use custom fields)
Assume admin access -- always test with restricted roles
Use record.load() + save() when submitFields() would suffice
Build search result arrays with run().each() for large datasets
Use getRange(0, 1000) without checking if more results exist
Trust client-side URL parameters without server validation
Run expensive operations without checking governance budget first
Use Scheduled Scripts for batch work that Map/Reduce handles better
Catch errors silently -- always log or surface the issue
Use synchronous HTTP calls in client scripts (blocks the UI)
Overwrite production scripts without backing up the previous version
Use string concatenation for dates (use N/format module)
Send emails with hardcoded HTML -- use NS email templates
Deploy directly to Released without testing with a single user first
Use string literals for record types ('salesorder' -- use record.Type)
Fail permanently on concurrent edit errors without retrying
Use SELECT * or unbounded queries in SuiteQL (always limit results)
Assume field values exist in templates -- always use null checks
Set concurrency to max for all scripts (causes queue contention)
Hardcode Suitelet URLs (they change between environments)
Ship scripts without version tracking or change documentation
Use NLAuth for production integrations (deprecated, less secure)
Use the messages tab for internal notes (use comments instead)
Assume deployment success -- always verify with execution log review
■ These rules are GFS-specific and reflect our NetSuite 2025.2 environment. Print this page and post near your workstation. When in doubt, check governance first, cache second, log third.
Confirm Delete
Are you sure you want to delete record SO-24891? This action cannot be undone. All line items, shipping records, and related transactions will be permanently removed.
← Back to Hub ·
GFS Design System v10.0 ·
Global Food Solutions, Inc. ·
131 Heartland Blvd, Edgewood, NY 11717 ·
(877) 728-5550