Hy An is a small retail business (under 10 people) selling across Facebook, TikTok Shop, and Shopee, managed through Pancake POS. Like most companies this size, they don’t have a dedicated accountant or finance team. The owner tracks everything himself, alongside running the actual business.
For a while, an Excel spreadsheet worked fine. Three side-by-side panels per month (one per bank account), every inflow summed as revenue. That’s a reasonable setup when you’re small and moving fast. But as the business grew across more channels, internal transfers between accounts started getting counted as income too. The spreadsheet couldn’t tell the difference between a customer payment and money being moved from one company account to another.
By Q1 2026, this was inflating the revenue figures significantly. Over 90% of the error came from internal transfers, the rest from owner capital movements. The P&L looked healthy on paper. The real numbers told a different story.
The owner was making decisions (marketing spend, inventory bets, cash planning) based on numbers that didn’t reflect reality. On top of that, he was manually copying Pancake order data into the sheet whenever he needed to cross-check revenue, a few hours of copy-paste a month he didn’t have.
A spreadsheet that tells the truth, updated automatically
I rebuilt his financial tracking in Google Sheets with two things the old Excel couldn’t do: a classification tag on every transaction (so the sheet knows what’s a real sale), and a daily automated pull from Pancake (so the order data is never stale).
Tagging every transaction
The old Excel file had no way to tell if money coming in was a real sale or an internal transfer. That’s not a mistake, it’s what happens when one person is running the whole business. So the first job was going back through every historical transaction and tagging it.
| Tag | What it means | Counts in P&L? |
|---|---|---|
| Customer | Real external transaction | Yes |
| Internal | Transfer between company accounts | No |
| Owner capital | Owner capital in/out | No |
| Refund | Refund or return | Yes (negative) |
A script read the Vietnamese description on each transaction and applied the right tag automatically. 98% of transactions classified themselves. The remaining 2% got flagged for the owner to label by hand, once, and the sheet remembers.
Key idea: The P&L only counts rows tagged "Customer". Internal transfers and capital movements still exist in the data, but they're structurally invisible to the report. No one has to remember to exclude them.
Five tabs, one source of truth
The Google Sheet was created programmatically and has five tabs, each doing one job:
- Transactions: every line item with its classification, category, notes, and receipt links. Dropdowns enforce consistent entry. Missing classifications get highlighted yellow.
- Opening balances: the starting balance for each bank account, per month.
- Monthly P&L: pick a month, the whole report recalculates. Revenue broken down by retail and wholesale. Expenses grouped by COGS, operations, marketing, logistics. Profit or loss at the bottom. Pancake revenue reconciled against bank revenue.
- Yearly overview: a 12-month matrix of revenue, COGS, gross profit, expenses, and net profit side by side.
- Pancake orders: raw order data synced daily from Pancake POS. One row per order line item.
The owner selects a month in the P&L tab and the entire report rebuilds itself from the tagged transactions. No formulas for him to touch, no internal transfers sneaking in.
Pancake orders, automatically
Every morning at 6am Vietnam time, an automation pulls the full order list from Pancake and writes it into the Pancake Orders tab. The workflow clears the tab first so there’s no risk of duplicates, then pulls everything fresh.
Along the way it detects which platform each order came from (TikTok Shop, Shopee, or Facebook) based on the page ID, and translates order statuses into plain Vietnamese. If the sync fails (network issue, API hiccup), it retries automatically and emails me if it still fails. The owner doesn’t need to know it happened.
The side benefit: the P&L tab now compares Pancake revenue (orders) against bank revenue (money actually received). The gap is cash in transit, money from completed orders not yet deposited. He can see his cash flow timing at a glance.
Why this shape
Sheets over a database. The owner already lives in Sheets. Introducing a database would mean a new tool to learn, new logins, new fragility. Everything this system does fits comfortably inside a spreadsheet.
Full re-sync, not incremental. The automation re-imports all Pancake orders every morning rather than tracking what’s new. Simpler, and at a few hundred orders a day it’s fast enough that the simplicity is free.
What it runs on
| Component | Tool | Cost |
|---|---|---|
| Operational hub | Google Sheets | Free |
| Daily automation | n8n (self-hosted) | ~$5/mo VPS |
| Order data | Pancake POS API | Included in plan |
| One-time data cleanup | Python scripts | One-time |
Impact
- Phantom revenue eliminated. Internal transfers and owner capital no longer inflate the P&L. The numbers the owner looks at now are the real ones.
- Daily Pancake data syncs itself. No more manual copy-paste when he wants to check revenue.
- Cash flow visibility. The gap between Pancake revenue and bank revenue shows money in transit.
- Monthly reports rebuild with a single cell change.
- Channel breakdown (TikTok / Shopee / Facebook) is automatic.
The owner still runs the finances himself. He just doesn’t have to fight the spreadsheet anymore. The system does the heavy lifting, and he can focus on growing the business.