All work
LiveWeb app added · Oct 2026

School Tuition Ledger

A six-workflow n8n system that moved a school’s tuition collection, its accounts receivable (AR), off scattered manual tracking and onto one automated ledger, with a person approving every payment. A web app added in October 2026 gives the accounting office one place to encode, approve and look things up, without changing how the automations work.

ClientEducational institution
RoleSole developer
TimelineJun 15 – Jul 3, 2026 · web app Oct 2026
Stackn8n · Sheets · Apps Script web app · Gmail
Approvals screen of the AR Ledger web app on a demo school: pending payments with OR number, method, amount and balance, each with Reject and Confirm buttons; one GCash payment is flagged because no screenshot is attached
The approvals screen. The head accountant sees each payment’s balance and any warnings, like a GCash payment with no screenshot, then confirms; n8n does everything after that click. Every screen on this page is the demo: the same app on a made-up school, because the school asked that nothing from the live system be shown.
Try the demoTry the demo

Switch between the two roles. Nothing is saved.

No single source of truth

Payments taken at the counter weren’t in the official ledger until someone copied them over by hand. Parents had no consistent receipt or reminder, and leadership’s monthly collection report was compiled manually.

The billing model made it harder. Tuition is spread over ten months, June to March, and a missed month isn’t its own overdue line: it rolls into the next open month. Tracking that by hand across hundreds of accounts is slow, and every mistake costs the school money.

One approval, six automations

A payment is logged, through a Google Form at first and the web app since October 2026. It lands in a pending queue. The head accountant reviews it and marks it confirmed. From that one confirmation, n8n does the rest.

1Confirmed Payment SyncEvery 2 minWrites each confirmed payment to the ledger with a sequential ID and a duplicate check.
2Parent Payment EmailOn confirmSends the receipt. Kept separate so a slow email can never hold up a ledger write.
3Monthly Due Reminder2 days beforeReminds parents before a due date instead of after it’s missed.
4Admin Pending SummaryDaily, 4:00 PMLists payments still waiting for a decision. Skips the email when nothing is pending.
5Principal Monthly Summary1st of monthReplaces the hand-compiled collection report.
6Error AlertsAlways onWatches the other five and reports any workflow error the same day.
Google Sheet of logged payments with a Status dropdown set to Confirmed or Pending on each row, and Migrated and Confirmation Sent columns filled in on the confirmed rows; student names, IDs, OR numbers and amounts are blurred
The pending queue on the school’s live sheet. The head accountant marks a payment Confirmed (in the sheet at first, in the web app now); n8n then stamps the row as migrated and records whether a receipt went out. Names, IDs, OR numbers and amounts blurred.
The main path of the Confirmed Payment Sync workflow in n8n: fetch the confirmed row, look up the student, check the student was found, read existing payments, generate the payment ID, check for a duplicate OR number, append to PAYMENTS and stamp the pending row as migrated
1 · Confirmed Payment Sync, its main path. One row at a time: find the student, check for a duplicate, then write to the ledger. The full workflow opens on zoom.
Show the other five workflowsHide them
n8n canvas of the Parent Payment Email workflow
2 · Parent Payment Email
n8n canvas of the Monthly Due Reminder workflow
3 · Monthly Due Reminder
n8n canvas of the admin pending summary workflow
4 · Admin Pending Summary
n8n canvas of the principal monthly summary workflow
5 · Principal Monthly Summary
n8n canvas of the Error Alerts workflow
6 · Error Alerts

October 2026 · live since Oct 24

A front desk for the office

Three months in, the automations ran on their own, but the office still worked inside the spreadsheet. Payments came in through a Google Form. Approving one meant changing a cell. Adding a student meant typing rows across four tabs, and uniform orders were sizes typed into cells.

So I built a web app on top of the same Google Sheet: one screen for the accountant who encodes, and one for the head accountant who approves. The six n8n workflows didn’t change. The app writes each payment into the same pending queue the Google Form used, in the same format, so n8n picks it up exactly as before. It just arrives cleaner.

Try the demo

Switch between the two roles. Nothing is saved.

Try it here

The working app on a made-up school. Use the switcher at the top to change roles. Nothing is saved.

AR Ledger web app dashboard for a demo school: total billed, collected, outstanding and due-this-month figures, outstanding balance by grade level, and collections by month
Dashboard. Totals, who is behind, and collections by month, from the same sheet the automations write to.
Show 4 more screensHide them
Encode payment form on a phone: student, amount, OR number, payment date, method and receipt upload
Encode payment, on a phone.
Student record panel showing total accounts, paid and balance, and a ten-month schedule with paid, carried and upcoming months
A student’s record, with the ten-month schedule and carry-over.
Uniforms page with pieces ordered, amount charged, and a supplier count table of items by size
Uniforms. Orders are charged to the student’s account, and the supplier count is ready to send.
Backups screen: a monthly backup on the last night of the month at 11 PM, the last 12 kept in a private folder shared with the head accountant only, a Back up now button, and a backup with matching row counts
Backups. A copy of the ledger every month, kept private to the head accountant, plus a button for an extra one before big changes.

Two roles, two screens

Accountant

  • Encodes payments with the OR number and GCash screenshot
  • Sees each student’s balance and what’s due before saving
  • Fixes and resubmits anything sent back
  • Logs uniform orders

Head accountant

  • Approves payments, one at a time or all at once
  • Adds new students in one form instead of four tabs
  • Sets the school year’s due dates and reminder timing
  • Manages who can sign in, and sees every change in an activity log
  • Backs up the ledger: monthly on its own, or on demand

How it was built and tested

A simulated school year first. Before touching the school’s sheet, the app ran on a copy with 396 students, 1,252 payments and 861 uniform order lines, June to October. Approved payments and the ledger matched to the peso.

Built with AI assistance. I wrote the requirements and made the design decisions: what the app may and may never write, the two-person rule, the uniform rework. Most of the code was written with Claude, an AI assistant, and I reviewed it, tested it on the simulated year, and deployed it.

No new running costs for the app. It runs as Google Apps Script inside the school’s own Google account, next to the sheet it already uses.

Automate around the decision

A person approves every payment

This was the school’s call, and it’s the same two-step check accountants use: one person records, another confirms. n8n can’t check that money actually arrived, whether cash at the counter or a GCash screenshot, so it never confirms a payment on its own.

Two people per payment, enforced

The school’s rule used to depend on habit. Now the person who encodes a payment can’t approve it.

The app never records money

n8n is still the only thing that writes to the payment ledger. The app can only add a payment to the queue and mark it confirmed or rejected, so the old workflows keep working untouched.

Money and email never share a workflow

More workflows to maintain, but the ledger can’t be held up by the part that’s allowed to be flaky.

Show 8 moreHide them

Automate the work, not the control

People still enter and confirm each payment. Everything after the confirmation (the ledger entry, the receipt, reminders and reports) runs on its own.

Gap-free IDs, one batch at a time

Each sync run takes the highest existing ID and counts up, processing confirmations as one batch so IDs stay sequential.

A schedule over a native trigger

Reading and filtering the sheet every two minutes proved more reliable than the Sheets row-update trigger.

A dropdown that only lists real students

Apps Script fills the payment form with the live roster, so a payment can’t be logged against a mistyped name.

Mistakes caught while typing

OR numbers are checked against every past and pending payment, and the approval screen flags a missing screenshot, an amount over the balance, or the same amount twice in three days.

Uniforms became order lines

Each item is its own line, charged to the student’s account. The office gets a supplier count by size, and the balance stays correct when an order changes.

Backups stay in the school’s account

Each month a copy of the ledger is saved to a private folder in the school’s own Google Drive, shared only with the head accountant. The last 12 are kept.

Columns found by name, not position

The live sheet isn’t laid out exactly like my test copy. The app looks up every column by its header, so it works on both.

Bugs only real data could show

An empty lookup silently stopped everything after it

When a Sheets lookup found no rows, n8n halted the rest of the workflow with no error and no log. It showed up across most of the six workflows. The fix was one setting, applied to every lookup, so “nothing pending today” is handled on purpose.

Low-code tools can fail without saying so.

Two grade levels showed 0% collected

The report assumed grade names that didn’t match the real roster (“Nursery 1”, “KINDER”). Groupings now come from the roster itself instead of a hardcoded list.

Test data catches logic errors. Only real data catches data errors.

What changed

Confirmed payments reach the ledger automatically, with no re-typing.

Parents with an email on file get receipts and reminders without staff sending them, and two recurring manual reports are gone.

Payments are encoded and approved in one app. The Google Form is closed, so every payment passes the same checks before anyone confirms it.

The school’s rule that a person approves every payment stayed in place, and the app now enforces it: whoever encodes a payment can’t approve it.

Uniform orders are charged to the student’s account, and a copy of the ledger is saved every month.

Time per task, before and after

TaskBeforeAfter
Recording a confirmed payment~5–10 min~30 sec–1 min
Approving the day’s payments~25 min~8 min
Checking pending or unconfirmed payments~30–60 min a day~5–10 min a day
Checking a student’s payment history or balance~5 minUnder 1 min
Adding a new student~5 min~2 min
Counting uniforms for the supplier~30 min~10 min
Preparing the monthly collection report~2–4 hrsAutomated
Sending payment receipts~1–2 hrs a monthAutomated
Sending due-date reminders~1–2 hrs a monthAutomated

Estimates from the school’s head accountant, who does this work every day. Not measured with a timer.

Chu was easy to work with. He took the time to understand how we actually do things in the school and then built the system around that. He was also easy to communicate with, and whenever we had an issue or something needed to be adjusted, he was able to help us figure it out.

Teresa BaldecasaHead accountant · runs the tuition ledger

Planned for the end of SY 2026–2027: receipts and due-date reminders by text message as well as email, and a one-step move to the next school year (students move up a level, unpaid balances carry forward, the old year is kept on file). Details to be confirmed with the school.

From first meeting to live

Jun 15 first meetingJul 3 the six workflows go liveOct 24 the web app goes live

Show the week-by-week timelineHide the timeline
  1. Week 1 · Jun 15

    First meeting, at the school

    The school

    Teresa, the school’s head accountant, walked me through the manual ledger: missed payments, duplicate entries, and no easy way to keep track.

    Me

    I suggested Google Sheets as the system of record instead of a custom app. It was more practical and cost-effective for what they needed.

  2. Week 2

    Agreeing the base, first build

    The school

    Agreed on Google Sheets after some back-and-forth over WhatsApp. Asked for a way for the principal to see reports.

    Me

    Built the ledger sheet with its formulas and scripts, mapped the payment rules, and started with two workflows: Confirmed Payment Sync and Parent Payment Email. Added a Principal Monthly Summary for the reports, instead of another platform.

  3. Week 2, later

    The scope grows, with approval

    The school

    Approved the extra automations.

    Me

    Suggested the rest: due-date reminders, a daily pending list for the head accountant, and error alerts. That made six workflows.

  4. Week 3

    Their real data, then testing

    The school

    Their existing ledger was moved into the new sheet.

    Me

    Ran and monitored every workflow on their real data before go-live. That’s where two problems showed up that test data never would have: a lookup that stopped silently on days with nothing pending, and grade names that didn’t match the real roster.

  5. Jul 3

    Live

    The school

    The system went into daily use.

    Me

    Deployed it on site at the school. It’s still live.

  6. Oct 2026

    A web app on top of the ledger

    The school

    Agreed to replace the Google Form, and set one rule: nothing from the live system on the portfolio.

    Me

    Built the web app with AI assistance and tested it on a simulated school year, plus a converter for the old uniform records. The six workflows stayed exactly as they were.

  7. Oct 24

    Web app live

    The school

    Closed the Google Form. Payments now come in through the app.

    Me

    Converted the uniform records, set up the accounts and trained both roles on site.

All work

Hiring, or have a process to automate?

Let’s talk.

Send a few lines about the role, or what keeps slipping through.

Write to me

ralphmatthewmarty@gmail.com

Or message me

WhatsApp +63 919 947 0840

Or connect

LinkedIn

Replies within one business day · UTC+8

Good to know

Based in

Central Luzon, PH (UTC+8)

Looking for

Full-time remote roles; contract too

Works

Remote; hybrid or on-site in the Philippines