Custom Process Outbound Transactions

Custom Process for outbound transactions lets you bypass the SuiteApp's native message generation and build your own outbound EDI logic. When enabled, the SuiteApp hides its native Generate buttons and leaves message creation entirely to your custom SuiteScript. You control what gets sent and when.

This is useful when:

  • A trading partner requires non-standard outbound data that the native mappers don't produce
  • Your business logic requires conditional generation (e.g., only send invoices that meet specific criteria)
  • You need to pull data from custom records or external systems before generating the EDI message
  • You want full control over the outbound payload structure

For inbound custom processing, see Custom Process Inbound Transactions.

How It Works

Outbound custom process works differently from inbound. With inbound, the SuiteApp stages the raw EDI data and stops — your code picks up from there. With outbound, the relationship is reversed: there is no incoming data to stage. Instead, your code must create the outbound message payload and hand it off to the SuiteApp for delivery.

Transaction Flow

  1. Configuration: An admin enables a transaction type on a Customer record and checks "Process as Custom." The handling preference for that transaction type should be set to "Custom (Manual/Workflow)."

  2. Native buttons hidden: The SuiteApp's Generate buttons (Generate 810, Generate 855, Generate 856, Generate 940) no longer appear on the relevant NetSuite records for that customer. The "Generate and Send" button on Orderful Transaction records is also hidden.

  3. Developer generates the message: Your custom SuiteScript creates or loads an Orderful Transaction record, builds the EDI message payload in JSON format, and writes it to the Message field.

  4. Send to Orderful: Once the message is populated, it can be sent via:

    • The "Send to Orderful" button on the Orderful Transaction record (visible for custom process types)
    • Setting the status to "Ready To Send" — the outbound sending MapReduce picks it up automatically
    • A WorkflowAction script triggered from a SuiteFlow workflow
  5. Delivery: The SuiteApp POSTs the message to the Orderful API and updates the transaction status to Success or Error.

Configuration

Step 1: Enable Custom Process on the Customer

  1. Navigate to the Customer record
  2. Go to the Orderful EDI subtab → EDI Enabled Transaction Types
  3. Find or add the outbound transaction type (e.g., 810, 855, 856, 940)
  4. Check Process as Custom
  5. Save the Customer record

Step 2: Set Handling Preferences

On the same Customer record, set the handling preference for the transaction type to Custom (Manual/Workflow):

  • 810 Invoice: Set "Invoice Handling Preference" to Custom
  • 855 PO Acknowledgment: Set "PO Ack Handling Preference" to Custom
  • 856 ASN: Set "ASN Handling Preference" to Custom
  • 940 Warehouse Shipping Order: Set "WSO Handling Preference" to Custom

When the handling preference is Custom, the SuiteApp does not automatically generate outbound transactions when trigger events occur (e.g., invoice creation, sales order approval, item fulfillment shipment).

For details on handling preferences, see Outbound Transaction Handling Preferences.

Developer Workflow

Creating the Orderful Transaction Record

Your SuiteScript must create an Orderful Transaction record (customrecord_orderful_transaction) and populate the required fields:

/**
 * Create a custom outbound Orderful Transaction record
 * and populate it with a developer-generated message payload.
 */
define(['N/record', 'N/search'], function (record, search) {

  function createCustomOutboundTransaction(options) {
    const { entityId, documentType, message, isTestMode } = options;

    // Create the Orderful Transaction record
    const orderfulTxn = record.create({
      type: 'customrecord_orderful_transaction',
    });

    // Set required fields
    orderfulTxn.setValue({
      fieldId: 'custrecord_ord_tran_entity',
      value: entityId
    });
    orderfulTxn.setValue({
      fieldId: 'custrecord_ord_tran_document',
      value: documentType  // Internal ID of the document type list value
    });
    orderfulTxn.setValue({
      fieldId: 'custrecord_ord_tran_direction',
      value: 2  // Out
    });
    orderfulTxn.setValue({
      fieldId: 'custrecord_ord_tran_status',
      value: getStatusId('transaction_status_ready_to_send')
    });
    orderfulTxn.setValue({
      fieldId: 'custrecord_ord_tran_message',
      value: JSON.stringify(message)
    });
    orderfulTxn.setValue({
      fieldId: 'custrecord_ord_tran_testmode',
      value: isTestMode || false
    });

    const transactionId = orderfulTxn.save();

    log.audit({
      title: 'Custom Outbound Transaction Created',
      details: `Orderful Transaction ${transactionId} created for entity ${entityId}`
    });

    return transactionId;
  }

  /**
   * Helper: Look up the internal ID of a transaction status by script ID
   */
  function getStatusId(scriptId) {
    const results = search.create({
      type: 'customlist_orderful_transaction_status',
      filters: [['scriptid', 'is', scriptId]],
      columns: ['internalid']
    }).run().getRange(0, 1);

    return results.length > 0 ? results[0].getValue('internalid') : null;
  }

  return { createCustomOutboundTransaction };
});

Orderful Transaction Fields

Field IDRequiredDescription
custrecord_ord_tran_entityYesInternal ID of the Customer or Vendor
custrecord_ord_tran_documentYesDocument type (internal ID from customrecord_orderful_edi_document_type)
custrecord_ord_tran_directionYesSet to 2 (Out)
custrecord_ord_tran_statusYesSet to Ready To Send when the message is ready for delivery
custrecord_ord_tran_messageYesThe JSON message payload (stringified)
custrecord_ord_tran_isa_senderRecommendedCompany ISA ID (sender). If not set, the SuiteApp uses the company-level default.
custrecord_ord_tran_receiverRecommendedCustomer ISA ID (receiver)
custrecord_ord_tran_testmodeNoSet to true for sandbox/test transactions
custrecord_ord_tran_inbound_transactionNoLink to a parent inbound Orderful Transaction (if this outbound is a response to an inbound, e.g., 855 responding to an 850)
custrecord_orderful_po_numberNoPurchase order number reference

Sending the Transaction

Once the message payload is populated, send it to Orderful using one of these methods:

Method 1: Status-Based Automatic Sending

Set the transaction status to Ready To Send. The customscript_orderful_outbound_sending MapReduce script runs on a schedule and picks up all outbound transactions with this status. This is the simplest approach for batch processing.

record.submitFields({
  type: 'customrecord_orderful_transaction',
  id: transactionId,
  values: {
    custrecord_ord_tran_status: readyToSendStatusId
  }
});

Method 2: Manual Send via UI

If the Orderful Transaction record has a populated message and the transaction type is configured as custom process, the "Send to Orderful" button appears on the record. A user can click this button to send the transaction immediately.

Method 3: WorkflowAction

Use the customscript_orderful_send_orderful_wa WorkflowAction in a SuiteFlow workflow to trigger sending programmatically. This is useful for approval-based flows where a workflow state transition triggers the send.

Transaction Statuses

StatusScript IDWhen Used
Pendingtransaction_status_pendingInitial state if creating a shell record before the message is ready
Ready To Sendtransaction_status_ready_to_sendMessage populated and ready for delivery. The outbound sending MapReduce picks up transactions in this status.
Successtransaction_status_successTransaction successfully sent to and accepted by Orderful
Errortransaction_status_errorSend failed. Check the custrecord_ord_tran_error field for details.

Comparison: Inbound vs Outbound Custom Process

AspectInboundOutbound
What the SuiteApp providesRaw EDI message payload, staged as an Orderful Transaction with status "Pending - Custom Process"Nothing — native generation is disabled. Developer must create the message.
Developer's responsibilityProcess the staged data and create NetSuite records (Sales Orders, Fulfillments, etc.)Generate the outbound message payload and populate it on the Orderful Transaction record
Initial statusPending - Custom ProcessPending (or Ready To Send if set by the developer at creation)
How to completeSet status to Success after processingPopulate the message, then send via button, status change, or WorkflowAction
UI impactNo native records are createdGenerate buttons are hidden; "Send to Orderful" button is shown

Available WorkflowAction Scripts

These scripts can be used in SuiteFlow workflows on the Orderful Transaction record:

Script IDPurpose
customscript_orderful_send_orderful_waSend an already-generated message to Orderful. Use this for custom process outbound.
customscript_orderful_generate_send_waGenerate the message using native mappers AND send. Not typically used for custom process (since the point is to bypass native generation).
customscript_orderful_generate_810_waGenerate a native 810 from an Invoice
customscript_orderful_generate_855_waGenerate a native 855 from a Sales Order
customscript_orderful_generate_856_waGenerate a native 856 from an Item Fulfillment
customscript_orderful_generate_940_waGenerate a native 940 from a Sales Order

Best Practices

  • Error handling: Wrap your message generation logic in try/catch blocks. If generation fails, set the Orderful Transaction status to Error and write a meaningful message to the custrecord_ord_tran_error field.
  • Logging: Use N/log to audit custom generation events. Include the Orderful Transaction ID, entity, and document type in log entries.
  • Test mode: Use the test mode flag (custrecord_ord_tran_testmode) during development. Test mode transactions are sent using the Test ISA ID and can be identified separately in Orderful.
  • ISA IDs: Always set the sender and receiver ISA IDs on the Orderful Transaction record. If omitted, the SuiteApp falls back to company-level defaults, which may not be correct for all customers.
  • Sandbox testing: Test custom outbound logic in a NetSuite sandbox environment before deploying to production.
  • Null removal: The SuiteApp automatically strips null values, empty arrays, and empty objects from the payload before sending. You do not need to clean the payload yourself.

Message Payload Format

The message you write to custrecord_ord_tran_message must conform to the format expected by the Orderful API. There are two formats depending on whether you are sending a standard (Orderful JSON) or simplified transaction.

Standard Format (Orderful JSON)

Used for X12 transaction types (810, 855, 856, 846, 880, 940, 943). Sent to https://api.orderful.com/v3/transactions.

{
  "sender": {
    "isaId": "YOURCOMPANYISA"
  },
  "receiver": {
    "isaId": "TRADINGPARTNERISA"
  },
  "type": {
    "name": "810_INVOICE"
  },
  "stream": "LIVE",
  "message": {
    "transactionSets": [
      {
        // Transaction set content in Orderful JSON format
        // Structure varies by transaction type
      }
    ]
  }
}

Key fields:

FieldDescription
sender.isaIdYour company's ISA ID (the sender for outbound transactions)
receiver.isaIdThe trading partner's ISA ID
type.nameThe Orderful transaction type identifier (see table below)
stream"LIVE" for production or "TEST" for sandbox transactions
message.transactionSetsArray containing one transaction set object in Orderful JSON format

Transaction type identifiers:

Transactiontype.name Value
810 Invoice810_INVOICE
855 PO Acknowledgment855_PURCHASE_ORDER_ACKNOWLEDGMENT
856 ASN856_SHIP_NOTICE_MANIFEST
846 Inventory Advice846_INVENTORY_INQUIRY_ADVICE
880 Grocery Invoice880_GROCERY_PRODUCTS_INVOICE
940 Warehouse Shipping Order940_WAREHOUSE_SHIPPING_ORDER
943 Warehouse Stock Transfer943_WAREHOUSE_STOCK_TRANSFER_SHIPMENT_ADVICE

Simplified Format

Used for simplified (non-X12) transaction types. Sent to https://api.orderful.com/v2/integration-payloads.

{
  "senderId": "YOURCOMPANYISA",
  "receiverId": "TRADINGPARTNERISA",
  "type": "855_PURCHASE_ORDER_ACKNOWLEDGMENT",
  "stream": "LIVE",
  "message": {
    "purchaseOrderNumber": "PO12345",
    "status": "accepted",
    "lineItems": []
  }
}

Note the differences from the standard format:

  • senderId and receiverId are flat strings (not nested objects)
  • type is a flat string (not { "name": "..." })
  • message contains the payload directly — no transactionSets wrapper

Format Detection

The SuiteApp automatically detects which format to use based on the message structure:

  • If message contains transactionSets, it sends to the standard (/v3/transactions) endpoint
  • If message contains simplified-format keys (e.g., purchaseOrderNumber, invoiceNumber, shipmentId), it sends to the simplified (/v2/integration-payloads) endpoint

You do not need to specify the endpoint — just structure the message correctly and the SuiteApp handles routing.

Limitations

  • No native message generation: When custom process is enabled for an outbound type, the SuiteApp's native mappers do not run. The developer is responsible for producing the complete message payload.
  • No automatic shell creation: When the handling preference is set to Custom (Manual/Workflow), the SuiteApp does not automatically create an Orderful Transaction record when a trigger event occurs. The developer must create the record.
  • No reprocess: Unlike inbound custom process transactions, outbound transactions do not have a "Reprocess" option. If a send fails, correct the message and re-send, or create a new Orderful Transaction record.
  • Validation is on the Orderful platform: The SuiteApp does not validate custom-generated payloads before sending. Validation errors from the Orderful API are written to the Error field on the Orderful Transaction record.