Case Study · Tutoring school · BC

Anonymized Case — A three-campus BC tutoring school: scheduling, attendance, package burn-down and payroll on one chain

A custom operations system for a three-campus tutoring school, in place of a per-seat scheduler — attendance is the single source of truth, and package burn-down, invoices and teacher hours are all derived from it.

Privacy note: the school is anonymized — institution name and student information have been removed. Only architecture, workflow and delivered outcomes are described.

Overview

A custom operations system for a three-campus tutoring chain, replacing a per-seat SaaS: student and family records, course catalog, recurring scheduling with conflict detection, attendance tracking, tuition packages/invoices/payments — with teacher hours pushed automatically to an employee-management system for payroll over versioned APIs. Client identity anonymized.

A tutoring school's operational pain is never 'one missing feature' — it's a broken data chain: scheduling in one system, attendance in spreadsheets, package reconciliation by hand, teacher hours re-tallied at month-end. Every link can fail, and every month repeats the same labor. The per-seat scheduler the school had been using was built for a general market; the school wanted its own workflow and its own data. We built them a custom operations system with one core design decision: attendance is the single source of truth, and everything else is derived from it.

The challenge

Three campuses shared a per-seat SaaS scheduler: recurring classes collided, attendance never matched package burn-down, package balances were maintained by hand, and teacher hours were tallied manually at month-end. More campuses meant more reconciliation and harder-to-trace errors.

Our approach

Rebuild the data chain around attendance as the source of truth. Student and family records, the course catalog, and recurring scheduling (with three-way conflict detection across teacher, room, and student) sit upstream. Once a class's attendance is confirmed, it automatically drives everything downstream: package deduction, invoice generation, payment reconciliation, and teacher-hour accumulation. Teacher hours are no longer tallied by hand — they push automatically over versioned APIs into the employee-management system we built for the same client group, feeding payroll. The system ships as modules, with unified data and per-campus permission isolation.

Results

Three campuses now operate in one system: scheduling conflicts are blocked at creation time; once attendance is confirmed, burn-down, balances, and invoices update automatically — month-end manual reconciliation is gone; teacher hours accumulate in real time and flow straight into payroll. The school is off the per-seat SaaS and owns its data outright.

Attendance as the single source of truth

Every flow of money and time in the system derives from attendance records:

  • Attendance confirmed → package hours deduct automatically, balances visible in real time.
  • Attendance accumulates → invoices generate from actual classes consumed; every line a parent sees is backed by an attendance record.
  • Attendance is hours → teacher pay accumulates from confirmed attendance, no month-end tally.
  • Attendance edits leave a trail → every backfill or correction is logged, so reconciliation is traceable.

This eliminates 'which number is right' by design: attendance is the only thing entered — everything else is computed.

Recurring scheduling with three-way conflict detection

Tutoring scheduling is hard because it recurs: a course runs the same slot for 20 weeks, and mid-term room changes, teacher swaps, and student transfers are routine. The system checks conflicts across teacher, room, and student dimensions at create and edit time — collisions surface before saving, not on the first day of class.

Hours straight to payroll: a versioned handshake between two systems

Teachers generate hours in the operations system and get paid in the employee-management system. The two talk over versioned APIs: the operations side pushes hours from confirmed attendance, and the payroll side receives with idempotency and version checks — retries never double-pay, and interface evolution never breaks reconciliation.

  • Idempotent pushes: the same class's hours can't be booked twice by a retry.
  • Versioned interfaces: either side can upgrade without breaking the other's reconciliation.
  • The employee-management system is our own standalone product (12 toggleable modules: time clock, time off, reviews, tasks, commission, payroll, and more).

Technical breakdown

  • Python (Flask) backend + PostgreSQL + Redis task queue, Next.js frontend, deployed with Docker Compose.
  • Shares one platform architecture with the CRM and employee-management products for the same client group — deliberately copied, not shared-library-coupled, so each product evolves independently.
  • Modular delivery: records, scheduling, attendance, packages, and invoicing/payments are independent modules, enabled as needed.
  • One database across three campuses with per-campus permission isolation; cross-campus reporting works out of the box.

Reusable lessons

  • The first design decision of an operations system is choosing the single source of truth. Choose wrong (or not at all) and everything downstream becomes reconciliation.
  • Moving off a general-purpose SaaS is less about subscription fees than about owning the data and fitting the school's own workflow.
  • Cross-system money interfaces must be idempotent and versioned, or every retry and upgrade is a financial incident.

Modules used

Want results like these?

Tell us about your business and we'll scope a paid proof of concept.