A comprehensive team management system for Fortitudo 1901 Rugby ASD youth teams. FortiDesk streamlines administrative tasks, athlete and staff registry management, guardian communications, and documentation for youth rugby teams.
FortiDesk provides complete management for:
- 👦 Youth Athletes (ages 3-18)
- 👔 Staff & Officials (coaches, escorts, managers, executives)
- 🔐 Role-based Access Control
- 🌐 Multi-language Support (English/Italian)
- Secure Login/Registration with bcrypt password hashing
- 4 User Roles with different permissions:
- Admin: Full system access, can delete records
- Coach: Can create/edit athletes and staff
- Parent: View-only access (future: only own children)
- Player: View-only access (future: only own data)
- Persistent sessions with "Remember me" functionality
- CSRF protection on all forms
- Password security: Bcrypt hashing with salt
Complete digital registry for young athletes with comprehensive data tracking:
- Personal Information: first name, last name, birth date/place, fiscal code
- Residential Address: street, number, postal code, city, province
- Identity Document: number, issuing authority, expiration date
- Medical Certificate/Sports Booklet: presence, type, expiration date
- Automatic age calculation and validation (3-18 years)
- Audit trail: creation date, last update, creator user
- Two guardians per athlete: father, mother, or legal guardians
- Complete contacts: first name, last name, phone, email
- Guardian type validation: cannot have two fathers/mothers
- 🔍 Advanced search by name, surname, or fiscal code
⚠️ Automatic expiry alerts for documents (≤30 days warning)- 🏥 Medical certificate status with visual indicators
- 📊 Registry statistics with total counts
- 📝 Complete data validation (fiscal code format, age limits, etc.)
- 🗂️ Pagination for large lists (20 items per page)
- 🎨 Visual status badges: expired (red), expiring soon (yellow), valid (green)
Complete management system for organizational staff:
- Coach (Allenatore) - Head coaches
- Assistant Coach (Allenatore Assistente) - Assistant coaches
- Escort (Accompagnatore) - Team escorts/chaperones
- Manager (Dirigente) - Team managers
- President (Presidente) - Club president
- Vice President (Vice Presidente) - Vice president
- Secretary (Segretario) - Administrative secretary
- Personal Information: first name, last name, birth date/place, fiscal code
- Contact Information: email, phone
- Residential Address: complete address details
- Identity Document: number, issuing authority, expiration
- Role & Notes: position with optional role description
- Medical Certificate: required for coaches and escorts
- Background Check (Certificato Penale): required for roles working with minors
- Age validation: staff must be 18+ years old
- 🔍 Search & Filter: by name, email, fiscal code, or role
- 📋 Role-based filtering: view staff by specific role
⚠️ Triple expiry tracking: documents, medical certificates, background checks- 💡 Smart requirements: automatic hints for role-specific documents
- 📊 Status indicators: visual badges for all expiry items
- 🗂️ Pagination with total staff count
Full bilingual support with professional translations:
- 2 Languages Supported:
- 🇬🇧 English (default)
- 🇮🇹 Italiano
- Language Switcher: Dropdown in navbar with flag icons
- 250+ Translated Strings: Complete coverage of:
- All UI elements and navigation
- Form labels and placeholders
- Validation messages
- Success/error messages
- Role names and statuses
- Session Persistence: Language preference saved across sessions
- Browser Detection: Automatic language from browser settings as fallback
- Professional Tone: Formal Italian ("Lei" form) for user messages
- Responsive Design: Bootstrap 5.1.3 framework
- Clean Navigation:
- Top navbar with Dashboard, Athletes, Staff links
- Language selector dropdown
- User profile dropdown
- Smart Forms:
- Conditional fields (show/hide based on selections)
- Real-time validation feedback
- Clear error messages
- Visual Feedback:
- Color-coded status badges (red/yellow/green/gray)
- Flash messages for user actions
- Loading states and transitions
- Card-based Layouts: Clean, scannable lists
- Pagination Controls: Previous/Next with page indicators
- Mobile-Friendly: Responsive on all devices
- Authentication Security:
- Bcrypt password hashing
- Secure session management
- CSRF token protection
- Authorization:
- Role-based access control (RBAC)
- Permission checks on all sensitive operations
- Route protection with decorators
- Data Security:
- SQL injection prevention (SQLAlchemy ORM)
- Input validation and sanitization
- XSS protection via Jinja2 auto-escaping
- Audit Trail:
- Creation and modification timestamps
- Creator user tracking
- Soft delete (no data loss)
- 4 Core Models:
- User: System users with authentication
- Athlete: Youth athlete registry
- Guardian: Parent/guardian contacts
- Staff: Organizational personnel
- Optimized Relations:
- User → Athletes (1:many, created_by)
- User → Staff (1:many, created_by)
- Athlete → Guardians (1:2, required)
- Performance:
- Indexes on fiscal_code, email, role
- Efficient queries with eager loading
- Pagination for large datasets
- Data Integrity:
- Foreign key constraints
- Unique constraints (fiscal codes, emails)
- NOT NULL constraints on required fields
- Flask 3.0.0 - Modern Python web framework
- SQLAlchemy 3.1.1 - Powerful ORM for database
- Flask-Login 0.6.3 - User session management
- Flask-WTF 1.2.1 - Form handling and validation
- Flask-Babel 4.0.0 - Internationalization support
- bcrypt 4.1.2 - Secure password hashing
- PyMySQL 1.1.0 - MySQL database driver
- python-dotenv 1.0.0 - Environment configuration
- Bootstrap 5.1.3 - Responsive CSS framework
- Jinja2 - Powerful template engine
- Vanilla JavaScript - Lightweight client-side logic
- MySQL 8.0 - Reliable relational database
- Optimized schema with proper indexes
- Foreign key relations for data integrity
- Docker - Application containerization
- Docker Compose - Multi-container orchestration
- Nginx - Reverse proxy and static file serving
- Gunicorn 21.2.0 - Production WSGI server
- Docker and Docker Compose installed
- Git for repository cloning
- 8GB RAM recommended
- Ports 80, 443, 3306 available
# 1. Clone the repository
git clone <repository-url>
cd FortiDesk
# 2. Copy environment file
cp .env.example .env
# 3. (Optional) Edit .env with your settings
nano .env
# 4. Start with automatic script
./docker-start.sh
# Or manually with docker-compose
docker-compose up -d- Application URL: http://localhost
- Default Admin:
- Username:
admin - Password:
admin123 ⚠️ Change immediately in production!
- Username:
- Default Coach:
- Username:
coach - Password:
coach123
- Username:
# View real-time logs
docker-compose logs -f
# View specific service logs
docker-compose logs -f web
# Stop all services
docker-compose down
# Stop and remove volumes (⚠️ deletes data)
docker-compose down -v
# Rebuild containers
docker-compose build --no-cache
# Restart a specific service
docker-compose restart web
# Access database shell
docker-compose exec db mysql -u fortidesk -p fortidesk
# Access Python shell with Flask context
docker-compose exec web python
>>> from run import app, db, User, Athlete, Staff
>>> with app.app_context():
... users = User.query.all()FortiDesk/
├── app/ # Flask application
│ ├── __init__.py # App factory and config
│ ├── models/ # SQLAlchemy models
│ │ ├── __init__.py # Model exports
│ │ ├── user.py # User authentication model
│ │ ├── athlete.py # Athlete registry model
│ │ ├── guardian.py # Guardian/parent model
│ │ └── staff.py # Staff/personnel model
│ ├── views/ # Flask blueprints (routes)
│ │ ├── __init__.py
│ │ ├── auth.py # Authentication routes
│ │ ├── main.py # Dashboard and main pages
│ │ ├── athletes.py # Athlete CRUD operations
│ │ └── staff.py # Staff CRUD operations
│ ├── forms/ # WTForms for validation
│ │ ├── __init__.py
│ │ ├── athletes_forms.py # Athlete and guardian forms
│ │ └── staff_forms.py # Staff forms
│ ├── templates/ # Jinja2 templates
│ │ ├── base.html # Base template with navbar
│ │ ├── dashboard.html # Dashboard page
│ │ ├── auth/ # Authentication pages
│ │ │ ├── login.html
│ │ │ └── register.html
│ │ ├── athletes/ # Athlete management
│ │ │ ├── index.html # List view
│ │ │ ├── detail.html # Detail view
│ │ │ └── form.html # Create/edit form
│ │ └── staff/ # Staff management
│ │ ├── index.html # List view
│ │ ├── detail.html # Detail view
│ │ └── form.html # Create/edit form
│ └── static/ # Static assets
│ ├── css/ # Custom stylesheets
│ └── js/ # JavaScript files
├── docker/ # Docker configurations
│ ├── nginx/ # Nginx configs
│ │ ├── nginx.conf
│ │ └── default.conf
│ └── mysql/ # Database init scripts
│ └── init.sql
├── translations/ # i18n translations
│ └── it/ # Italian translations
│ └── LC_MESSAGES/
│ ├── messages.po # Translation source
│ └── messages.mo # Compiled translations
├── babel.cfg # Babel extraction config
├── config.py # Flask configuration
├── docker-compose.yml # Service orchestration
├── Dockerfile # Flask app container
├── docker-start.sh # Quick start script
├── requirements.txt # Python dependencies
├── run.py # Application entry point
├── .env.example # Environment template
├── .gitignore # Git ignore rules
├── CLAUDE.md # Development documentation
└── README.md # This file
id(PK)username(unique, indexed)email(unique, indexed)password_hashfirst_name,last_namerole(admin/coach/parent/player)is_activecreated_at,last_login
id(PK)- Personal:
first_name,last_name,birth_date,birth_place,fiscal_code(unique) - Address:
street_address,street_number,postal_code,city,province - Document:
document_number,issuing_authority,document_expiry - Medical:
has_medical_certificate,certificate_type,certificate_expiry - Meta:
created_at,updated_at,created_by(FK→users),is_active
id(PK)first_name,last_namephone,emailguardian_type(father/mother/guardian)athlete_id(FK→athletes, required)created_at,updated_at,is_active
id(PK)- Personal:
first_name,last_name,birth_date,birth_place,fiscal_code(unique) - Contact:
phone,email - Address:
street_address,street_number,postal_code,city,province - Document:
document_number,issuing_authority,document_expiry - Role:
role(coach/assistant_coach/escort/manager/president/vice_president/secretary) role_notes(optional text)- Medical:
has_medical_certificate,certificate_type,certificate_expiry - Background:
has_background_check,background_check_date,background_check_expiry - Meta:
created_at,updated_at,created_by(FK→users),is_active
User1→NAthlete(created_by)User1→NStaff(created_by)Athlete1→NGuardian(athlete_id, typically 2 per athlete)- All deletions are "soft" (is_active=False)
| Action | Admin | Coach | Parent | Player |
|---|---|---|---|---|
| View Athletes | ✅ | ✅ | ✅ | ✅ |
| Create Athletes | ✅ | ✅ | ❌ | ❌ |
| Edit Athletes | ✅ | ✅ | ❌ | ❌ |
| Delete Athletes | ✅ | ❌ | ❌ | ❌ |
| View Staff | ✅ | ✅ | ✅ | ✅ |
| Create Staff | ✅ | ✅ | ❌ | ❌ |
| Edit Staff | ✅ | ✅ | ❌ | ❌ |
| Delete Staff | ✅ | ❌ | ❌ | ❌ |
| User Management | ✅ | ❌ | ❌ | ❌ |
- English (en) - Default
- Italian (it) - Complete translation
# 1. Mark new strings in code
# Python files: use _() or _l()
flash(_('Success message'))
label = _l('Form Label')
# Templates: use {{ _('text') }}
<h1>{{ _('Page Title') }}</h1>
# 2. Extract messages
uvx --with jinja2 --from babel pybabel extract -F babel.cfg -k _l -k _ -o messages.pot .
# 3. Update catalogs
uvx --with jinja2 --from babel pybabel update -i messages.pot -d translations
# 4. Edit translations
# Edit translations/it/LC_MESSAGES/messages.po
# 5. Compile
uvx --with jinja2 --from babel pybabel compile -d translations- Team/squad creation (U12, U14, U16, etc.)
- Athlete team assignments
- Season management
- Roster management
- Training session planning
- Athlete attendance tracking
- Absence notifications
- Attendance reports
- Match scheduling
- Player call-ups
- Match lineups
- Results tracking
- Parent messaging system
- Team announcements
- Email notifications
- Newsletter generation
- Document upload (PDF, images)
- Digital document archive
- Automatic form generation
- Document expiry reminders
- Membership fee tracking
- Payment status
- Invoice generation
- Financial reports
- Attendance statistics
- Team performance metrics
- Custom report builder
- Data export (Excel, CSV, PDF)
# 1. Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# 2. Install dependencies
pip install -r requirements.txt
# 3. Set up environment
cp .env.example .env
# Edit .env with local MySQL connection
# 4. Initialize database
python run.py # First run creates tables
# 5. Run development server
flask run
# Or: python run.py# Linting
uvx ruff check
# Type checking
uvx --from pyright pyright app/
# Manual testing
# Access http://localhost:5000FortiDesk is developed specifically for Fortitudo 1901 Rugby ASD.
- Create an issue on GitHub
- Include steps to reproduce
- Provide error messages/screenshots
- Open a GitHub issue with "[Feature Request]" prefix
- Describe the use case
- Explain expected behavior
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request
This project is developed for internal use of Fortitudo 1901 Rugby ASD.
For questions or support:
- 📧 Email: [contact information]
- 🐛 GitHub Issues: [repository issues page]
- 📚 Documentation: See CLAUDE.md for development docs
- Fortitudo 1901 Rugby ASD - For the opportunity and requirements
- Flask Community - For excellent documentation and support
- Bootstrap Team - For the responsive framework
FortiDesk - Simplifying management, improving youth rugby 🏉
Built with ❤️ for Fortitudo 1901 Rugby ASD