Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Danielsl4/TFG_DAM_2526_Consulta2/llms.txt

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

Teams and players are the core entities of the Futsal League Manager. Teams persist across seasons, while player enrollments are season-specific. This separation lets the same player wear a different jersey number or play for a different club each season without losing historical records.
A player can appear in different teams across different seasons. The team_players junction table stores one enrollment record per player per season, so a player’s history is fully preserved even after a transfer.

Teams

Every team record holds the following fields:
FieldTypeDescription
namestringTeam name (required)
kit_colorstringPrimary kit colour, used for display purposes
logo_urltextCloudinary URL of the team’s crest
delegatestringName of the team delegate or contact person
coachstringName of the head coach
phonestringContact phone number
is_activebooleantrue for active teams; false for soft-deleted teams
Creating a teamPOST /teams requires name. All other fields are optional. Pass a season_id to immediately register the team in a season (creates the team_stats record). Editing a teamPUT /teams/:id accepts all fields. If logo_url changes and the Cloudinary public IDs differ, the old image is automatically deleted from Cloudinary. Team detailGET /teams/:id returns the full team record together with the current season’s roster, standings stats, and match schedule. Pass ?season_id= to retrieve data for a specific season instead of the active one. Registering in a seasonPOST /teams/:id/register with a season_id body parameter enrolls an existing team in a season. Use this when promoting a team that already exists in the database into a new edition.

Players

Each player record stores:
FieldTypeDescription
namestringFull name (required)
birth_datedateDate of birth
photo_urltextCloudinary URL of the player’s photo
is_activebooleantrue for active players; false for soft-deleted ones
Creating a playerPOST /players requires name. Optionally pass season_id and team_id to enroll the player immediately upon creation. Editing a playerPUT /players/:id accepts name, birth_date, and photo_url. The old photo is removed from Cloudinary if the URL changes and the public IDs differ. Removing from a seasonDELETE /players/:id/season/:seasonId removes the player’s enrollment and season stats for that specific season without affecting other seasons.

Assigning players to teams

Player-to-team assignments are managed through the team_players junction table. Each record links a player to a team for a single season:
ColumnDescription
player_idReferences players.id
team_idReferences teams.id
season_idReferences seasons.id
jersey_numberThe player’s shirt number for this season
Enrolling a playerPOST /players/:id/register with team_id, season_id, and optionally jersey_number in the request body. Any previous enrollment in the same season is replaced, making this also the transfer endpoint. Jersey numbers must be unique within a team and season. Removing from a teamDELETE /players/:id/unregister with team_id and season_id in the request body removes a specific team assignment without deleting the player record. Players without a team assignment (enrolled in the season but not yet assigned to a club) are handled by omitting team_id when calling the enroll endpoint.

Uploading logos and photos

All images are stored in Cloudinary. The upload flow works as follows:
  1. Send a POST /admin/upload request as multipart/form-data with the file in the image field.
  2. Optionally pass ?folder=teams or ?folder=players as a query parameter to organise files in Cloudinary. Pass ?filename= to control the public ID.
  3. The server compresses the image with Sharp before uploading. The response contains the Cloudinary URL:
{ "url": "https://res.cloudinary.com/..." }
  1. Save the returned URL into the logo_url (teams) or photo_url (players) field when creating or editing the record.
When a logo or photo is replaced, the previous image is automatically removed from Cloudinary, provided its Cloudinary public ID differs from the new one (i.e., the file was re-uploaded rather than reused).

Soft deletion and recovery

Both teams and players use soft deletion (is_active = false) rather than immediate removal. This preserves match history and statistics. Soft-deleting a teamDELETE /teams/:id sets is_active = false. The team disappears from public listings but its match records remain intact. Restoring a teamPOST /teams/:id/restore sets is_active = true. Permanently deleting a teamDELETE /teams/:id/permanent performs a hard delete. This is blocked if the team has any match history or season enrollments. The same pattern applies to players and fields:
  • Soft-delete: DELETE /players/:id
  • Restore: POST /players/:id/restore
  • Permanent delete: DELETE /players/:id/permanent (blocked if the player has match events or team enrollments)
Deleted teams and players appear in their respective trash views (GET /teams/admin/trash, GET /players/admin/trash) and can be recovered from there.
Permanently deleting a team removes all associated match history. The permanent delete endpoint explicitly checks for existing matches and season enrollments and returns a 400 error if any are found — but always verify in the trash view before proceeding.

Build docs developers (and LLMs) love