Automate Customer Payment Reconciliation in NetSuite
The friction between bank statement reconciliation and accounts receivable (AR) application is one of the most common bottlenecks in a month-end close.
Sarah Jenkins, CPAPrincipal Finance Automation Specialist
The friction between bank statement reconciliation and accounts receivable (AR) application is one of the most common bottlenecks in a month-end close. For many organizations, especially those transitioning from simpler accounting software like Xero or MYOB, the "NetSuite way" of handling these transactions can feel counterintuitive.
The core challenge lies in the sequence of operations: NetSuite typically expects the accounting event (the Customer Payment) to exist before the bank reconciliation occurs. When you are identifying payments directly from a bank feed, this can feel like an extra step because the data is being "pulled" from the bank rather than "pushed" from an invoice.
The Challenge of Manual Cash Application
When a customer sends a payment, the data often arrives in a messy format. A single bank deposit might contain payments for three different invoices, or a customer might include a credit memo note in the wire transfer. Manually matching these requires:
- Identifying the correct customer from a string of text in a bank memo.
- Matching the payment to the specific invoice or credit memo.
- Ensuring the currency amounts align perfectly.
If you are manually creating Customer Payment records one by one from a Bank Deposit, you are essentially performing double data entry. This is where the automated Transaction Matching and automated reconciliation features become critical tools for simplifying the workflow.
using Automated Cash Application
NetSuite provides specific functionality designed to bridge the gap between bank data and AR records. When using the Match Bank Data screen, NetSuite can attempt to "read" the transaction details.
How it Works
The system looks for specific identifiers within the bank letters or memo fields. If a customer provides an invoice number in the payment reference, NetSuite can attempt to match that string against the tranid (Transaction ID) of an outstanding invoice.
Key Limitations to Note
While capable, the limitations of this automated flow:
- Cross-Currency Limitations: Automated Cash Application often struggles with cross-currency payments. If the bank deposit is in a different currency than the invoice, the system may not be able to perform the automated match. In these cases, you must manually record and deposit the payment first, then reconcile it against the bank statement.
- Data Integrity: The success of this feature depends on how consistently your customers provide information. If a customer provides "Invoice #12345" and the actual ID in NetSuite is "INV-12345," the automated match may fail unless the string is clean.
simplifying the Workflow: Step-by-Step
To effectively work with these tools, you must follow a specific workflow that aligns with NetSuite's internal logic.
Step 1: Identifying the Payment
Navigate to Transactions Bank > Match Bank Data. This is where you reconcile the bank's "Statement Line" with your internal records.
Step 2: Using Automated Cash Application
When you select a transaction in the Match Bank Data screen, look for the Cash Application functionality.
- If a match is found, NetSuite will attempt to create a Customer Payment record.
- If the system identifies a pattern (e.g., a specific customer name or invoice number), it will "memorize" this rule for future transactions.
Step 3: Handling Complex Scenarios
For complex scenarios where multiple invoices are paid in one lump sum, or for cross-currency transactions, the automated tool may not be sufficient. In these cases:
- Create a Customer Payment record manually.
- Select the correct Entity (Customer).
- Apply the payment to the relevant invoices or credit memos.
- Once the Customer Payment is saved, go back to the Match Bank Data screen and match that specific payment record to the bank deposit.
Automating Payment Matching with SuiteScript 2.1
For high-volume environments, relying solely on the UI's automated match can still be tedious. You can use SuiteScript to programmatically validate or create payments based on specific criteria, such as matching a unique identifier in a custom memo field.
The following example demonstrates how to use the N/record module to programmatically create a Customer Payment. This is useful if you are building a custom tool to ingest bank files and want to automate the creation of the customerpayment record.
/**
* @NApiVersion 2.1
* @NScriptType UserEventScript
*/
define(['N/record', 'N/log'], (record, log) => {
/**
* Example function to create a Customer Payment record.
* This demonstrates the correct use of the Record API for
* creating a customer_payment.
*/
const createCustomerPayment = (customerId, invoiceId, amount) => {
try {
// Create the customer payment record
// Note: The internal ID for a Customer Payment is 'customerpayment'
const paymentRec = record.create({
recordType: record.Type.CUSTOMER_PAYMENT,
companyName: 'Your Company Name' // Placeholder for company context
});
// Set basic header information
paymentRec.setValue({ fieldId: 'entity', value: customerId });
paymentRec.setValue({ fieldId: 'amount', value: amount });
// Set the transaction date (e.g., today)
paymentRec.setValue({ fieldId: 'trandate', value: new Date() });
// Add the line item (Invoice)
// Note: In a real scenario, you would loop through multiple invoices
paymentRec.setSublistValue({
sublistId: 'apply', // The sublist for applying to invoices/credits
fieldId: 'apply',
line: 0,
value: invoiceId
});
const recordId = paymentRec.save();
log.audit({ title: 'Success', details: 'Created Payment ID: ' + recordId });
return recordId;
} catch (e) {
log.error({ title: 'Error Creating Payment', details: e.name + ': ' + e.message });
return null;
}
};
return {
// Example entry point for a User Event or similar trigger
beforeSubmit: (scriptContext) => {
// Logic to handle record validation or processing
}
};
});
Key Technical Details in the Code:
- Record Type: We use
record.Type.CUSTOMER_PAYMENTas the identifier for the record type. - Field IDs: Note the use of
entityfor the customer andamountfor the payment value. - Sublist Handling: The
applysublist is used to link the payment to specific invoices. - Error Handling: Always wrap record creation in a
try..catchblock to log errors properly usinglog.error().
For more detailed information on handling record creation and sublist interactions, refer to the SuiteScript Developer Guide.
Comparison of Reconciliation Methods
Mastering customer payment reconciliation means understanding how the bank's data maps to your internal records. Automated Transaction Matching works for standard invoices but isn't a magic bullet. Cross-currency transactions still need manual intervention. Know when to use the automated tools and when to step in manually, and your accounts receivable stay accurate with minimal effort during month-end.


