from datetime import datetime from flask import Flask, render_template, request, jsonify from flask_sqlalchemy import SQLAlchemy from sqlalchemy import func import os app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL') db = SQLAlchemy(app) # Models class Player(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False, unique=True) class Date(db.Model): id = db.Column(db.Integer, primary_key=True) date_str = db.Column(db.String(20), nullable=False, unique=True) # e.g. '08/05/25' class Attendance(db.Model): """ Attendance record for a player on a date. status: 'yes', 'no', 'maybe', or blank (None) """ id = db.Column(db.Integer, primary_key=True) date_id = db.Column(db.Integer, db.ForeignKey('date.id'), nullable=False) player_id = db.Column(db.Integer, db.ForeignKey('player.id'), nullable=False) status = db.Column(db.String(10)) # 'yes', 'no', 'maybe', or blank __table_args__ = (db.UniqueConstraint('date_id', 'player_id', name='_date_player_uc'),) class GuestName(db.Model): id = db.Column(db.Integer, primary_key=True) date_id = db.Column(db.Integer, db.ForeignKey('date.id'), nullable=False, unique=True) name = db.Column(db.String(50), nullable=False) def get_initial_data(): # Ensure tables exist db.create_all() # If no players, insert defaults if Player.query.count() == 0: for name in ["Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace", "Hannah"]: db.session.add(Player(name=name)) db.session.commit() if not GuestName.query.first(): # Set default guest name for all dates pass def parse_date(date_str): return datetime.strptime(date_str, '%d/%m/%y') def db_to_json(): players = [p.name for p in Player.query.order_by(Player.id)] guest = "Guest" dates = sorted([d.date_str for d in Date.query.all()], key=parse_date) attendance = {} for att in Attendance.query.all(): date = Date.query.get(att.date_id).date_str player = Player.query.get(att.player_id) colIdx = players.index(player.name) if player.name in players else len(players) # guest is last key = f"{date}|{colIdx}" attendance[key] = True if att.status == 'yes' else 'no' guest_names = {Date.query.get(g.date_id).date_str: g.name for g in GuestName.query.all()} return { "players": players, "guest": guest, "dates": dates, "attendance": attendance, "guestNames": guest_names } def json_to_db(data): try: db.session.query(Attendance).delete() db.session.commit() db.session.query(GuestName).delete() db.session.commit() db.session.query(Date).delete() db.session.commit() db.session.query(Player).delete() db.session.commit() except Exception as e: db.session.rollback() print("Error during deletion:", e) raise # Insert players from JSON for name in data.get("players", []): db.session.add(Player(name=name)) db.session.commit() # Insert dates and attendance for date_str in data.get("dates", []): date = Date(date_str=date_str) db.session.add(date) db.session.commit() for idx, player_name in enumerate(data["players"] + [data["guest"]]): key = f"{date_str}|{idx}" status = data["attendance"].get(key) if status: player = Player.query.filter_by(name=player_name).first() if player: # Save status as 'yes', 'no', or 'maybe' db.session.add(Attendance(date_id=date.id, player_id=player.id, status=('yes' if status is True else (status if status in ['no', 'maybe'] else None))) guest_name = data.get("guestNames", {}).get(date_str) if guest_name: db.session.add(GuestName(date_id=date.id, name=guest_name)) db.session.commit() @app.route('/') def index(): return render_template('index.html') @app.route('/reports') def reports(): return render_template('reports.html') @app.route('/api/data', methods=['GET']) def get_data(): get_initial_data() return jsonify(db_to_json()) @app.route('/api/data', methods=['POST']) def update_data(): data = request.json json_to_db(data) return jsonify({"status": "success"}) # Optional: export from DB as JSON (for compatibility) @app.route('/export-data') def export_data(): from flask import Response get_initial_data() data = db_to_json() return Response( response=json.dumps(data, indent=2), mimetype='application/json', headers={'Content-Disposition': 'attachment;filename=attendance_data.json'} ) if __name__ == '__main__': import os port = int(os.environ.get('PORT', 5000)) app.run(host='0.0.0.0', port=port, debug=False)