How to Sync Revel POS Orders to NetSuite
Push Revel Systems POS transactions into NetSuite for accounting.
What This Integration Does
Manually keying daily POS totals into NetSuite is fine for one store but quickly becomes the worst job in finance once you operate two or three. This workflow takes Revel's end-of-day transaction set, transforms it into the structure NetSuite expects (sales receipts, journal entries, or daily summaries depending on your accounting policy), and posts it nightly so the GL is always one day behind reality at most.
The workflow runs after business close, fetches every closed order for the trading day from Revel, aggregates by tender type, sales category, tax code, and location, and creates the matching records in NetSuite. It's idempotent on a per-day basis: re-running won't double-post because each record is keyed by the Revel order ID (for receipts) or by the trading-day date (for summary journals).
Prerequisites
- A Revel Systems connection with permission to list and read orders.
- A NetSuite connection with REST + SuiteQL access and permission to create the record type you'll post (Sales Receipt, Cash Sale, Journal Entry, or Daily Sales Summary).
- An agreed accounting policy: are you posting one record per order, or one summary journal per day per location? This decides the NetSuite record type.
- NetSuite reference data: location IDs, department IDs, tax codes, and the chart-of-accounts mappings for each Revel sales category and tender type.
Step 1: Schedule Trigger
Drop a Trigger node and set it to Schedule. Run it at 02:00 local time so the trading day is fully closed and any late voids have settled. The trigger exposes the previous run timestamp, but for accounting workflows you generally want to scope by trading day, not a rolling window.
Step 2: Compute the Trading Day
Add a Variable assignment using the date connector. Compute tradingDay as yesterday's date in the venue's local timezone. Some restaurants run a trading day that ends at 04:00 (so late-night covers stay on yesterday's books). Use the date start-of tool with the venue's offset to be precise.
Step 3: Fetch Closed Orders from Revel
Add a Connector node pointing at revel and pick list-orders. Filter to status = closed and the trading day window. Page through and store as {{ orders }}. For each order you'll need the line items, tenders, taxes, discounts, and location - if any of these aren't on the list response, follow up with get-order in a Loop to retrieve full detail.
Step 4: Transform to NetSuite Shape
Add a Transform node. The shape depends on your accounting policy:
- Per-order Sales Receipt - one NetSuite Sales Receipt per Revel order, with item lines mapped from Revel SKUs to NetSuite items.
- Daily Summary Journal Entry - one Journal Entry per location per day. Debit cash/clearing accounts by tender total, credit sales accounts by category total, credit a tax-payable account by tax total.
Use lookup tables (kept in MongoDB or a JSON variable) to map Revel categories and tender types to NetSuite account internal IDs. Stamp every output record with externalId set to revel-{{ orderId }} or revel-summary-{{ tradingDay }}-{{ locationId }} so the next step can idempotently upsert.
Step 5: Post to NetSuite
Wrap a Loop around the transformed records. Inside, add a Connector node pointing at netsuite. For new-only inserts use create-record; for idempotent re-runs use upsert-record with the externalId you stamped earlier. Configure:
- recordType:
salesreceipt,cashsale, orjournalentry - externalId:
{{ record.externalId }} - body: the transformed record payload
Per-node retries handle transient NetSuite throttling; for hard failures, route to a Slack notification so finance sees the breakage same-day.
Step 6: Reconciliation Check
After posting, add a Connector node calling run-suiteql on netsuite to sum what was just posted for the trading day:
SELECT SUM(amount) AS posted_total
FROM transaction
WHERE trandate = TO_DATE('{{ tradingDay }}', 'YYYY-MM-DD')
AND externalid LIKE 'revel-%'
Compare against the Revel-side total computed in Step 4. If they differ by more than rounding, post a slack send-message to the finance channel with the variance. Confidence in the sync depends on this check.
Tips
- Decide your record type up front - changing from per-order receipts to summary journals later means a re-import and a cleanup. Talk to the accountant before building.
- Cache the mapping tables - GL account mappings rarely change. Keep them in MongoDB and refresh on demand instead of on every run.
- Run a parallel branch for voids and refunds - they often need different account mappings to net sales. Use a Parallel node to keep them separate from regular sales lines.
Common Pitfalls
- Tip handling - tips collected at POS often pass through a clearing liability account, not revenue. Make sure your mapping reflects this or net income will be wrong.
- Multi-currency - if Revel operates in a different functional currency than NetSuite, set the exchange rate explicitly on each posting using NetSuite's
exchangeratefield, otherwise NetSuite uses today's rate which can drift. - Trading-day cutoff - midnight isn't always the cutoff. Late-night venues commonly run trading days to 04:00. If you query by raw date you'll split single nights across two records.
Testing
Pick a single quiet trading day from last week and run the workflow with the schedule disabled. Inspect the records created in NetSuite (or use NetSuite's preview mode), confirm GL totals match Revel's end-of-day report exactly, and verify the reconciliation SuiteQL returns the expected sum. Only then enable the daily schedule.