How to Export Financial Reports to CSV and Upload via FTP
Generate financial reports and deliver them to your accounting team via FTP.
What This Integration Does
Plenty of accounting partners and audit firms still expect a CSV in a specific folder on an SFTP server every week. This workflow generates that CSV on a schedule, drops it in the expected location, and keeps the file naming and column order consistent so downstream tools never break.
The workflow runs weekly, pulls the previous week's transactions out of your ERP, aggregates the figures, converts the result to CSV, and uploads it to your FTP server. A Slack notification confirms each successful run and surfaces failures immediately.
Prerequisites
- A NetSuite connection (or other ERP) with read access to the transactions you want to report on.
- An FTP connection (FTP/SFTP) with write access to the target directory.
- A Slack connection for run notifications.
Step 1: Schedule Trigger
Add a Trigger node set to Schedule. Pick a cadence and time that matches your accounting team's review cycle (e.g., Mondays at 07:00 in their local timezone). The trigger exposes the current timestamp downstream.
Step 2: Compute the Report Window
Add a Transform (or Variable assignment) that calculates reportStart and reportEnd as the boundaries of the previous full week. Use the date connector's start-of and subtract tools to compute these reliably across daylight-saving boundaries.
Step 3: Query the Transactions
Add a Connector node pointing at netsuite using run-suiteql:
SELECT trandate, tranid, account, memo, amount, currency
FROM transaction
WHERE trandate >= TO_DATE('{{ reportStart }}', 'YYYY-MM-DD')
AND trandate < TO_DATE('{{ reportEnd }}', 'YYYY-MM-DD')
AND posting = 'T'
Fetch all the columns the receiving system expects. Add more queries (or a Parallel branch) if the report combines multiple data sources such as invoices and customer payments.
Step 4: Aggregate and Group
Add a Transform node to compute totals by category (or by account, or by department). Use the array connector's group-by tool and the math connector's sum tool for clean aggregations. The output should be the exact array shape the CSV will be built from.
Step 5: Convert to CSV
Add a Connector node pointing at the csv connector and pick the to-json tool's counterpart used to render a CSV string. Specify the column order so the receiving system never sees a surprise reshuffling. Use csv sort first if the report requires a specific row order.
Step 6: Upload via FTP and Notify
Add a Connector node pointing at ftp using upload-file. Configure:
- Path:
/reports/{{ reportEnd }}-weekly.csv - Body: the CSV string from the previous step.
After the upload, send a slack send-message to your finance channel with the filename, row count, and the report window. On failure, route to the same channel with the error details so on-call sees it instantly.
Tips
- Hash the CSV body with the encoding connector's
hash-sha256tool and include it in the Slack message. Auditors love being able to confirm the file wasn't modified after delivery. - Keep a copy in cold storage too. Drop the same CSV into S3 or a backup directory in case the FTP target deletes old files.
- If the file ever grows past a few MB, switch to streaming output rather than building the whole CSV in memory.
Common Pitfalls
- Timezone mismatch. The accounting team's "previous week" rarely matches your ERP's UTC week. Compute the window in their timezone with the date connector's
timezonetool. - FTP credentials expiring silently. Rotate via your connection settings and add a healthcheck workflow that uses ftp
verify-connectiondaily. - Excel auto-formatting. If the receiving team opens the CSV in Excel, leading zeros on account numbers vanish. Quote those columns or document a fixed schema with them.
Testing
Run the workflow once manually with a one-day window and a test directory on the FTP server. Open the resulting CSV, confirm the column order, row count, and totals match a spot check against your ERP, then enable the schedule.