points in one system
The chain grows — adding a point takes 10 minutes: one row in the catalogue plus access grants.
A 15+ point restaurant chain used to live in notebooks, Excel files and group chats. We built a single accounting system on AppSheet + Google Sheets + Apps Script: every location runs its shift from a phone, all data flows into one sheet, the daily report self-arrives in the owner's Telegram. No in-house backend developer — maintained by a single data engineer.

At the location, a staff member opens the AppSheet app on a regular smartphone and lands on the active-shift dashboard. From there — big icons for every action: statistics, paid expenses, staff on shift, payroll accrual and payout, write-offs, inter-point transfers, invoice uploads, Z-report attachment. What needs to be done today sits on one screen. And the key part: AppSheet is cross-platform. The same app runs on iOS, Android and in the browser from a single schema. No separate iPhone / Android build, no App Store / Google Play publishing.



The same data the location enters, the owner reads from anywhere through AppSheet web. On the left — the per-shift card (day, point, opening time, status). In the centre — the expanded view with operational actions and expense/income tables. On the right — the «Today» table with active shifts across the chain: one row per open location.
The chain grows — adding a point takes 10 minutes: one row in the catalogue plus access grants.
At end of day, Apps Script computes the digest and pushes it to the owner's Telegram.
Owner, chain director, point manager, cashier, accountant — each sees only what's theirs.
No in-house backend developer: maintenance and growth — a few hours a week.
Opening, closing, status, linkage to a point and to employees, Z-report attachment (photo).
Paid expenses with item & supplier catalogues, units (pcs / kg / l), receipt photos.
Cash, terminal, cash-on-delivery — per shift, automatically rolled into the daily stats.
Hours × rate from the shift → statement; payouts logged as a separate operation linked to the employee.
A dedicated module with reason (spoilage, breakage, shortage) and the employee on shift.
Paired rows: one point gives, the other receives. Chain balance reconciles without manual entry.
Attach the invoice photo to the income row — search later by supplier and date.
Items, suppliers, expense categories, points, roles and rates — all editable in Google Sheets, no release.
5 roles, row filters in AppSheet by USEREMAIL() and point — each user sees only their own.
Morning report: which shifts are open across the chain. Evening: income, expenses, balance per point.
Dashboards in Sheets via QUERY() and SUMIFS() — revenue, expenses and payroll across points and periods.
Every change is written into a dedicated tab with author, time and old value — disputes resolve in a minute.



The on-site staff member opens «Paid expenses», picks an item from the catalogue (sugar, pepper, eggs, milk, mushrooms…), enters the amount and unit (pcs / kg / l), picks a supplier (veggies, lavash, store, delivery, advertising…) and saves. Linking to the open shift and the point — automatic, no manual entry. The same flow — for income, invoices, write-offs and inter-point transfers.
We'll build the accounting system for your chain on AppSheet + Google Sheets + Apps Script: a mobile app for the points, Telegram reports, multi-level access. Tell us what you need — we'll come back with architecture and a cost estimate in a couple of days.
An accounting system for a restaurant chain, built without an in-house developer — only a data engineer. Front — AppSheet (mobile + browser), data — one Google Sheet with 20+ tabs as a relational database, logic — Google Apps Script (validation, aggregates, cron-style triggers). Daily and evening reports go straight from Apps Script to Telegram via UrlFetchApp. 5 access roles are implemented through AppSheet security filters on top of USEREMAIL().

At the location, a staff member opens the AppSheet app on a regular smartphone and lands on the active-shift dashboard. From there — big icons for every action: statistics, paid expenses, staff on shift, payroll accrual and payout, write-offs, inter-point transfers, invoice uploads, Z-report attachment. What needs to be done today sits on one screen. And the key part: AppSheet is cross-platform. The same app runs on iOS, Android and in the browser from a single schema. No separate iPhone / Android build, no App Store / Google Play publishing.



The same data the location enters, the owner reads from anywhere through AppSheet web. On the left — the per-shift card (day, point, opening time, status). In the centre — the expanded view with operational actions and expense/income tables. On the right — the «Today» table with active shifts across the chain: one row per open location.
AppSheet compiles the app for iOS, Android and the web browser from a single declarative schema on top of Google Sheets. No React Native, no Flutter, no separate codebase — behaviour matches across platforms. On-site staff use it on their phone, the owner reads the same app in a browser from anywhere.
For a chain up to 30 points the data volume is tens of thousands of rows per year. Sheets handles that easily, AppSheet caches it, aggregates are computed with QUERY()/SUMIFS(). Paying for managed PostgreSQL and building an admin from scratch isn't economical at this scale.
A security filter is a formula that decides which rows of a table actually ship to a given user. Implementation: AND(USEREMAIL() = [email], OR([role] = 'admin', [point_id] = LOOKUP(USEREMAIL(), employees, email, point_id))). A line worker physically never receives someone else's rows on their device.
ScriptApp.newTrigger('sendMorningReport').timeBased().atHour(9).everyDays(1).create() — Google fires the function on schedule. No dedicated server / k8s / Docker — the script lives inside the document.
Apps Script calls the Bot API directly: UrlFetchApp.fetch('https://api.telegram.org/bot.../sendMessage', { method: 'post', payload: {...} }). No separate bot server, no webhooks, no hosting.
An Image-typed column in AppSheet stores the file in a target Drive folder and keeps the URL in the cell. The shift link goes through a ref to shifts.id. No separate object storage, no S3.
A transfer between points is one row with from_point and to_point. An AppSheet action atomically writes paired rows: -X on the sending location, +X on the receiving one. The chain balance reconciles without manual sheets.
In operational tables (shifts, paid_expenses) we keep the point's name and the employee's last name directly, not just an id — so the AppSheet card renders without a LOOKUP chain. Edits are rare; reads happen dozens of times a day.
An onEdit trigger writes into a log tab: timestamp, USEREMAIL(), table, column, old and new value. Staff disputes resolve in a minute.
Items, suppliers, points, rates live in separate tabs. Operational tables reference them through ref. Adding a new product = adding a row to a catalogue, no app release.
Maintenance — a few hours a week: read Apps Script logs, fix formulas, ship new modules. The chain gets a full accounting system at a consultant's cost.
Open/close, the Z-report photo attaches straight into the shift row through an AppSheet Image column.
An action appends a row to shift_employees(shift_id, employee_id, hours). Those hours flow into payroll.
Refs to items and suppliers catalogues, an Image column for the receipt, automatic linkage to the point's open shift.
Separate amounts per payment method, total computed as [cash] + [terminal].
Dedicated module with a reason (spoilage, breakage, shortage), the responsible employee taken from shift_employees.
An action writes paired -X / +X rows — chain balance reconciles without manual aggregation.
Accrual by hours × rate from the employees catalogue, payout — a separate operation with the receiver's signature.
An Image column stores the scan in Drive, filter by supplier and period — search in seconds.
Morning and evening reports across the chain via Apps Script + UrlFetchApp; digest format edited in the script.
5 roles via USEREMAIL() + lookup on employees.email → role / point_id. Line staff never receive other rows physically.
onEdit writes into a log: author, time, old and new value. Disputed shifts resolve in a minute.
QUERY() + SUMIFS() on a dashboard tab: revenue, expenses, payroll across points and periods — no BI tooling.



The on-site staff member opens «Paid expenses», picks an item from the catalogue (sugar, pepper, eggs, milk, mushrooms…), enters the amount and unit (pcs / kg / l), picks a supplier (veggies, lavash, store, delivery, advertising…) and saves. Linking to the open shift and the point — automatic, no manual entry. The same flow — for income, invoices, write-offs and inter-point transfers.
We'll build the accounting system for your chain on AppSheet + Google Sheets + Apps Script: a mobile app for the points, Telegram reports, multi-level access. Tell us what you need — we'll come back with architecture and a cost estimate in a couple of days.