Skip to main content

Forfaits club

Cette page documente les règles Convex de forfaits déclarés sur une compétition. Sources principales :
  • convex/schema.ts
  • convex/competition/club_forfeits.ts
  • convex/competition/club_forfeit_impacts.ts
  • convex/competition/club_forfeit_sanctions.ts
  • convex/competition/bet_settlement.ts
  • convex/lib/audit_logs.ts
  • convex/social/announcements.ts

club_forfeits et statut

Les champs clés vérifiés : leagueId, season, clubId, effectiveAt, declaredAt, declaredById, scope, mercatoStartAt, status, reason, adminNote, cancelledAt, cancelledById, cancelReason. Statuts :
  • ACTIVE
  • CANCELLED
Idempotence métier : la déclaration d’un forfait actif existant retourne l’enregistrement existant.

Détermination de scope

Deux scopes existent :
  • FULL_COMPETITION
  • POST_MERCATO_ONLY
Quand une fenêtre de mercato est connue, le scope est dérivé : avant mercato = FULL_COMPETITION, à partir de mercato = POST_MERCATO_ONLY.

Application sportive (applyClubForfeit)

Le moteur applique le forfait sur les matchs actifs où le club est impliqué, selon le scope :
  • FULL_COMPETITION : tous les matchs en cours de saison,
  • POST_MERCATO_ONLY : seulement à partir de mercatoStartAt si défini.
Scores imposés :
  • forfait simple : club forfaité perd (0), adversaire marque 1,
  • double forfait : score 0-0.
Écriture d’impact :
  • scores/évolution match en resultOrigin = CLUB_FORFEIT,
  • forfeitClubId, forfeitCreatedResult,
  • snapshots de restauration : previousHomeScore, previousAwayScore, previousResultOrigin, previousMatchStatus,
  • isDisputed = false, validatedAt posé,
  • match repassé validated.

Répercussions associées

  • Invalidation des stats match (match_player_stats, match_team_stats) avec invalidatedReason = CLUB_FORFEIT.
  • Annulation paris : cancelPendingBetsForMatch avec reason = MATCH_FORFEITED (uniquement PENDING).
  • Recalcul classement via recalculateLeagueStandingsCore.
  • Sanctions automatiques via generateForfeitSanctions.
  • Annonce globale sourceType = CLUB_FORFEIT.

Réversion (revertClubForfeitImpacts)

La réversion re-cible uniquement les impacts signés par le forfait (resultOrigin = CLUB_FORFEIT, forfeitClubId).
  • si forfeitCreatedResult === true : suppression du résultat puis restauration status depuis snapshot previousMatchStatus,
  • sinon : restauration homeScore / awayScore et flags de forfeit,
  • réactivation des stats invalidées par ce forfeit,
  • recalcul des standings,
  • levée des sanctions liées.
Cas complexe :
  • si l’adversaire est encore en forfait actif, la restauration de score peut être ignorée avec warning.
Les paris annulés lors du forfeit ne sont pas réouverts ; seuls les PENDING ont été annulés.

Sanctions

generateForfeitSanctions applique un COMPETITION_BAN :
  • destinataires GM + MANAGER / CO_MANAGER actifs,
  • scope principal : ["SPORT_ELIGIBILITY"],
  • banScope par défaut PLAYER_AND_STAFF,
  • périodes : de baseSeason sur seasonCount saisons (défaut 3, cap 10),
  • traçage source (sourceType, sourceForfeitId, sourceClubId).
liftForfeitSanctions met fin à la sanction en mode manuel (END_MANUAL, ENDED_MANUAL) avec raison par défaut "Forfait annulé".

Limites / précisions

  • Les effets exacts hors Convex (accès terrain/API externe, emails ciblés, placement visuel final des annonces) ne sont pas tous détaillés dans ce périmètre. [non vérifié]
  • La logique métier sur le comportement d’un forfeit en mode replay/écran front n’est pas couverte ici. [non vérifié]
Last modified on June 24, 2026