How to Email Daily Revel POS Sales Summaries to Store Managers
Build a Spojit workflow that runs every night, pulls the day's Revel orders for each location, totals sales and covers into a per-store CSV, and emails a formatted summary to your store managers.
What This Integration Does
Multi-location restaurant and retail operators need each store manager to start the day knowing how yesterday performed: total sales, order count, and average ticket. Pulling those numbers by hand from Revel every morning is slow and inconsistent. This workflow does it for you: once a night it reads the previous day's orders from Revel, groups them by establishment (location), computes the totals with the Math connector, writes a clean per-store table with the CSV connector, and sends a daily summary email from Spojit's built-in mail service.
The run model is a Schedule trigger on a nightly Unix cron in your own timezone. On each run the workflow resolves the reporting window (yesterday, midnight to midnight), fetches the matching Revel orders with list-orders, aggregates per establishment, builds a CSV body, and emails the summary plus the CSV attachment to managers. Nothing is written back to Revel, so the workflow is read-only and safe to re-run: triggering it again for the same date simply regenerates and re-sends the same figures. Each execution is independent and leaves no state behind.
Prerequisites
- A Revel connection added under Connections with API access to the establishments you want to report on. See the Revel Systems connector article for setup.
- The Revel establishment (location) ID for each store, plus a manager email address for each. Keep this mapping handy; you will paste it into a small lookup early in the workflow.
- Manager email addresses added to your org allowlist under Settings → General → Email recipients if any are external to your workspace, so the Send Email node can deliver to them.
- The CSV and Math utility connectors, which are built in and need no authentication.
Step 1: Add a Schedule trigger for the nightly run
Create a new workflow and set the Trigger node type to Schedule. Add a 5-field Unix cron expression and an IANA timezone so the report always fires after close in local time. For a 2:00 AM run every day in Sydney, use:
Cron: 0 2 * * *
Timezone: Australia/Sydney
Running after midnight means the previous calendar day is fully closed before you report on it. The trigger output is { scheduledAt }, an ISO timestamp you will use in the next step to compute the reporting window. A single Schedule trigger can hold multiple schedules if you later want, for example, a second region in a different timezone.
Step 2: Compute yesterday's reporting window with the Date connector
Add a Connector node in Direct mode using the Date connector and the start-of tool to find the start of today, then a second Date node with subtract to step back one day. This gives you a clean midnight-to-midnight window that does not drift with the exact trigger time.
start-of:
date: {{ trigger.scheduledAt }}
unit: day -> {{ today_start.iso }}
subtract:
date: {{ today_start.iso }}
value: 1
unit: day -> {{ window_start.iso }} (yesterday 00:00)
Use {{ window_start.iso }} as the lower bound and {{ today_start.iso }} as the upper bound. Both are ISO 8601 strings, which is exactly what Revel's date filters expect.
Step 3: List yesterday's orders from Revel
Add a Connector node in Direct mode for the Revel connector and pick the list-orders tool. Filter to the reporting window with created_date__gte and created_date__lte, sort newest first, and raise the limit high enough to cover a busy day. Leave establishment empty so you receive orders for all locations in one call, then group them yourself in the next step.
list-orders:
created_date__gte: {{ window_start.iso }}
created_date__lte: {{ today_start.iso }}
ordering: "-created_date"
limit: 500
If a single store can exceed your limit in a day, page through results by repeating the call with offset, or narrow the call by passing one establishment ID at a time inside a Loop over your store list. The order records carry the per-order total and the establishment field you will group on.
Step 4: Aggregate sales and covers per store with the Math connector
Add a Transform node to reshape the raw orders into one row per establishment: order count, summed sales, and a covers tally if your orders carry a guest count. For the money math, use Connector nodes in Direct mode on the Math connector. The sum tool totals an array of order amounts and average gives you the average ticket; pass the per-store arrays your Transform produced.
sum:
numbers: {{ store.orderTotals }} -> {{ store_sales.result }}
average:
numbers: {{ store.orderTotals }} -> {{ store_avg.result }}
round:
number: {{ store_avg.result }}
decimals: 2 -> {{ store_avg_rounded.result }}
If you have several stores, wrap this aggregation in a Loop node set to ForEach over your store list so each location gets its own sum and average. Collect each result into an array of objects shaped like { store, location, orders, sales, avgTicket, covers } for the CSV step.
Step 5: Build the per-store CSV with the CSV connector
Add a Connector node in Direct mode for the CSV connector and use the from-json tool to turn your array of per-store rows into a CSV string. Pass the columns array to fix the column order so the report reads the same every day. Optionally chain a sort call to rank stores by sales.
from-json:
data: {{ store_rows }}
columns: ["location", "orders", "sales", "avgTicket", "covers"]
header: true
sort:
csv: {{ csv_from_json.result }}
columns: ["sales"]
orders: ["desc"]
The result is a plain CSV string you can drop straight into the email body and attach as a file. Keep the column set small and consistent so managers can scan it on a phone.
Step 6: Email the summary to store managers
Add a Send Email node. It sends from Spojit's built-in mail service, so no connection is required. Put the manager addresses in Recipients (comma-separated and templated), template the Subject with the report date, and place a short headline plus the CSV in the Body. Set If sending fails to Continue anyway if you would rather log a delivery problem than fail the whole report.
Recipients: {{ managers }}
Subject: Daily Sales Summary - {{ window_start.iso }}
Body: Yesterday's sales by location:
{{ sorted_csv.result }}
Replies go to the operations team.
Only upstream variables resolve in the email, so compute everything (date label, totals, CSV) before this node. Each external recipient must be on your org allowlist, and the send counts toward your monthly email allowance. If you need the mail to come from your own restaurant domain instead, swap the Send Email node for the Resend or SMTP connector.
Tips
- Per-manager delivery: if each manager should see only their own store, wrap Steps 4 to 6 in a Loop over your store-to-manager mapping and send a separate Send Email per location.
- Ask Miraxa, the intelligent layer across your automation, to scaffold the skeleton with a prompt like "Build a workflow on a nightly schedule that lists Revel orders for yesterday, totals sales per establishment with the Math connector, builds a CSV, and emails it." Then fine-tune fields in the properties panel.
- Keep the CSV columns short and stable so the daily email stays readable and easy to diff day over day.
- If you only need one or two locations, pass a single
establishmentID intolist-ordersto keep each call small and fast.
Common Pitfalls
- Timezone drift: set the IANA timezone on the Schedule trigger and reuse
{{ trigger.scheduledAt }}for the window. A UTC-based window can pull the wrong calendar day and split a dinner service across two reports. - Pagination:
list-ordersreturns up tolimitrecords. A high-volume store can exceed it, silently dropping orders from the totals. Page withoffsetor filter perestablishment. - Missing covers: not every Revel order carries a guest count. Treat covers as optional in your Transform and default to the order count so the report never errors on a blank field.
- Allowlist blocks: external manager addresses must be on the org allowlist or the Send Email node will not deliver to them.
Testing
Before relying on the schedule, validate on a small scope. Temporarily hard-code {{ window_start.iso }} and {{ today_start.iso }} to a recent date you already know the numbers for, then run the workflow with the Run button. Check the execution log to confirm list-orders returned the expected count, that the Math results match a manual spot-check, and that the CSV columns are correct. Send the first email to yourself instead of the managers, compare the figures against Revel's own reports, then switch the recipients and re-enable the Schedule trigger.