Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/azahel79/Spartans-gym/llms.txt

Use this file to discover all available pages before exploring further.

Membership plans are the foundation of how Spartans Gym charges its members. Every client is linked to exactly one plan at any given time. Plans are managed centrally by admins, and their pricing is surfaced throughout the application — in the reception enrollment modal, the renewal dialog, and the Config → Planes y Membresías tab.

Plan Data Model

FieldTypeNotes
idString (UUID)Auto-generated on creation.
nameString (unique)Display name, e.g. "Mensual" or "Anual". Must be unique across all plans.
priceDecimal (MXN)The amount charged to members on enrollment or renewal.
periodStringDuration string: "Mes", "3 Meses", "6 Meses", or "Año". Defaults to "Mes".
colorStringA CSS class used for UI badge colouring. Defaults to "bg-primary".
isActiveBooleanWhether the plan is available for new enrollments. Defaults to true.
createdAtDateTimeSet by the database on insert.
updatedAtDateTimeUpdated automatically on every change.

Period-to-Months Mapping

When calculating a membership expiry date (at enrollment or renewal), the backend’s getPlanMonths function converts the plan’s period string into a number of calendar months to add to the base date.
Period value in DBResolved months
"Mes"1
"3 Meses"3
"trimestral" (case-insensitive)3
"6 Meses"6
"semestral" (case-insensitive)6
"Año"12
"anual" (case-insensitive)12
The function uses a regex match for patterns like "2 meses" before falling back to keyword detection, so custom period strings containing a number followed by "mes" or "meses" also resolve correctly. If no pattern matches, the function defaults to 1 month.

Creating a Plan

Plans are created by admins via POST /api/plans. The request body requires at minimum a name and a price. period defaults to "Mes" if omitted.
{
  "name": "Semestral VIP",
  "price": 2500,
  "period": "6 Meses",
  "color": "bg-secondary"
}
On success the API returns HTTP 201 with the new plan object including its auto-generated UUID.
Plan names must be unique. Attempting to create a plan with a name that already exists — even if the existing plan is inactive — returns HTTP 400. Choose distinct, descriptive names to avoid collisions.
Plans are listed and managed in the Config → Planes y Membresías tab of the application settings. Pricing changes made here take effect immediately for any new enrollment or renewal processed after the update.

Soft Deleting a Plan

Deleting a plan via DELETE /api/plans/:id performs a soft delete: it sets isActive = false on the record rather than removing it from the database.
Existing client records store the plan name as a plain string rather than a foreign key. Permanently deleting a plan would not break existing records, but it would remove the plan from pricing lookups. Soft deletion keeps the plan data available for historical reporting and prevents accidental loss of configuration while ensuring the plan no longer appears in enrollment or renewal dropdowns.
Clients already enrolled in a soft-deleted plan retain their plan field value and their existing expiry date. They can still renew, but staff must select a currently active plan when processing the renewal.

Renewal Logic

Membership renewals are processed via POST /api/clients/:id/renew with the following body:
{
  "newPlan": "Trimestral",
  "amount": 1200,
  "paymentMethod": "Efectivo"
}
The backend calculates the new expiry date using the following rule:
1

Determine the base date

Compare the client’s current vencimiento date to today’s date.
  • If vencimiento is in the future → use vencimiento as the base date (extends from the end of the current period).
  • If vencimiento is today or in the past → use today as the base date (starts a fresh period from now).
2

Add the plan period

Call calculateExpiryDate(baseDate, newPlan, plan.period), which adds the resolved number of months to the base date using JavaScript’s setMonth.
3

Update the client record

The client’s plan, monto, metodoPago, vencimiento, and status fields are updated in a single database write. status is always reset to ACTIVO.
The renewal response returns the updated plan, monto, vencimiento, and status fields:
{
  "success": true,
  "data": {
    "plan": "Trimestral",
    "monto": "1200.00",
    "vencimiento": "2025-10-15T00:00:00.000Z",
    "status": "ACTIVO"
  }
}
A transaction record is created automatically on renewal, which feeds into the Dashboard’s Ingresos Totales del Mes and Actividad Reciente sections.

Seed Plans

On first deploy the seed script populates the plans table with a set of sample plans so the application is usable immediately without manual configuration. These plans cover the standard monthly, quarterly, semi-annual, and annual periods. You can view and modify seeded plans at any time from the Config → Planes y Membresías tab, or delete them (soft delete) and replace them with your own pricing structure.
If you rename a seeded plan, ensure no existing client records reference the old name string. Because the plan field on clients is stored as a plain string (not a foreign key), renaming a plan in the plans table does not automatically update client records.

Build docs developers (and LLMs) love