
Gym & Fitness Membership Management
Gym memberships that expire, freeze and renew on their own, a front desk that says why entry is refused, class bookings with a waiting list.
Available for Odoo 16.0, Odoo 17.0, Odoo 18.0, Odoo 19.0. Technical name bambooforge_gym.
Gym & Fitness Membership Management
One moment decides whether gym software is any good: somebody is standing at the desk and the screen has to say yes or no, and why.
The front desk
Type or scan a name or a member number and the panel answers in one line: come in, or not today with the actual reason - not started, on hold, ran out on the 3rd, no sessions left, cancelled, not a member here. A refusal is never a red dialog somebody has to dismiss with a queue waiting.
If the gym has switched it on, money overdue also stops the door - overdue, not merely unpaid, so an invoice raised this morning on fourteen-day terms is not an argument in front of other members. It is off by default for the same reason.
A server error never reaches the desk as a crash dialog either: the panel says so and nothing is recorded. A scan that arrives while the previous one is still going is not swallowed in silence.
Plans
Monthly, quarterly, yearly, or a session pass. A plan carries:
its price, and the product the invoice line is written against;
how many sessions it includes (0 = unlimited) and how long a pass stays valid;
how many freeze days a member may take per period;
the notice period that still has to be paid;
whether it renews itself;
which classes it opens - empty means all of them.
Memberships
A membership is a contract, not a flag on a contact.
The price is copied at signature, so a price rise never rewrites what somebody already signed.
Two live memberships for one person are refused. That is how a member ends up billed twice and the door ends up guessing.
A pass may sit alongside a monthly, and at the door the unlimited membership wins - a member who paid for unlimited entry would be furious to watch a paid session disappear.
Holds
Injury, travel, a broken leg.
A hold pushes the end date out when it finishes, not when it starts - otherwise a member freezes, trains through the freeze and keeps the days.
It gives back the days actually taken, not the days asked for. A fortnight abandoned after two days is worth two days.
A hold booked for next week starts itself on the day, so the door refuses while it runs. One booked entirely in the future gives nothing until it has begun.
A finished hold cannot be edited or deleted. The allowance counts the days that were credited, so the same fortnight cannot be handed out twice by typing over an old row.
A hold that is scrapped gives back no days.
Leaving
Giving notice moves the end date to the end of the notice period and the membership stays live and billable until then. The end date only ever moves outwards: a year that has been paid for is never cut back to thirty days. The days that run past what was already invoiced are charged, or the member trains through the notice for nothing.
Notice can only be given on a live membership, and only once. A plan with no notice period ends on the spot.
Classes
Capacity can never exceed the studio's fire limit, and a trainer cannot teach two rooms at once.
A full class puts the next member on a waiting list; the moment a seat frees up it goes to whoever waited longest - skipping anyone whose membership has lapsed in the meantime and carrying on down the list, with a note saying so. A lapsed member at the head of the queue never swallows the seat.
Cancelling late costs a session, inside a window the manager sets - and a no-show costs the same, because the seat was held either way. Charging the phone call and not the empty chair rewards the wrong behaviour.
Ticking somebody in from the waiting list cannot push a class over its capacity, and cannot be done for a membership that has lapsed.
A member who cancels can book the class again; only live bookings are unique.
If the gym cancels the class, every seat is released and nobody pays for it.
Closing the register marks whoever was booked and did not turn up as a no show, and a scheduled job closes classes that are over so the list is true in the morning without anybody ticking it.
One visit, one session
A session credit is spent in exactly one place - the door - and one visit a day costs one session, enforced by a unique index rather than by hope. Scanning in for a class you booked marks that register, so somebody who turned up is never closed off as a no-show an hour later. Ticking the register goes through the same code, so a member who scans in and is ticked off by the trainer is charged once.
Deleting a visit gives a paid session back, and deleting a booking that carries a late-cancellation or a no-show would too, so both are a manager's job. Credits never go negative.
Billing
The invoice names the period it covers, and the same period is never invoiced twice. A scheduled job raises the invoice for a period that has started - off by default, because letting software bill people should be a decision - and it never bills a membership that is on hold.
Roles
Trainer runs the timetable and the register and reads the medical note - and can actually do all of it, which is worth saying because a role that cannot open its own screens is not a role. Every price, on the plan and on the membership, is hidden from them at field level.
Reception works the door, sells and renews memberships and invoices them, and needs no accounting role to do it: the figures the desk sees are computed with sudo rather than by handing a receptionist the whole ledger.
Gym manager configures plans, classes and studios, and is the only role that can delete a paid visit or a charged booking.
Two sites in one database stay two sites: the door only ever looks at memberships of the gym it is standing in, and each site's invoices are raised in its own company.
The medical note is protected at field level, not by hiding a page, and it is never tracked into a chatter everybody follows.
Community only
Depends on product, account and base_setup - all Community. Tested on 16.0, 17.0, 18.0 and 19.0.
Screens


