Use cases · Classes & memberships

Fitness studio

A boutique studio running scheduled classes — spin, yoga, strength — with hard capacity, waitlists, and check-in. Members pay monthly; drop-ins buy class packs. A no-show on a packed class costs someone else a spot, so the rules around capacity, packs, and fees have to be exact.

The shape

A class is a Seldon EventSession under an EventSeries, projected through an open_capacity Availability that caps seats; a Registration is the roster spot with a waitlist, and Attendance records check-in. Membership tiers and entitlement live in Terminus; class packs are Mallow stored value; recurring dues run through Daneel + Payments.

  • Seldon models the timetable as an EventSeries of EventSessions. An open_capacity Availability enforces the seat cap; Registration handles booking + waitlist; Attendance records who actually showed. One-on-one PT uses a variable-duration grid instead.
  • Terminus holds members as Persons. An "Unlimited" plan is a RankedGroup(kind=tier) with a TierDefinition auto-enrolment rule; member-only classes gate on checkEntitlement.
  • Mallow runs class packs as stored value — a 10-class pack is a StoredValueAccount, and each booking burns one with a StoredValueTransaction. Monthly membership dues post to the same ledger.
  • Payments charges recurring dues on a stored credential (MIT / merchant-initiated), so the monthly run doesn't need the member present.
  • Daneel owns the recurring-billing workflow, waitlist promotion when a seat frees, and the no-show fee that fires off the Seldon no_show emission.
  • Speaker sends class reminders and "a spot opened" pushes (consent-gated; the studio's operator app is an installable PWA on the push channel).

Walk-through

Book a class

A member books Saturday's 9am spin. Seldon checks the open_capacity seat cap and, because it's a member-only class, calls Terminus checkEntitlement against her Unlimited tier. Both pass; a Registration lands her on the roster.

Sell out and waitlist

The class fills. The next member to book enters the waitlist (a Registration in a queued state). When someone cancels, Daneel's waitlist-promotion moves the top of the list to confirmed and Speaker pushes "you're in" — consent permitting.

Drop-in on a class pack

A non-member books with a 10-class pack. There's no entitlement tier, so booking redeems one credit from her Mallow StoredValueAccount — a single StoredValueTransaction — and the roster spot is hers. The pack balance is now nine.

Check-in

At the door, the front desk taps her in; Seldon records Attendance against the Registration. A no-show, by contrast, leaves the Registration unattended — the Seldon no_show emission triggers a Daneel workflow that books the studio's late-cancel fee against the member.

Monthly dues

On the first, Daneel's billing workflow runs the membership roster: for each active tier member, Payments charges the stored credential merchant-initiated, Mallow posts the dues to the ledger, and a failed charge opens a dunning sub-flow rather than silently lapsing the membership.

Why this is hard without LatticeKit

Studio software usually bundles scheduling, memberships, and billing into one closed monolith — great until you want the class pack to draw from the same ledger as the retail counter, or the no-show fee to reconcile against the same invoices as dues. Here capacity, entitlement, stored value, and recurring billing are separate primitives that compose: the seat cap is Seldon's, the tier gate is Terminus's, the pack balance is Mallow's stored-value ledger, and the monthly charge is Payments' MIT path — so a refunded class credit and a failed dues charge both land in the one ledger your accountant already reads.