diff --git a/app.py b/app.py index dc912d8..0beea4c 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,3 @@ - from flask import Flask, request, jsonify, session, render_template_string, redirect import os import json @@ -24,7 +23,7 @@ default_users = [ 'is_active': True, 'created_at': datetime.now().isoformat(), 'last_login': None, - 'force_password_change': False # Nach erstmaligem Login Passwort ändern + 'force_password_change': False } ] @@ -79,7 +78,7 @@ Buchungsdetails: - Datum: {date} - Uhrzeit: {time} - Personen: {guests} -- Tische: {tables} +- Raum: {room} Wir freuen uns auf Ihren Besuch! @@ -124,12 +123,14 @@ Ihr Restaurant-Team """ } -# Datenstruktur +# Datenstruktur - Räume mit Kapazität und Block-Status rooms = [ { 'id': 1, 'name': 'Hauptraum', 'description': 'Großer Saal mit Fensterfront', + 'capacity': 40, + 'blocked': False, 'tables': [ {'id': 1, 'name': 'Tisch 1', 'seats': 4, 'shape': 'circle'}, {'id': 2, 'name': 'Tisch 2', 'seats': 2, 'shape': 'circle'}, @@ -141,6 +142,8 @@ rooms = [ 'id': 2, 'name': 'Nebenraum', 'description': 'Gemütlicher kleiner Raum', + 'capacity': 20, + 'blocked': False, 'tables': [ {'id': 5, 'name': 'Tisch A', 'seats': 4, 'shape': 'circle'}, {'id': 6, 'name': 'Tisch B', 'seats': 4, 'shape': 'circle'}, @@ -150,6 +153,8 @@ rooms = [ 'id': 3, 'name': 'Terrasse', 'description': 'Draußen unter dem Vordach', + 'capacity': 15, + 'blocked': False, 'tables': [ {'id': 7, 'name': 'Tisch T1', 'seats': 4, 'shape': 'rect'}, {'id': 8, 'name': 'Tisch T2', 'seats': 4, 'shape': 'rect'}, @@ -166,6 +171,12 @@ def generate_booking_id(): if not any(r.get('booking_id') == booking_id for r in reservations): return booking_id +def get_room(room_id): + for room in rooms: + if room['id'] == room_id: + return room + return None + def get_table(table_id): for room in rooms: for table in room['tables']: @@ -176,11 +187,14 @@ def get_table(table_id): def get_available_tables(date_str, time_str): available = [] for room in rooms: + if room.get('blocked', False): + continue for table in room['tables']: table_copy = table.copy() table_copy['room_id'] = room['id'] table_copy['room_name'] = room['name'] - available.append(table_copy) + if is_table_available(table['id'], date_str, time_str): + available.append(table_copy) return available def is_table_available(table_id, date_str, time_str): @@ -190,6 +204,44 @@ def is_table_available(table_id, date_str, time_str): return False return True +def auto_assign_tables(room_id, guests, date_str, time_str): + """Automatische Tisch-Zuweisung basierend auf Raum und Gästeanzahl""" + room = get_room(room_id) + if not room: + return None, "Raum nicht gefunden" + + if room.get('blocked', False): + return None, "Raum ist derzeit nicht verfügbar" + + # Alle verfügbaren Tische im Raum + available_tables = [] + for table in room['tables']: + if is_table_available(table['id'], date_str, time_str): + available_tables.append(table) + + if not available_tables: + return None, "Keine Tische im Raum verfügbar" + + # Sortiere nach Sitzplätzen (größte zuerst) + available_tables.sort(key=lambda t: t['seats'], reverse=True) + + # Finde beste Kombination für Gäste + total_seats = sum(t['seats'] for t in available_tables) + if total_seats < guests: + return None, f"Nicht genügend Platz im Raum. Verfügbar: {total_seats} Plätze" + + # Wähle Tische aus (greedy - erst große, dann kleine) + selected_tables = [] + remaining_guests = guests + + for table in available_tables: + if remaining_guests <= 0: + break + selected_tables.append(table) + remaining_guests -= table['seats'] + + return [t['id'] for t in selected_tables], None + def send_email_smtp(to_email, subject, body): try: import smtplib @@ -251,21 +303,9 @@ PUBLIC_RESERVATION_HTML = ''' width: 100%; padding: 1rem; border: 2px solid #e0e0e0; border-radius: 10px; font-size: 1rem; } - .form-group input:focus { outline: none; border-color: #667eea; } - .checkbox-group { - display: flex; align-items: center; gap: 0.75rem; - padding: 1rem; background: #f8f9fa; border-radius: 10px; - border: 2px solid #e0e0e0; cursor: pointer; - } - .checkbox-group input[type="checkbox"] { width: 24px; height: 24px; } - .table-selection { - display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 0.75rem; - } - .table-option { - border: 2px solid #e0e0e0; border-radius: 12px; padding: 1rem; - text-align: center; cursor: pointer; transition: all 0.2s; - } - .table-option.selected { border-color: #667eea; background: #f0f4ff; } + .form-group input:focus, .form-group select:focus { outline: none; border-color: #667eea; } + .error-msg { display: none; color: #ef4444; font-size: 0.85rem; margin-top: 0.5rem; } + .success-message { text-align: center; padding: 3rem 2rem; } .btn { width: 100%; padding: 1.25rem; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); @@ -273,12 +313,13 @@ PUBLIC_RESERVATION_HTML = ''' font-size: 1.1rem; font-weight: 600; cursor: pointer; } .btn:disabled { opacity: 0.6; cursor: not-allowed; } - .success-message { text-align: center; padding: 3rem 2rem; } .booking-id { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 1rem 2rem; border-radius: 10px; font-size: 1.5rem; font-weight: bold; margin: 1rem 0; letter-spacing: 2px; } + .hidden { display: none !important; } + .capacity-info { color: #667eea; font-size: 0.9rem; margin-top: 0.5rem; }
@@ -314,22 +355,20 @@ PUBLIC_RESERVATION_HTML = '''Variablen: {name}, {booking_id}, {date}, {time}, {guests}, {tables}
+Variablen: {name}, {booking_id}, {date}, {time}, {guests}, {room}