diff --git a/Web/app.py b/Web/app.py index 7ade039..951c25b 100755 --- a/Web/app.py +++ b/Web/app.py @@ -4113,15 +4113,24 @@ def student_cards_admin(): all_cards = [_decrypt_student_card_doc(card) for card in all_cards] client.close() + # Alle eindeutigen Klassen für das Dropdown ermitteln + client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) + db = client[cfg.MONGODB_DB] + student_cards_collection = db['student_cards'] + + # Extrahiere alle vorhandenen Klassen, entferne leere/None Werte und sortiere sie + raw_classes = student_cards_collection.distinct('Klasse') + available_classes = sorted([c for c in raw_classes if c]) + + client.close() + return render_template( 'student_cards_admin.html', - username=session['username'], - student_cards=all_cards, + student_cards=student_cards, edit_mode=edit_mode, form_data=form_data, - config={'default': cfg.STUDENT_DEFAULT_BORROW_DAYS}, - library_module_enabled=cfg.MODULES.is_enabled('library'), - student_cards_module_enabled=cfg.MODULES.is_enabled('student_cards') + available_classes=available_classes, + config=cfg.get_school_info() ) @@ -4202,7 +4211,7 @@ def student_card_barcode_download(): if 'username' not in session: return redirect(url_for('login')) current_permissions = us.get_effective_permissions(session['username']) - + if not current_permissions['actions'].get('can_manage_users', False): flash('Ihnen fehlen die nötigen Berechtigungen, um diese Aktion auszuführen.', 'error') return redirect(url_for('library_view')) @@ -4215,12 +4224,13 @@ def student_card_barcode_download(): from reportlab.pdfgen import canvas from reportlab.lib.units import mm from reportlab.lib.colors import HexColor, white, black + from reportlab.pdfbase.pdfmetrics import stringWidth from io import BytesIO import barcode from barcode.writer import ImageWriter import tempfile import os - + client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] student_cards = db['student_cards'] @@ -4230,7 +4240,7 @@ def student_card_barcode_download(): pdf_buffer = BytesIO() c = canvas.Canvas(pdf_buffer, pagesize=A4) - + page_width, page_height = A4 margin = 10 * mm card_width = 88 * mm @@ -4242,130 +4252,144 @@ def student_card_barcode_download(): y_start = page_height - margin y_pos = y_start col_idx = 0 - + # Professional color palette header_color = HexColor("#0F172A") # Sehr dunkles blau accent_color = HexColor("#2563EB") # Helles blau - light_bg = HexColor("#F8FAFC") # Sehr heller grau - card_bg_color = HexColor("#FFFFFF") # Weiß - text_dark = HexColor("#1E293B") # Dunkler text - text_gray = HexColor("#64748B") # Grauer text - + light_bg = HexColor("#F8FAFC") # Sehr heller grau + card_bg_color = HexColor("#FFFFFF") # Weiß + text_dark = HexColor("#1E293B") # Dunkler text + text_gray = HexColor("#64748B") # Grauer text + for i, card in enumerate(all_cards): if col_idx == 0 and i > 0: y_pos -= (card_height + gap_y) - + # New page if needed if y_pos - card_height < margin: c.showPage() y_pos = y_start col_idx = 0 - + x_pos = x_positions[col_idx] - + # Card shadow effect (unter border) c.setFillColor(HexColor("#E2E8F0")) - c.rect(x_pos + 0.5*mm, y_pos - card_height - 0.5*mm, card_width, card_height, fill=1, stroke=0) - + c.rect(x_pos + 0.5 * mm, y_pos - card_height - 0.5 * mm, card_width, card_height, fill=1, stroke=0) + # Card background c.setLineWidth(1) c.setFillColor(card_bg_color) c.setStrokeColor(HexColor("#CBD5E1")) c.rect(x_pos, y_pos - card_height, card_width, card_height, fill=1, stroke=1) - + # Left info section (38mm) info_width = 38 * mm c.setFillColor(light_bg) c.rect(x_pos, y_pos - card_height, info_width, card_height, fill=1, stroke=0) - + # Header bar c.setFillColor(header_color) - c.rect(x_pos, y_pos - 10*mm, card_width, 10*mm, fill=1, stroke=0) - + c.rect(x_pos, y_pos - 10 * mm, card_width, 10 * mm, fill=1, stroke=0) + # Header accent line c.setStrokeColor(accent_color) c.setLineWidth(2) - c.line(x_pos, y_pos - 10*mm, x_pos + card_width, y_pos - 10*mm) - + c.line(x_pos, y_pos - 10 * mm, x_pos + card_width, y_pos - 10 * mm) school_name = cfg.get_school_info() - school_name = school_name["name"] - # "SCHÜLERAUSWEIS" text in header - c.setFont("Helvetica-Bold", 9) + school_name_str = str(school_name["name"]) + + # Zwei-Zeilen-Header: 1. BIBLIOTHEKSAUSWEIS, 2. Schulname (dynamisch) + c.setFont("Helvetica-Bold", 8) c.setFillColor(white) - c.drawString(x_pos + 3*mm, y_pos - 6.5*mm, f"BIBLIOTHEKSAUSWEIS - {str(school_name)}") - + c.drawString(x_pos + 3 * mm, y_pos - 4 * mm, "BIBLIOTHEKSAUSWEIS") + + # Dynamische Anpassung des Schulnamens an die Breite + font_size = 8 + while stringWidth(school_name_str, "Helvetica-Bold", font_size) > (card_width - 6 * mm) and font_size > 4: + font_size -= 0.5 + + c.setFont("Helvetica-Bold", font_size) + c.drawString(x_pos + 3 * mm, y_pos - 8 * mm, school_name_str) + # Student name - large and bold c.setFillColor(text_dark) c.setFont("Helvetica-Bold", 10) name = card['SchülerName'][:20] - c.drawString(x_pos + 3*mm, y_pos - 14*mm, name) - + c.drawString(x_pos + 3 * mm, y_pos - 16 * mm, name) + # ID with label c.setFont("Helvetica", 8) c.setFillColor(text_gray) - c.drawString(x_pos + 3*mm, y_pos - 18*mm, "Ausweis ID:") + c.drawString(x_pos + 3 * mm, y_pos - 20 * mm, "Ausweis ID:") c.setFillColor(text_dark) c.setFont("Helvetica-Bold", 9) - c.drawString(x_pos + 3*mm, y_pos - 21*mm, str(card['AusweisId'])) - + c.drawString(x_pos + 3 * mm, y_pos - 23 * mm, str(card['AusweisId'])) + # Class with label if card.get('Klasse'): c.setFont("Helvetica", 8) c.setFillColor(text_gray) - c.drawString(x_pos + 3*mm, y_pos - 25*mm, "Klasse:") + c.drawString(x_pos + 3 * mm, y_pos - 27 * mm, "Klasse:") c.setFillColor(text_dark) c.setFont("Helvetica-Bold", 9) - c.drawString(x_pos + 3*mm, y_pos - 28*mm, card['Klasse']) - c.drawString(x_pos + 3*mm, y_pos - 31*mm, "-") - c.drawString(x_pos + 3*mm, y_pos - 34*mm, "-") - c.drawString(x_pos + 3*mm, y_pos - 37*mm, "-") - c.drawString(x_pos + 3*mm, y_pos - 40*mm, "-") + c.drawString(x_pos + 3 * mm, y_pos - 30 * mm, card['Klasse']) + c.drawString(x_pos + 3 * mm, y_pos - 33 * mm, "-") + c.drawString(x_pos + 3 * mm, y_pos - 36 * mm, "-") + c.drawString(x_pos + 3 * mm, y_pos - 39 * mm, "-") + c.drawString(x_pos + 3 * mm, y_pos - 42 * mm, "-") # Right barcode section with border highlight - barcode_x_start = x_pos + info_width + 1*mm + barcode_x_start = x_pos + info_width + 1 * mm c.setFillColor(accent_color) c.setLineWidth(0) - c.rect(barcode_x_start - 1*mm, y_pos - card_height, - card_width - info_width + 1*mm, 2*mm, fill=1, stroke=0) - - # Generate and add larger barcode + c.rect(barcode_x_start - 1 * mm, y_pos - card_height, + card_width - info_width + 1 * mm, 2 * mm, fill=1, stroke=0) + + # Generate and add dynamically sized barcode try: temp_dir = tempfile.gettempdir() barcode_path = os.path.join(temp_dir, f"barcode_{card['AusweisId']}") - - # Generate barcode with higher module width for better scanning + + # ImageWriter Settings für maximalen Platz und Lesbarkeit + options = { + 'write_text': False, # Text entfernen (spart Platz) + 'quiet_zone': 1.0, # Minimaler Rand + 'dpi': 300 # Hohe Auflösung + } + barcode_obj = barcode.get('code128', str(card['AusweisId']), writer=ImageWriter()) - barcode_obj.save(barcode_path) + barcode_obj.save(barcode_path, options=options) barcode_file = f"{barcode_path}.png" - + if os.path.exists(barcode_file): - # Larger barcode taking up most of right section - barcode_width = (card_width - info_width - 4*mm) - barcode_height = 16*mm - barcode_y = y_pos - card_height + (card_height - barcode_height) / 2 + 2*mm - - c.drawImage(barcode_file, - barcode_x_start + 1*mm, - barcode_y, - width=barcode_width, - height=barcode_height, - preserveAspectRatio=True) + # Barcode über den fast kompletten restlichen Bereich strecken + barcode_width = (card_width - info_width - 4 * mm) + barcode_height = card_height - 15 * mm + barcode_y = y_pos - card_height + 2.5 * mm + + c.drawImage(barcode_file, + barcode_x_start + 1 * mm, + barcode_y, + width=barcode_width, + height=barcode_height, + preserveAspectRatio=False) # Strecken erlauben für maximalen Scanbereich os.remove(barcode_file) else: raise Exception("Barcode file not created") except Exception as e: c.setFont("Helvetica", 7) c.setFillColor(HexColor("#DC2626")) - c.drawString(barcode_x_start + 2*mm, y_pos - card_height + 20*mm, "⚠️ Barcode Error") - + c.drawString(barcode_x_start + 2 * mm, y_pos - card_height + 20 * mm, "⚠️ Barcode Error") + col_idx += 1 if col_idx >= cols: col_idx = 0 - + c.save() pdf_buffer.seek(0) - + return send_file( pdf_buffer, mimetype='application/pdf', @@ -4378,6 +4402,187 @@ def student_card_barcode_download(): return redirect(url_for('student_cards_admin')) +@app.route('/student_card_class_barcode_download', methods=['GET']) +def student_card_class_barcode_download(): + """ + Download PDF with student card barcodes filtered by a specific class from dropdown. + """ + from flask import request, session, redirect, url_for, send_file, flash + + if 'username' not in session: + return redirect(url_for('login')) + + current_permissions = us.get_effective_permissions(session['username']) + if not current_permissions['actions'].get('can_manage_users', False): + flash('Ihnen fehlen die nötigen Berechtigungen, um diese Aktion auszuführen.', 'error') + return redirect(url_for('library_view')) + + class_name = request.args.get('class_name', '').strip() + if not class_name: + flash('Bitte wählen Sie eine Klasse aus.', 'error') + return redirect(url_for('student_cards_admin')) + + try: + from reportlab.lib.pagesizes import A4 + from reportlab.pdfgen import canvas + from reportlab.lib.units import mm + from reportlab.lib.colors import HexColor, white + from reportlab.pdfbase.pdfmetrics import stringWidth + from io import BytesIO + import barcode + from barcode.writer import ImageWriter + import tempfile + import os + import datetime + + client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) + db = client[cfg.MONGODB_DB] + student_cards = db['student_cards'] + + class_cards = list(student_cards.find({'Klasse': class_name}).sort('AusweisId', 1)) + class_cards = [_decrypt_student_card_doc(card) for card in class_cards] + client.close() + + if not class_cards: + flash(f'Keine Ausweise für die Klasse "{class_name}" gefunden.', 'error') + return redirect(url_for('student_cards_admin')) + + pdf_buffer = BytesIO() + c = canvas.Canvas(pdf_buffer, pagesize=A4) + + page_width, page_height = A4 + margin = 10 * mm + card_width = 88 * mm + card_height = 56 * mm + cols = 2 + gap_x = 8 * mm + gap_y = 8 * mm + x_positions = [margin, margin + card_width + gap_x] + y_start = page_height - margin + y_pos = y_start + col_idx = 0 + + header_color = HexColor("#0F172A") + accent_color = HexColor("#2563EB") + light_bg = HexColor("#F8FAFC") + card_bg_color = HexColor("#FFFFFF") + text_dark = HexColor("#1E293B") + text_gray = HexColor("#64748B") + + for i, card in enumerate(class_cards): + if col_idx == 0 and i > 0: + y_pos -= (card_height + gap_y) + + if y_pos - card_height < margin: + c.showPage() + y_pos = y_start + col_idx = 0 + + x_pos = x_positions[col_idx] + + c.setFillColor(HexColor("#E2E8F0")) + c.rect(x_pos + 0.5 * mm, y_pos - card_height - 0.5 * mm, card_width, card_height, fill=1, stroke=0) + + c.setLineWidth(1) + c.setFillColor(card_bg_color) + c.setStrokeColor(HexColor("#CBD5E1")) + c.rect(x_pos, y_pos - card_height, card_width, card_height, fill=1, stroke=1) + + info_width = 38 * mm + c.setFillColor(light_bg) + c.rect(x_pos, y_pos - card_height, info_width, card_height, fill=1, stroke=0) + + c.setFillColor(header_color) + c.rect(x_pos, y_pos - 10 * mm, card_width, 10 * mm, fill=1, stroke=0) + + c.setStrokeColor(accent_color) + c.setLineWidth(2) + c.line(x_pos, y_pos - 10 * mm, x_pos + card_width, y_pos - 10 * mm) + + school_name = cfg.get_school_info() + school_name_str = str(school_name["name"]) + + c.setFont("Helvetica-Bold", 8) + c.setFillColor(white) + c.drawString(x_pos + 3 * mm, y_pos - 4 * mm, "BIBLIOTHEKSAUSWEIS") + + font_size = 8 + while stringWidth(school_name_str, "Helvetica-Bold", font_size) > (card_width - 6 * mm) and font_size > 4: + font_size -= 0.5 + + c.setFont("Helvetica-Bold", font_size) + c.drawString(x_pos + 3 * mm, y_pos - 8 * mm, school_name_str) + + c.setFillColor(text_dark) + c.setFont("Helvetica-Bold", 10) + name = card.get('SchülerName', '')[:20] + c.drawString(x_pos + 3 * mm, y_pos - 16 * mm, name) + + c.setFont("Helvetica", 8) + c.setFillColor(text_gray) + c.drawString(x_pos + 3 * mm, y_pos - 20 * mm, "Ausweis ID:") + c.setFillColor(text_dark) + c.setFont("Helvetica-Bold", 9) + c.drawString(x_pos + 3 * mm, y_pos - 23 * mm, str(card.get('AusweisId', ''))) + + if card.get('Klasse'): + c.setFont("Helvetica", 8) + c.setFillColor(text_gray) + c.drawString(x_pos + 3 * mm, y_pos - 27 * mm, "Klasse:") + c.setFillColor(text_dark) + c.setFont("Helvetica-Bold", 9) + c.drawString(x_pos + 3 * mm, y_pos - 30 * mm, card['Klasse']) + + barcode_x_start = x_pos + info_width + 1 * mm + c.setFillColor(accent_color) + c.setLineWidth(0) + c.rect(barcode_x_start - 1 * mm, y_pos - card_height, card_width - info_width + 1 * mm, 2 * mm, fill=1, + stroke=0) + + try: + temp_dir = tempfile.gettempdir() + barcode_path = os.path.join(temp_dir, f"barcode_{card.get('AusweisId', i)}") + + options = { + 'write_text': False, + 'quiet_zone': 1.0, + 'dpi': 300 + } + + barcode_obj = barcode.get('code128', str(card.get('AusweisId', '')), writer=ImageWriter()) + barcode_obj.save(barcode_path, options=options) + barcode_file = f"{barcode_path}.png" + + if os.path.exists(barcode_file): + barcode_width = (card_width - info_width - 4 * mm) + barcode_height = card_height - 15 * mm + barcode_y = y_pos - card_height + 2.5 * mm + + c.drawImage(barcode_file, barcode_x_start + 1 * mm, barcode_y, + width=barcode_width, height=barcode_height, preserveAspectRatio=False) + os.remove(barcode_file) + except Exception as e: + pass + + col_idx += 1 + if col_idx >= cols: + col_idx = 0 + + c.save() + pdf_buffer.seek(0) + + filename = f'ausweise_klasse_{class_name.replace(" ", "_")}_{datetime.datetime.now().strftime("%Y%m%d")}.pdf' + + return send_file( + pdf_buffer, + mimetype='application/pdf', + as_attachment=True, + download_name=filename + ) + except Exception as e: + flash('Fehler beim PDF-Download', 'error') + return redirect(url_for('student_cards_admin')) + @app.route('/student_card_single_barcode_download/', methods=['GET']) def student_card_single_barcode_download(card_id): """ @@ -4386,7 +4591,7 @@ def student_card_single_barcode_download(card_id): if 'username' not in session: return redirect(url_for('login')) current_permissions = us.get_effective_permissions(session['username']) - + if not current_permissions['actions'].get('can_manage_users', False): flash('Ihnen fehlen die nötigen Berechtigungen, um diese Aktion auszuführen.', 'error') return redirect(url_for('library_view')) @@ -4399,148 +4604,165 @@ def student_card_single_barcode_download(card_id): from reportlab.pdfgen import canvas from reportlab.lib.units import mm from reportlab.lib.colors import HexColor, white, black + from reportlab.pdfbase.pdfmetrics import stringWidth from io import BytesIO from bson.objectid import ObjectId import barcode from barcode.writer import ImageWriter import tempfile import os - + client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT) db = client[cfg.MONGODB_DB] student_cards = db['student_cards'] card = student_cards.find_one({'_id': ObjectId(card_id)}) card = _decrypt_student_card_doc(card) client.close() - + if not card: flash('Ausweis nicht gefunden.', 'error') return redirect(url_for('student_cards_admin')) pdf_buffer = BytesIO() c = canvas.Canvas(pdf_buffer, pagesize=A4) - + page_width, page_height = A4 - margin = 20 * mm card_width = 105 * mm card_height = 70 * mm x_pos = (page_width - card_width) / 2 - y_pos = (page_height - card_height) / 2 - + + # Korrektur des y_pos auf die OBERKANTE, damit die nachfolgenden Rechnungen bündig sind + y_pos = (page_height + card_height) / 2 + # Professional color palette - header_color = HexColor("#0F172A") # Sehr dunkles blau - accent_color = HexColor("#2563EB") # Helles blau - light_bg = HexColor("#F8FAFC") # Sehr heller grau - card_bg_color = HexColor("#FFFFFF") # Weiß - text_dark = HexColor("#1E293B") # Dunkler text - text_gray = HexColor("#64748B") # Grauer text - + header_color = HexColor("#0F172A") + accent_color = HexColor("#2563EB") + light_bg = HexColor("#F8FAFC") + card_bg_color = HexColor("#FFFFFF") + text_dark = HexColor("#1E293B") + text_gray = HexColor("#64748B") + # Card shadow effect c.setFillColor(HexColor("#E2E8F0")) - c.rect(x_pos + 1*mm, y_pos - card_height - 1*mm, card_width, card_height, fill=1, stroke=0) - + c.rect(x_pos + 1 * mm, y_pos - card_height - 1 * mm, card_width, card_height, fill=1, stroke=0) + # Card background c.setLineWidth(1.5) c.setFillColor(card_bg_color) c.setStrokeColor(HexColor("#CBD5E1")) - c.rect(x_pos, y_pos, card_width, card_height, fill=1, stroke=1) - + c.rect(x_pos, y_pos - card_height, card_width, card_height, fill=1, stroke=1) + # Left info section (50mm) info_width = 50 * mm c.setFillColor(light_bg) c.rect(x_pos, y_pos - card_height, info_width, card_height, fill=1, stroke=0) - + # Vertical divider line c.setStrokeColor(accent_color) c.setLineWidth(3) c.line(x_pos + info_width, y_pos - card_height, x_pos + info_width, y_pos) - + # Header bar c.setFillColor(header_color) - c.rect(x_pos, y_pos - 10*mm, card_width, 10*mm, fill=1, stroke=0) - + c.rect(x_pos, y_pos - 10 * mm, card_width, 10 * mm, fill=1, stroke=0) + # Header accent line c.setStrokeColor(accent_color) c.setLineWidth(2.5) - c.line(x_pos, y_pos - 10*mm, x_pos + card_width, y_pos - 10*mm) - + c.line(x_pos, y_pos - 10 * mm, x_pos + card_width, y_pos - 10 * mm) + school_name = cfg.get_school_info() - school_name = school_name["name"] - # "SCHÜLERAUSWEIS" text in header - c.setFont("Helvetica-Bold", 11) + school_name_str = str(school_name["name"]) + + # Zwei-Zeilen-Header + c.setFont("Helvetica-Bold", 10) c.setFillColor(white) - c.drawString(x_pos + 4*mm, y_pos - 6.5*mm, f"BIBLIOTHEKSAUSWEIS - {str(school_name)}") - + c.drawString(x_pos + 4 * mm, y_pos - 4.5 * mm, "BIBLIOTHEKSAUSWEIS") + + # Dynamische Größe für den Schulnamen + font_size = 10 + while stringWidth(school_name_str, "Helvetica-Bold", font_size) > (card_width - 8 * mm) and font_size > 4: + font_size -= 0.5 + + c.setFont("Helvetica-Bold", font_size) + c.drawString(x_pos + 4 * mm, y_pos - 8.5 * mm, school_name_str) + # Student name - large and prominent c.setFillColor(text_dark) c.setFont("Helvetica-Bold", 12) name = card['SchülerName'][:25] - c.drawString(x_pos + 4*mm, y_pos - 16*mm, name) - + c.drawString(x_pos + 4 * mm, y_pos - 18 * mm, name) + # ID section with label c.setFont("Helvetica", 9) c.setFillColor(text_gray) - c.drawString(x_pos + 4*mm, y_pos - 21*mm, "Ausweis-ID:") - + c.drawString(x_pos + 4 * mm, y_pos - 24 * mm, "Ausweis-ID:") + c.setFillColor(text_dark) c.setFont("Helvetica-Bold", 11) - c.drawString(x_pos + 4*mm, y_pos - 25*mm, str(card['AusweisId'])) - + c.drawString(x_pos + 4 * mm, y_pos - 28 * mm, str(card['AusweisId'])) + # Class section if card.get('Klasse'): c.setFont("Helvetica", 9) c.setFillColor(text_gray) - c.drawString(x_pos + 4*mm, y_pos - 30*mm, "Klasse:") - + c.drawString(x_pos + 4 * mm, y_pos - 34 * mm, "Klasse:") + c.setFillColor(text_dark) c.setFont("Helvetica-Bold", 11) - c.drawString(x_pos + 4*mm, y_pos - 34*mm, card['Klasse']) - + c.drawString(x_pos + 4 * mm, y_pos - 38 * mm, card['Klasse']) + # Barcode section - right side with blue accent - barcode_x_start = x_pos + info_width + 3*mm + barcode_x_start = x_pos + info_width + 3 * mm c.setFillColor(accent_color) c.setLineWidth(0) - c.rect(x_pos + info_width, y_pos - card_height, - card_width - info_width, 3*mm, fill=1, stroke=0) - - # Generate and add large barcode + c.rect(x_pos + info_width, y_pos - card_height, + card_width - info_width, 3 * mm, fill=1, stroke=0) + + # Generate and add large dynamically sized barcode try: temp_dir = tempfile.gettempdir() barcode_path = os.path.join(temp_dir, f"barcode_{card['AusweisId']}") - - # Generate barcode with better sizing + + # Options anpassen für Scanbarkeit + options = { + 'write_text': False, + 'quiet_zone': 1.0, + 'dpi': 300 + } + barcode_obj = barcode.get('code128', str(card['AusweisId']), writer=ImageWriter()) - barcode_obj.save(barcode_path) + barcode_obj.save(barcode_path, options=options) barcode_file = f"{barcode_path}.png" - + if os.path.exists(barcode_file): - # Large barcode on right side - barcode_width = (card_width - info_width - 8*mm) - barcode_height = 20*mm - barcode_y_offset = (card_height - 10*mm - barcode_height) / 2 - - c.drawImage(barcode_file, - barcode_x_start, - y_pos - card_height + barcode_y_offset + 5*mm, - width=barcode_width, - height=barcode_height, - preserveAspectRatio=True) + # Den gesamten Platz auf der rechten Seite ausnutzen + barcode_width = (card_width - info_width - 8 * mm) + barcode_height = card_height - 18 * mm + barcode_y = y_pos - card_height + 5 * mm + + c.drawImage(barcode_file, + barcode_x_start + 1 * mm, + barcode_y, + width=barcode_width, + height=barcode_height, + preserveAspectRatio=False) # Ausdehnung in alle Richtungen os.remove(barcode_file) else: raise Exception("Barcode file not created") except Exception as e: c.setFont("Helvetica", 9) c.setFillColor(HexColor("#DC2626")) - c.drawString(barcode_x_start + 2*mm, y_pos - card_height + 25*mm, "⚠️ Barcode Error") - + c.drawString(barcode_x_start + 2 * mm, y_pos - card_height + 25 * mm, "⚠️ Barcode Error") + # Bottom info line c.setStrokeColor(HexColor("#CBD5E1")) c.setLineWidth(0.5) - c.line(x_pos, y_pos - card_height + 3*mm, x_pos + card_width, y_pos - card_height + 3*mm) - + c.line(x_pos, y_pos - card_height + 3 * mm, x_pos + card_width, y_pos - card_height + 3 * mm) + c.save() pdf_buffer.seek(0) - + return send_file( pdf_buffer, mimetype='application/pdf', @@ -4552,7 +4774,6 @@ def student_card_single_barcode_download(card_id): flash('Fehler beim PDF-Download', 'error') return redirect(url_for('student_cards_admin')) - @app.route('/login', methods=['GET', 'POST']) def login(): """ diff --git a/Web/templates/student_cards_admin.html b/Web/templates/student_cards_admin.html index 6e77b79..9b79178 100644 --- a/Web/templates/student_cards_admin.html +++ b/Web/templates/student_cards_admin.html @@ -232,6 +232,16 @@

📚 Bibliotheksausweise (Bibliothek)

+
+ + +
+ 📥 Alle Ausweise (PDF) ← Zur Bibliotheks-Upload