feat(ClubTeam): enhance club team management with lineup features and member eligibility

- Added teamGender and teamAgeGroup fields to ClubTeam model for better categorization.
- Updated create and update club team endpoints to handle new fields and default values.
- Implemented getClubTeamLineup and updateClubTeamLineup functions for managing team lineups.
- Enhanced member management with adultReleaseApproved and adultReserveApproved fields in Member model.
- Updated frontend views to support new lineup features and member eligibility flags.
- Improved localization for new terms related to team management and member eligibility across multiple languages.
This commit is contained in:
Torsten Schulz (local)
2026-03-31 13:44:28 +02:00
parent cb7830571b
commit 5eff1d63aa
28 changed files with 1325 additions and 72 deletions

View File

@@ -51,6 +51,18 @@ const ClubTeam = sequelize.define('ClubTeam', {
comment: 'Team ID from myTischtennis (e.g. 2995094)',
field: 'my_tischtennis_team_id'
},
teamGender: {
type: DataTypes.ENUM('open', 'female'),
allowNull: false,
defaultValue: 'open',
field: 'team_gender'
},
teamAgeGroup: {
type: DataTypes.ENUM('adult', 'J19', 'J17', 'J15', 'J13', 'J11'),
allowNull: false,
defaultValue: 'adult',
field: 'team_age_group'
},
}, {
underscored: true,
tableName: 'club_team',

View File

@@ -0,0 +1,47 @@
import { DataTypes } from 'sequelize';
import sequelize from '../database.js';
const ClubTeamMember = sequelize.define('ClubTeamMember', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
clubTeamId: {
type: DataTypes.INTEGER,
allowNull: false,
field: 'club_team_id',
},
memberId: {
type: DataTypes.INTEGER,
allowNull: false,
field: 'member_id',
},
lineupHalf: {
type: DataTypes.ENUM('first_half', 'second_half'),
allowNull: false,
defaultValue: 'first_half',
field: 'lineup_half',
},
position: {
type: DataTypes.INTEGER,
allowNull: false,
},
}, {
underscored: true,
tableName: 'club_team_member',
timestamps: true,
indexes: [
{
unique: true,
fields: ['club_team_id', 'lineup_half', 'member_id'],
},
{
unique: true,
fields: ['club_team_id', 'lineup_half', 'position'],
}
]
});
export default ClubTeamMember;

View File

@@ -161,6 +161,20 @@ const Member = sequelize.define('Member', {
field: 'member_form_handed_over',
comment: 'Mitgliedsformular ausgehändigt'
},
adultReleaseApproved: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'adult_release_approved',
comment: 'Jugendspieler mit Freigabe fuer Erwachsene'
},
adultReserveApproved: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'adult_reserve_approved',
comment: 'Jugendspieler als Ersatz bei Erwachsenen zugelassen'
},
myTischtennisPlayerId: {
type: DataTypes.STRING,
allowNull: true,

View File

@@ -20,6 +20,7 @@ import Match from './Match.js';
import League from './League.js';
import Team from './Team.js';
import ClubTeam from './ClubTeam.js';
import ClubTeamMember from './ClubTeamMember.js';
import TeamDocument from './TeamDocument.js';
import Season from './Season.js';
import Location from './Location.js';
@@ -168,6 +169,11 @@ ClubTeam.belongsTo(League, { foreignKey: 'leagueId', as: 'league' });
Season.hasMany(ClubTeam, { foreignKey: 'seasonId', as: 'clubTeams' });
ClubTeam.belongsTo(Season, { foreignKey: 'seasonId', as: 'season' });
ClubTeam.hasMany(ClubTeamMember, { foreignKey: 'clubTeamId', as: 'lineupEntries' });
ClubTeamMember.belongsTo(ClubTeam, { foreignKey: 'clubTeamId', as: 'clubTeam' });
Member.hasMany(ClubTeamMember, { foreignKey: 'memberId', as: 'clubTeamAssignments' });
ClubTeamMember.belongsTo(Member, { foreignKey: 'memberId', as: 'member' });
// TeamDocument relationships
ClubTeam.hasMany(TeamDocument, { foreignKey: 'clubTeamId', as: 'documents' });
TeamDocument.belongsTo(ClubTeam, { foreignKey: 'clubTeamId', as: 'clubTeam' });
@@ -406,6 +412,7 @@ export {
League,
Team,
ClubTeam,
ClubTeamMember,
TeamDocument,
Group,
GroupActivity,