Skip to main content

Integration Test Cases

Integration patterns for QuickMart Supplies - connecting NetSuite to external systems.


Integration Patterns Overview

INTEGRATION PATTERNS - QuickMart Architecture
===============================================================================

+-------------+ +-------------+ +-------------+ +-------------+
| SHOPIFY | | POS | | WAREHOUSE | | ACCOUNTING |
| (Store) | | (Retail) | | (App) | | (System) |
+------+------+ +------+------+ +------+------+ +------+------+
| | | |
| POST | GET | |
| (orders) | (stock/loyalty) | |
v v | |
+------+-------------------+-------------------+-------------------+------+
| NETSUITE |
| |
| RECEIVE EXPOSE PUSH OUT PULL IN |
| (RESTlet POST) (RESTlet GET) (User Event) (Scheduled)|
| |
| - Create SO - Stock Query - Send to WH - Exchange |
| - Create Payment - Loyalty Lookup - Send Invoice Rates |
| - Send Alerts - Catalog |
+-------------------------------------------------------------------------+

Pattern Comparison

PatternDirectionTriggerScript TypesUse Case
Push OutNS → ExternalEvent-drivenUser Event, ScheduledSend orders to warehouse
Pull InExternal → NSScheduledScheduled, Map/ReduceFetch exchange rates
ReceiveExternal → NSOn-demandRESTlet POSTShopify sends order
ExposeNS → ExternalOn-demandRESTlet GETPOS queries stock

Test Case #27: Push Out - Send Order to Warehouse

Pattern: PUSH OUT (Event-Driven)

Objective: When a Sales Order is approved, automatically send order details to external warehouse system.

Scenario

David (Warehouse) uses a mobile app to manage picking. When orders are approved in NetSuite, they should appear in his app immediately.

Architecture

PUSH OUT FLOW
-------------------------------------------------------------------------------

NetSuite Warehouse App
+------------------+ +------------------+
| | HTTP POST | |
| Sales Order | -----------------> | Orders Queue |
| Status: Approved | JSON Payload | |
| | | -> Pick List |
| User Event: | Response: 200 OK | -> Mobile App |
| afterSubmit | <----------------- | |
| | | |
+------------------+ +------------------+

Implementation

See SuiteScript Test #13

Test Steps

  1. Prerequisite: Warehouse API endpoint available (or mock server)
  2. Create Sales Order with items
  3. Change status to "Pending Fulfillment"
  4. Save the order
  5. Verify:
    • Check Integration Log custom record
    • Confirm order appears in warehouse system
    • Response code: 200

Expected Payload

{
"orderId": "SO-12345",
"nsInternalId": 56789,
"customer": "ABC Corporation",
"shipAddress": "123 Main St, City, ST 12345",
"priority": true,
"lines": [
{
"item": "Printer Paper A4",
"quantity": 20,
"location": "Warehouse 1"
},
{
"item": "Ink Cartridge HP",
"quantity": 5,
"location": "Warehouse 1"
}
]
}

Error Handling

ScenarioExpected Behavior
API timeoutLog error, retry later via scheduled job
API returns 400Log validation error, alert admin
API returns 500Log server error, queue for retry

Test Case #28: Push Out - Send Invoice to Accounting

Pattern: PUSH OUT (Scheduled)

Objective: Send invoices to external accounting system nightly.

Architecture

PUSH OUT - BATCH FLOW
-------------------------------------------------------------------------------

NetSuite Accounting System
+------------------+ +------------------+
| | | |
| Invoices | Scheduled Script | Journal Entries |
| (Created Today) | runs at 11 PM | |
| | -----------------> | |
| Search: | POST /api/invoices | |
| date = today | (batch) | |
| | | |
+------------------+ +------------------+

Script Configuration

/**
* @NApiVersion 2.1
* @NScriptType ScheduledScript
*
* QuickMart - Push Invoices to Accounting
* Runs: Daily at 11:00 PM
*/
define(['N/search', 'N/https', 'N/log', 'N/record'], function(search, https, log, record) {

const ACCOUNTING_API = 'https://accounting.quickmart.com/api/invoices';

function execute(context) {
var invoices = findTodaysInvoices();

if (invoices.length === 0) {
log.audit('No Invoices', 'No invoices to push today');
return;
}

var payload = { invoices: invoices };

try {
var response = https.post({
url: ACCOUNTING_API,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});

log.audit('Push Complete', 'Sent ' + invoices.length + ' invoices');

} catch (e) {
log.error('Push Failed', e.message);
}
}

function findTodaysInvoices() {
var invoices = [];
var today = new Date();

search.create({
type: search.Type.INVOICE,
filters: [
['trandate', 'on', 'today'],
'AND',
['mainline', 'is', 'T']
],
columns: ['tranid', 'entity', 'total', 'duedate']
}).run().each(function(result) {
invoices.push({
invoiceNumber: result.getValue('tranid'),
customer: result.getText('entity'),
amount: result.getValue('total'),
dueDate: result.getValue('duedate')
});
return true;
});

return invoices;
}

return { execute: execute };
});

Test Steps

  1. Create several invoices during the day
  2. Wait for scheduled script to run (or run manually)
  3. Verify: Integration log shows successful push

Test Case #29: Pull In - Fetch Exchange Rates

Pattern: PULL IN (Scheduled)

Objective: Fetch daily exchange rates from external API and update NetSuite.

Architecture

PULL IN FLOW
-------------------------------------------------------------------------------

External API NetSuite
+------------------+ +------------------+
| | | |
| Exchange API | Scheduled Script | Currency Rates |
| (exchangerate.io)| runs at 7 AM | |
| | <----------------- | |
| GET /latest | | Search/Update |
| | -----------------> | Currency Records |
| JSON Response | | |
| | | |
+------------------+ +------------------+

Implementation

See SuiteScript Test #16

Test Steps

  1. Configure scheduled script with API URL
  2. Run script manually for testing
  3. Verify: Exchange rates updated in NetSuite

Sample API Response

{
"base": "USD",
"date": "2024-03-15",
"rates": {
"EUR": 0.92,
"GBP": 0.79,
"SGD": 1.35,
"IDR": 15650
}
}

Test Case #30: Pull In - Import Supplier Catalog

Pattern: PULL IN (Map/Reduce for High Volume)

Objective: Import 5,000+ items from supplier catalog API.

Why Map/Reduce?

GOVERNANCE LIMITS
-------------------------------------------------------------------------------

Scheduled Script: 10,000 usage units
Map/Reduce Script: 10,000 units per stage (50,000+ total)
Automatic restart on timeout

For 5,000+ items: Use Map/Reduce!

Architecture

PULL IN - HIGH VOLUME
-------------------------------------------------------------------------------

Supplier API NetSuite
+------------------+ +------------------+
| | | |
| Catalog API | getInputData() | Items |
| /api/catalog | <----------------- | (5,000+ records) |
| | GET all items | |
| Returns: | | map(): Parse |
| 5,000 items | | reduce(): Update |
| | | each item |
+------------------+ +------------------+

Implementation

See SuiteScript Test #18


Test Case #31: Receive - Orders from Shopify

Pattern: RECEIVE (RESTlet POST)

Objective: Receive and process orders from Shopify webhooks.

Scenario

Lisa (Admin) currently copies orders manually from Shopify. This RESTlet receives orders automatically.

Architecture

RECEIVE FLOW
-------------------------------------------------------------------------------

Shopify NetSuite
+------------------+ +------------------+
| | | |
| New Order | Webhook POST | RESTlet |
| Created | -----------------> | |
| | JSON: Order Data | 1. Find Customer |
| Trigger: | | 2. Create SO |
| Order Created | Response: 200 | 3. Add Lines |
| | <----------------- | 4. Return ID |
| | {success: true} | |
+------------------+ +------------------+

Implementation

See SuiteScript Test #19

Shopify Webhook Configuration

Shopify Admin > Settings > Notifications > Webhooks

Event: Order Creation
Format: JSON
URL: https://<account>.restlets.api.netsuite.com/app/site/hosting/restlet.nl
?script=XXX&deploy=1
Headers:
Authorization: NLAuth nlauth_account=XXX, nlauth_email=XXX, nlauth_signature=XXX

Test Steps

  1. Deploy RESTlet with deployment ID
  2. Configure Shopify webhook to call RESTlet
  3. Place test order on Shopify
  4. Verify: Sales Order created in NetSuite

Sample Webhook Payload (Simplified)

{
"order_id": "SHOP-98765",
"customer_email": "customer@example.com",
"customer_name": "Jane Smith",
"priority": false,
"line_items": [
{
"sku": "PAPER-A4",
"quantity": 5,
"price": 12.00
}
],
"shipping_address": {
"address1": "456 Oak Ave",
"city": "Springfield",
"zip": "12345"
}
}

Expected Response

{
"success": true,
"netsuite_order_id": 12345,
"message": "Order created successfully"
}

Test Case #32: Receive - Payments from POS

Pattern: RECEIVE (RESTlet POST)

Objective: Receive payment transactions from POS system.

Architecture

RECEIVE - PAYMENT FLOW
-------------------------------------------------------------------------------

POS System NetSuite
+------------------+ +------------------+
| | | |
| Payment | POST | RESTlet |
| Completed | -----------------> | |
| | invoice_number | 1. Find Invoice |
| Cashier clicks | amount | 2. Transform to |
| "Complete" | payment_method | Payment |
| | | 3. Apply to Inv |
| | Response | |
| | <----------------- | |
+------------------+ {payment_id: 123} +------------------+

Implementation

See SuiteScript Test #20

Test Steps

  1. Create Invoice in NetSuite (e.g., INV-00100)
  2. POST payment to RESTlet:
    {
    "invoice_number": "INV-00100",
    "amount": 150.00,
    "payment_method": 5,
    "reference": "POS-TXN-789"
    }
  3. Verify: Customer Payment created, Invoice marked paid

Test Case #33: Expose - Stock Availability Query

Pattern: EXPOSE (RESTlet GET)

Objective: Allow external systems to query real-time stock levels.

Scenario

E-commerce website needs to show "In Stock" or "Out of Stock" before customer adds to cart.

Architecture

EXPOSE FLOW
-------------------------------------------------------------------------------

E-commerce Site NetSuite
+------------------+ +------------------+
| | | |
| Product Page | GET | RESTlet |
| (needs stock) | -----------------> | |
| | ?sku=PAPER-A4 | 1. Search Item |
| Show: | | 2. Get Inventory |
| "150 in stock" | Response | 3. Return JSON |
| | <----------------- | |
+------------------+ {available: 150} +------------------+

Implementation

See SuiteScript Test #21

Test Steps

  1. Deploy RESTlet
  2. Call with item SKU:
    GET /restlet?script=XXX&deploy=1&sku=PAPER-A4
  3. Verify: Response contains accurate stock levels

Sample Request/Response

Request:
GET ?script=XXX&deploy=1&sku=PAPER-A4

Response:
{
"item_id": "12345",
"sku": "PAPER-A4",
"name": "A4 Printer Paper 500 sheets",
"available": 150,
"on_hand": 200,
"on_order": 50
}

Test Case #34: Expose - Customer Loyalty Lookup

Pattern: EXPOSE (RESTlet GET)

Objective: Allow POS to look up customer loyalty data for in-store discounts.

Scenario

Mike (Sales) rings up a customer at the register. POS needs to check if they're a loyalty member and what discount they get.

Architecture

EXPOSE - LOYALTY FLOW
-------------------------------------------------------------------------------

POS System NetSuite
+------------------+ +------------------+
| | | |
| Customer at | GET | RESTlet |
| Register | -----------------> | |
| | ?email=x@email.com | 1. Find Customer |
| "Your loyalty | | 2. Get Loyalty |
| discount: 10%" | Response | Record |
| | <----------------- | 3. Return JSON |
+------------------+ {tier: Gold, ...} +------------------+

Implementation

See SuiteScript Test #22

Test Steps

  1. Create Customer with email: test@example.com
  2. Create Loyalty record: Gold tier, 1500 points
  3. Call RESTlet:
    GET ?script=XXX&deploy=1&email=test@example.com
  4. Verify: Response shows tier and discount

Sample Response

{
"found": true,
"customer_id": 789,
"customer_name": "ABC Corporation",
"loyalty": {
"tier": 3,
"tier_name": "Gold",
"points": 1500,
"total_spent": 15000.00,
"discount_percent": 10
}
}

Test Case #35: Push Out - Fulfillment Status to Shopify

Pattern: PUSH OUT (Event-Driven)

Objective: When an order is fulfilled in NetSuite, update the Shopify order status.

Scenario

Customers expect real-time shipping updates. When fulfillment is completed in NetSuite, Shopify should show the order as fulfilled.

Architecture

PUSH OUT - FULFILLMENT STATUS
-------------------------------------------------------------------------------

NetSuite Shopify
+------------------+ +------------------+
| | HTTP PUT | |
| Item Fulfillment | -----------------> | Order Status |
| (Created) | /orders/{id}.json | -> Fulfilled |
| User Event: | | |
| afterSubmit | <----------------- | Response: 200 OK |
+------------------+ +------------------+

Implementation

See SuiteScript Test #31

Test Steps

  1. Ensure Sales Order has custbody_external_order_id populated
  2. Create Item Fulfillment in NetSuite
  3. Verify: Shopify order shows Fulfilled status
  4. Verify: Integration log entry created (optional)

Integration Security Checklist

Security MeasureDescriptionImplementation
AuthenticationVerify caller identityNLAuth, Token-Based Auth
AuthorizationCheck permissionsRole-based access, IP whitelist
ValidationValidate input dataCheck required fields, types
Rate LimitingPrevent abuseTrack call frequency
LoggingAudit trailIntegration Log custom record
Error HandlingGraceful failuresTry/catch, meaningful errors

Authentication Example

// Token-Based Authentication (TBA)
// Configured in: Setup > Integration > Manage Integrations

// OAuth 1.0 Headers (set by calling system):
// Authorization: OAuth
// oauth_consumer_key="...",
// oauth_token="...",
// oauth_signature="...",
// oauth_signature_method="HMAC-SHA256",
// oauth_timestamp="...",
// oauth_nonce="...",
// oauth_version="1.0"

Integration Log Record

For tracking all integration calls, create a custom record:

Custom Record: Integration Log
ID: customrecord_integration_log

Fields:
+-----------------+-----------+----------------------------------+
| Field | Type | Purpose |
+-----------------+-----------+----------------------------------+
| Name | Auto | Auto-generated |
| Pattern | List | PUSH_OUT, PULL_IN, RECEIVE, etc. |
| Status | List | SUCCESS, ERROR, PENDING |
| Direction | List | INBOUND, OUTBOUND |
| Endpoint | URL | API URL called |
| Request Body | Text Area | Outbound payload (truncated) |
| Response Body | Text Area | Response received (truncated) |
| Error Message | Text Area | Error details if failed |
| Related Record | Text | SO ID, Invoice ID, etc. |
| Timestamp | DateTime | When call was made |
+-----------------+-----------+----------------------------------+

Next Steps