From Json to PostgreSQL
This commit is contained in:
parent
00365460d4
commit
94b0f9f693
119
app.py
119
app.py
@ -1,32 +1,92 @@
|
|||||||
from flask import Flask, render_template, request, jsonify, send_from_directory
|
from flask import Flask, render_template, request, jsonify
|
||||||
import json
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from sqlalchemy import func
|
||||||
import os
|
import os
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
DATA_FILE = 'data/attendance_data.json'
|
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL')
|
||||||
|
db = SQLAlchemy(app)
|
||||||
|
|
||||||
# Default player names
|
# Models
|
||||||
DEFAULT_PLAYERS = [
|
class Player(db.Model):
|
||||||
"Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace", "Hannah"
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
]
|
name = db.Column(db.String(50), nullable=False, unique=True)
|
||||||
DEFAULT_GUEST = "Guest"
|
|
||||||
|
|
||||||
def load_data():
|
class Date(db.Model):
|
||||||
if not os.path.exists(DATA_FILE):
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
data = {
|
date_str = db.Column(db.String(20), nullable=False, unique=True) # e.g. '08/05/25'
|
||||||
"players": DEFAULT_PLAYERS,
|
|
||||||
"guest": DEFAULT_GUEST,
|
class Attendance(db.Model):
|
||||||
"dates": [],
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
"attendance": {}
|
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), nullable=False) # 'yes' or 'no'
|
||||||
|
|
||||||
|
__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 db_to_json():
|
||||||
|
players = [p.name for p in Player.query.order_by(Player.id)]
|
||||||
|
guest = "Guest"
|
||||||
|
dates = [d.date_str for d in Date.query.order_by(Date.id)]
|
||||||
|
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
|
||||||
}
|
}
|
||||||
with open(DATA_FILE, 'w') as f:
|
|
||||||
json.dump(data, f)
|
|
||||||
with open(DATA_FILE, 'r') as f:
|
|
||||||
return json.load(f)
|
|
||||||
|
|
||||||
def save_data(data):
|
def json_to_db(data):
|
||||||
with open(DATA_FILE, 'w') as f:
|
db.session.query(Attendance).delete()
|
||||||
json.dump(data, f, indent=2)
|
db.session.query(Date).delete()
|
||||||
|
db.session.query(GuestName).delete()
|
||||||
|
db.session.commit()
|
||||||
|
# Players are assumed fixed
|
||||||
|
for date_str in data.get("dates", []):
|
||||||
|
date = Date(date_str=date_str)
|
||||||
|
db.session.add(date)
|
||||||
|
db.session.commit()
|
||||||
|
# Attendance
|
||||||
|
for idx, player_name in enumerate(data["players"] + [data["guest"]]):
|
||||||
|
key = f"{date_str}|{idx}"
|
||||||
|
status = data["attendance"].get(key)
|
||||||
|
if status:
|
||||||
|
if player_name == data["guest"]:
|
||||||
|
# Guest is not stored as player, skip
|
||||||
|
continue
|
||||||
|
player = Player.query.filter_by(name=player_name).first()
|
||||||
|
if player:
|
||||||
|
db.session.add(Attendance(date_id=date.id, player_id=player.id, status='yes' if status is True else 'no'))
|
||||||
|
# Guest name
|
||||||
|
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('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
@ -38,17 +98,26 @@ def reports():
|
|||||||
|
|
||||||
@app.route('/api/data', methods=['GET'])
|
@app.route('/api/data', methods=['GET'])
|
||||||
def get_data():
|
def get_data():
|
||||||
return jsonify(load_data())
|
get_initial_data()
|
||||||
|
return jsonify(db_to_json())
|
||||||
|
|
||||||
@app.route('/api/data', methods=['POST'])
|
@app.route('/api/data', methods=['POST'])
|
||||||
def update_data():
|
def update_data():
|
||||||
data = request.json
|
data = request.json
|
||||||
save_data(data)
|
json_to_db(data)
|
||||||
return jsonify({"status": "success"})
|
return jsonify({"status": "success"})
|
||||||
|
|
||||||
|
# Optional: export from DB as JSON (for compatibility)
|
||||||
@app.route('/export-data')
|
@app.route('/export-data')
|
||||||
def export_data():
|
def export_data():
|
||||||
return send_from_directory(directory='data', path='attendance_data.json', as_attachment=True)
|
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__':
|
if __name__ == '__main__':
|
||||||
import os
|
import os
|
||||||
|
|||||||
@ -1 +1,3 @@
|
|||||||
flask
|
flask
|
||||||
|
sqlalchemy
|
||||||
|
psycopg2-binary
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user