---
title: "The Status That Gets You Paid: What Invoice Ninja, TutorCruncher and Fresha Build Around the Money"
date: 2026-09-24T00:00:00+00:00
source: https://saasreadyit.com/blog/the-status-that-gets-you-paid-invoice-ninja-tutorcruncher-fresha.html
---

# The Status That Gets You Paid: What Invoice Ninja, TutorCruncher and Fresha Build Around the Money

We read the documentation of three vertical SaaS products in three different
trades — invoicing, tutoring agencies, and salon and spa booking — and, for one
of them, its source code. We were looking for how each one models its records.

What we found was narrower and more useful: **each product has one status
change that the revenue depends on, and each builds machinery around that one
change.** One sends a reminder, one forces it through a till, and one
calculates it so nobody has to.

If you are building a product in any of these categories, that status is the
first screen to design. Everything below is quoted from the products' own
documentation or source, with links, so you can check it.

## The three, side by side

| Product | Trade | The status the money hangs on | What the product builds around it |
|---|---|---|---|
| TutorCruncher | Tutoring agencies | Awaiting Confirmation → **Complete** | Only Complete lessons are invoiced; a daily reminder chases tutors who haven't marked them |
| Fresha | Salons and spas | **Completed** | Can only be set by checking out through the point of sale, so every completed appointment has a sale |
| Invoice Ninja (v5) | Invoicing | **Overdue** | Never set by anyone — computed from the due date, so the chase list maintains itself |

## TutorCruncher: a lesson that happened is not yet a lesson you can bill

TutorCruncher's lesson statuses are Planned, Awaiting Confirmation, Complete and
Cancelled. The two in the middle are the interesting ones:

> **Awaiting Confirmation:** "The Lesson’s scheduled date/time has passed, but it is still awaiting being marked as ‘Complete’ (or cancelled) by an Administrator or Tutor."
>
> **Complete:** "The Lesson has been marked as ‘Complete’ by an Administrator or Tutor, and will be included in Invoices and Payment Orders."

So there is a state for *taught but not billable*. A lesson can be over and
still earn nothing, because nobody has confirmed it. Cancelled lessons, by
contrast, "will therefore not be included in any Invoices or Payment Orders."

The product knows this gap is where agencies lose money, so it ships an
automated email called **‘Reminder to mark Lesson(s) complete’**. Enabled, it
means tutors "are sent a daily email reminder to mark any Lessons that are
‘Awaiting Confirmation’ as ‘Complete’ if they haven’t done so within 24 hours." And if Auto Invoice is switched on, only lessons marked Complete are
invoiced automatically.

There is one more status worth knowing: **Cancel but still charge**, which marks
a lesson "Cancelled but Chargeable" — how an agency enforces a late-cancellation
fee without pretending the lesson happened.

## Fresha: you cannot finish an appointment without ringing it up

Fresha has five system statuses that, in its words, "can’t be edited,
reordered, or deleted": Booked, Confirmed, Completed, Cancelled and No-show.
Businesses can add their own in between — Fresha's examples are "Arrived" and
"Started".

The one that matters is Completed:

> "Set when the appointment is checked out through the point of sale."
>
> "It will always have a sale linked to it, but the payment may still be unpaid or part-paid."

There is no separate button to mark an appointment done. Finishing the service
and recording the sale are the same act, which means the appointment book and
the till can never disagree about what happened today. No-show, meanwhile, is
set manually, and only once the appointment's start time has passed.

## Invoice Ninja: Overdue is a calculation, not a job

Invoice Ninja's version 5 source code defines its invoice statuses as
constants: Draft, Sent, Partial, Paid, Cancelled and Reversed. Two more have
negative numbers, because they are never stored:

```php
public const STATUS_OVERDUE = -1; // ... due_date < now()
public const STATUS_UNPAID = -2;
```

Overdue is worked out from the due date every time you ask for it. Nobody marks
an invoice overdue, and nobody can forget to. The list of invoices to chase
builds itself.

Whether the client opened the invoice is recorded as well, but not as a status.
Opening an invoice runs `markViewed()`, which sets a `viewed_date` on the
invitation and `last_viewed` on the invoice — a timestamp beside the status.

**A correction, stated plainly.** When we first researched this category we read
Invoice Ninja's older documentation, which lists "Viewed" as a status, and
recorded it that way. The current product's source does not have it. We have
corrected our own data; the lesson is below.

## What to take from this if you are building one

1. **Find the status your competitors' money hangs on before you design a
   screen.** In all three products it is not the last status in the list and
   not the obvious one. It is the step between *the work happened* and *the
   money is owed*.
2. **Decide how your product closes that gap.** These three show the three
   options: nag the person responsible (TutorCruncher's daily reminder), make
   the step impossible to skip (Fresha's checkout), or remove the step by
   computing it (Invoice Ninja's Overdue). Each is a product decision, and a
   competitor has already made it.
3. **Read the current version.** Help centres keep old pages online. Our own
   Invoice Ninja mistake came from reading documentation for a version the
   product has moved past. The source, or the newest docs, is what customers
   actually use.

## Method, and its limits

One product per trade, three trades. Documentation was read in September 2026
and re-checked on 2026-09-24; Invoice Ninja was checked against its public
source on GitHub. Documentation describes how a product is meant to work, not
how its customers use it — we did not operate paid accounts in any of the
three. A different product in the same trade might make a different choice;
the pattern we would expect to hold is that *some* status carries the revenue,
not that it is always the one named here.

SaaSReadyit is not affiliated with Invoice Ninja, TutorCruncher or Fresha.

## Sources

- TutorCruncher — [Lesson Statuses](https://help.tutorcruncher.com/en/articles/14183043-lesson-statuses)
- TutorCruncher — [Cancelling Lessons](https://help.tutorcruncher.com/en/articles/14183040-cancelling-lessons)
- Fresha — [Update appointment statuses](https://www.fresha.com/help-center/knowledge-base/calendar/600-update-appointment-statuses)
- Invoice Ninja — [app/Models/Invoice.php](https://github.com/invoiceninja/invoiceninja/blob/v5-develop/app/Models/Invoice.php) (status constants)
- Invoice Ninja — [app/Models/InvoiceInvitation.php](https://github.com/invoiceninja/invoiceninja/blob/v5-develop/app/Models/InvoiceInvitation.php) (`markViewed`)
- Invoice Ninja — [Invoices user guide (v5)](https://invoiceninja.github.io/docs/user-guide/invoices)
- Invoice Ninja — [Invoices (legacy docs, lists "Viewed")](https://invoice-ninja.readthedocs.io/en/latest/invoices.html)

---

*This research was done by [SaaSReadyit](https://saasreadyit.com), which writes
AI-generated validation reports for software ideas. The findings above are read
from the products' own documentation and source, not generated by a model.*
