Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The NetSuite Pro

The NetSuite Pro Logo The NetSuite Pro Logo

The NetSuite Pro Navigation

  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • NetSuite Customization
    • NetSuite Integration
    • NetSuite Advanced PDF Templates
    • NetSuite Reporting & Analytics Guide
    • Real-World NetSuite Examples
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask A Question
  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • NetSuite Customization
    • NetSuite Integration
    • NetSuite Advanced PDF Templates
    • NetSuite Reporting & Analytics Guide
    • Real-World NetSuite Examples
  • Blog
  • Contact Us
Home/ Real-World NetSuite Examples/Automating Supplier Invoice Matching with SuiteScript 2.x

Automating Supplier Invoice Matching with SuiteScript 2.x

💼 Business Context

Accounts Payable teams often spend hours manually verifying supplier invoices against Purchase Orders and Item Receipts — a process known as invoice matching.
In NetSuite, this ensures you only pay for goods and services that were actually ordered and received.

  • 2-Way Match: Compares the vendor invoice to the Purchase Order (PO) — checking quantities, prices, and amounts.
  • 3-Way Match: Adds a goods receipt (Item Receipt) to confirm that billed quantities were received before approval.

When performed manually, this is slow and prone to errors. By automating it with SuiteScript 2.x, you can validate invoices instantly, auto-approve matches, and route exceptions for human review.


⚙️ Why Automate Invoice Matching

BenefitDescription
Accuracy & Fraud PreventionReduces human error and detects overbilling or duplicate invoices before payment.
Efficiency & Cost SavingsAuto-approved invoices speed up the payables cycle, cutting processing costs.
Policy ComplianceEnforces tolerance rules ( e.g., ±3 % variance ) and ensures 3-way match for invoices > $5 000.
Audit Trail & VisibilityLogs all match results, variances, and approval decisions for audit readiness.

🧩 Solution Architecture & Workflow

1️⃣ Invoice Entry:
A Vendor Bill enters NetSuite (manually, via Bill Capture OCR, or through integration) and references a Purchase Order.

2️⃣ Trigger Match Logic:
A User Event or Scheduled/Map-Reduce Script runs to locate the related PO and Item Receipts.

3️⃣ Perform Comparisons:

  • Check invoice quantities ≤ ordered & received quantities.
  • Validate unit rates and amount totals.
  • Apply configured tolerances (e.g., ±5 %).

4️⃣ Take Action:

  • ✅ Within tolerance → auto-approve, set Match Status = Matched or change status to Approved.
  • 🚫 Exceeds tolerance → set Match Status = Exception, email AP manager, hold for review.

5️⃣ Re-check Pending Invoices:
A daily scheduled script re-evaluates invoices awaiting receipts — once items are received, the script can auto-approve them.

6️⃣ Exception Handling:
Unmatched invoices remain pending until reviewed or adjusted, ensuring no payment is released without validation.


🧠 SuiteScript 2.x Modules Used

ModulePurpose
N/recordLoad POs, Vendor Bills, and Item Receipts; update approval fields.
N/searchFind receipts, existing bills, and variance data efficiently.
N/runtimeRead script parameters (e.g., tolerance %) and execution context.
N/emailNotify AP teams of exceptions or auto-approvals.
N/log / N/errorCapture debug and error details for troubleshooting and audit trails.

🧱 Implementation Strategy

1️⃣ User Event Script (AfterSubmit)

Runs immediately when a Vendor Bill is created or edited.
Ideal for real-time feedback — auto-approves or flags the bill instantly.

Tip: Keep runtime light (< 5 seconds). Use one search per PO, not per line.

2️⃣ Scheduled Script

Processes bills in bulk (e.g., nightly) for performance or re-check scenarios.
Searches for Pending Approval bills and re-matches them.

3️⃣ Map/Reduce Script

Best for high volume.
Automatically yields and runs in parallel for hundreds of invoices, ensuring scalability and governance compliance.


🧩 Sample Code Snippet (Pseudo)

/**
 * @NApiVersion 2.x
 * @NScriptType UserEventScript
 * @Description Automated 2-way / 3-way invoice matching
 */

define(['N/record', 'N/search', 'N/runtime', 'N/email'], (record, search, runtime, email) => {

  function afterSubmit(context) {
    if (context.type !== context.UserEventType.CREATE && context.type !== context.UserEventType.EDIT) return;

    const bill = record.load({ type: record.Type.VENDOR_BILL, id: context.newRecord.id });
    const poId = bill.getValue('purchaseorder');
    if (!poId) return;

    const po = record.load({ type: record.Type.PURCHASE_ORDER, id: poId });
    const qtyTolerance = parseFloat(runtime.getCurrentScript().getParameter({ name: 'custscript_qty_tolerance' })) || 0;
    const rateTolerance = parseFloat(runtime.getCurrentScript().getParameter({ name: 'custscript_rate_tolerance' })) || 0;

    let hasException = false;
    let messages = [];

    const lineCount = bill.getLineCount({ sublistId: 'item' });
    for (let i = 0; i < lineCount; i++) {
      const qtyBill = parseFloat(bill.getSublistValue({ sublistId: 'item', fieldId: 'quantity', line: i })) || 0;
      const qtyOrdered = parseFloat(po.getSublistValue({ sublistId: 'item', fieldId: 'quantity', line: i })) || 0;
      if (qtyBill > qtyOrdered + qtyTolerance) {
        hasException = true;
        messages.push(`Line ${i + 1}: Qty ${qtyBill} > PO Qty ${qtyOrdered}`);
      }
    }

    record.submitFields({
      type: record.Type.VENDOR_BILL,
      id: bill.id,
      values: {
        custbody_match_status: hasException ? 'EXCEPTION' : 'MATCHED'
      }
    });

    if (hasException) {
      email.send({
        author: -5,
        recipients: ['ap@company.com'],
        subject: `Invoice Exception – Bill ${bill.getValue('tranid')}`,
        body: messages.join('\n')
      });
    }
  }

  return { afterSubmit };
});

⚡ Edge Cases Handled

  • Minor Variance: Within tolerance → auto-approve.
  • Partial Receipt: Re-check daily until received quantities match.
  • Over-billing / Unauthorized Item: Flag and hold payment.
  • Duplicate Invoices: Detect same vendor + invoice number.
  • PO-less Invoices: Skip auto-approval and route for manual review.
  • Multi-PO Invoices: Supported via custom logic or RESTlet integration.

🧮 Integration & Extensions

IntegrationPurpose
NetSuite Bill CaptureOCRs supplier invoices → feeds data to matching script.
Third-Party AP AutomationPlatforms like Stampli or Tipalti handle OCR + push to NetSuite; SuiteScript validates.
RESTlet IntegrationExternal systems can POST invoice data and trigger matching on creation.

🧰 Deployment & Best Practices

  • ✅ Test in Sandbox with real PO/Bill data.
  • 🕐 Schedule batch scripts off-peak hours.
  • ⚠️ Enable “Enforce Unique Reference” to prevent duplicates.
  • 🔄 Use Match Status custom field for workflow control instead of directly setting Approved.
  • 🧩 Phase Deployment: start in “log-only” mode to monitor behavior before auto-approval.
  • 📧 Email alerts for exceptions and include PO + Vendor details for AP visibility.

🧩 Summary

Automating 2-way and 3-way invoice matching in NetSuite using SuiteScript 2.x transforms Accounts Payable from a manual control task to a streamlined, auditable process.
Matched invoices move straight to payment; exceptions are flagged instantly for review.
The result: faster AP cycles, fewer errors, and stronger financial controls.

Share
  • Facebook

Leave a ReplyCancel reply

Sidebar

Ask A Question

Stats

  • Questions 6
  • Answers 6
  • Best Answers 0
  • Users 3
  • Popular
  • Answers
  • Rocky

    Issue in running a client script in NetSuite SuiteScript 2.0 ...

    • 1 Answer
  • admin

    How can I send an email with an attachment in ...

    • 1 Answer
  • admin

    How do I avoid SSS_USAGE_LIMIT_EXCEEDED in a Map/Reduce script?

    • 1 Answer
  • admin
    admin added an answer The issue is usually caused by following Wrong script file… September 14, 2025 at 10:33 pm
  • admin
    admin added an answer Steps to send an Invoice PDF by email: define(['N/email', 'N/render',… August 28, 2025 at 3:05 am
  • admin
    admin added an answer This error means your script hit NetSuite’s governance usage limit… August 28, 2025 at 3:02 am

Top Members

Rocky

Rocky

  • 1 Question
  • 22 Points
Begginer
Sophie1022

Sophie1022

  • 0 Questions
  • 20 Points
Begginer
admin

admin

  • 5 Questions
  • 2 Points

Trending Tags

clientscript netsuite scripting suitescript

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help

Footer

Menu

  • Home
  • About Us
  • Tutorials
    • NetSuite Scripting
    • NetSuite Customization
    • NetSuite Integration
    • NetSuite Advanced PDF Templates
    • NetSuite Reporting & Analytics Guide
    • Real-World NetSuite Examples
  • Blog
  • Contact Us

Quick Links

  • NetSuite Scripting
  • NetSuite Customization
  • NetSuite Advanced PDF Template
  • NetSuite Integration
  • NetSuite Reporting & Analytics

Subscribe for NetSuite Insights....

© 2025 The NetSuite Pro. All Rights Reserved