The School year rollover button is placed in the school settings.
Release Inventarsystem / release-docker (push) Successful in 2m16s
Release Inventarsystem / release-docker (push) Successful in 2m16s
This commit is contained in:
-63
@@ -228,7 +228,6 @@ def rollover_student_card_classes(dry_run=False, *, max_class=None, graduate_lab
|
|||||||
client.close()
|
client.close()
|
||||||
|
|
||||||
|
|
||||||
# Admin route to trigger rollover manually
|
|
||||||
@app.route('/admin/trigger_school_year_rollover', methods=['POST'])
|
@app.route('/admin/trigger_school_year_rollover', methods=['POST'])
|
||||||
def admin_trigger_school_year_rollover():
|
def admin_trigger_school_year_rollover():
|
||||||
if 'username' not in session:
|
if 'username' not in session:
|
||||||
@@ -3038,42 +3037,6 @@ def optimized_image(filename):
|
|||||||
app.logger.error(f"Error serving optimized image {filename}: {str(e)}")
|
app.logger.error(f"Error serving optimized image {filename}: {str(e)}")
|
||||||
return Response("Optimized image not found", status=404)
|
return Response("Optimized image not found", status=404)
|
||||||
|
|
||||||
|
|
||||||
# @app.route('/QRCodes/<filename>')
|
|
||||||
# def qrcode_file(filename):
|
|
||||||
# """
|
|
||||||
# Serve QR code files from the QRCodes directory.
|
|
||||||
#
|
|
||||||
# Args:
|
|
||||||
# filename (str): Name of the QR code file to serve
|
|
||||||
#
|
|
||||||
# Returns:
|
|
||||||
# flask.Response: The requested QR code file or placeholder image if not found
|
|
||||||
# """
|
|
||||||
# try:
|
|
||||||
# # Check production path first
|
|
||||||
# prod_path = "/var/Inventarsystem/Web/QRCodes"
|
|
||||||
# dev_path = app.config['QR_CODE_FOLDER']
|
|
||||||
# if os.path.exists(os.path.join(prod_path, filename)):
|
|
||||||
# return send_from_directory(prod_path, filename)
|
|
||||||
# if os.path.exists(os.path.join(dev_path, filename)):
|
|
||||||
# return send_from_directory(dev_path, filename)
|
|
||||||
#
|
|
||||||
# # Use a placeholder image if file not found - first try SVG, then PNG
|
|
||||||
# svg_placeholder_path = os.path.join(app.static_folder, 'img', 'no-image.svg')
|
|
||||||
# png_placeholder_path = os.path.join(app.static_folder, 'img', 'no-image.png')
|
|
||||||
#
|
|
||||||
# if os.path.exists(svg_placeholder_path):
|
|
||||||
# return send_from_directory(app.static_folder, 'img/no-image.svg')
|
|
||||||
# elif os.path.exists(png_placeholder_path):
|
|
||||||
# return send_from_directory(app.static_folder, 'img/no-image.png')
|
|
||||||
# else:
|
|
||||||
# return send_from_directory(app.static_folder, 'favicon.ico')
|
|
||||||
# except Exception as e:
|
|
||||||
# print(f"Error serving QR code {filename}: {str(e)}")
|
|
||||||
# return Response("QR code not found", status=404)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/<path:filename>')
|
@app.route('/<path:filename>')
|
||||||
def catch_all_files(filename):
|
def catch_all_files(filename):
|
||||||
"""
|
"""
|
||||||
@@ -3136,32 +3099,6 @@ def test_connection():
|
|||||||
"""
|
"""
|
||||||
return {'status': 'success', 'message': 'Connection successful', 'status_code': 200}
|
return {'status': 'success', 'message': 'Connection successful', 'status_code': 200}
|
||||||
|
|
||||||
""" if sucess in deployment the funktion can be removed
|
|
||||||
@app.route('/user_status')
|
|
||||||
def user_status():
|
|
||||||
|
|
||||||
API endpoint to get the current user's status (username, admin status).
|
|
||||||
Used by JavaScript in templates to personalize the UI.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
JSON: User status information or error if not authenticated
|
|
||||||
|
|
||||||
if 'username' in session:
|
|
||||||
is_admin = us.check_admin(session['username'])
|
|
||||||
return jsonify({
|
|
||||||
'authenticated': True,
|
|
||||||
'username': session['username'],
|
|
||||||
'is_admin': is_admin
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
return jsonify({
|
|
||||||
'authenticated': False,
|
|
||||||
'error': 'Not logged in'
|
|
||||||
}), 401
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
##################################################### changes to be made to account for the new account permison managment system ##############################
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def home():
|
def home():
|
||||||
|
|||||||
@@ -120,9 +120,64 @@
|
|||||||
<p>Diese Angaben erscheinen künftig im amtlichen Audit-PDF und in anderen Behördenberichten.</p>
|
<p>Diese Angaben erscheinen künftig im amtlichen Audit-PDF und in anderen Behördenberichten.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Danger Zone: Schuljahreswechsel -->
|
||||||
|
<div class="card danger-zone" style="grid-column: 1 / -1; border-color: #fca5a5;">
|
||||||
|
<div class="card-header" style="background: #fef2f2; border-bottom: 1px solid #fca5a5;">
|
||||||
|
<h2 style="color: #991b1b;">Erweiterte Aktionen</h2>
|
||||||
|
</div>
|
||||||
|
<div class="card-body" style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 15px;">
|
||||||
|
<div>
|
||||||
|
<strong style="color: #7f1d1d; display: block; font-size: 1.05rem; margin-bottom: 4px;">Schuljahreswechsel durchführen</strong>
|
||||||
|
<span style="color: #991b1b; font-size: 0.9rem;">Diese Aktion bereitet das System auf das neue Schuljahr vor (z. B. Hochstufen von Klassen).</span>
|
||||||
|
</div>
|
||||||
|
<button type="button"
|
||||||
|
id="btn-rollover"
|
||||||
|
class="btn btn-danger"
|
||||||
|
onclick="triggerSchoolYearRollover()">
|
||||||
|
Schuljahreswechsel auslösen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
async function triggerSchoolYearRollover() {
|
||||||
|
if (!confirm('Möchtest du den Schuljahreswechsel wirklich durchführen? Dies kann nicht rückgängig gemacht werden!')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const btn = document.getElementById('btn-rollover');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.textContent = 'Wird ausgeführt...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/admin/trigger_school_year_rollover', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (response.ok && data.ok) {
|
||||||
|
alert('Schuljahreswechsel erfolgreich durchgeführt!\n\nZusammenfassung:\n' + JSON.stringify(data.summary, null, 2));
|
||||||
|
location.reload();
|
||||||
|
} else {
|
||||||
|
alert('Fehler: ' + (data.message || 'Schuljahreswechsel konnte nicht durchgeführt werden.'));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Rollover error:', error);
|
||||||
|
alert('Netzwerk- oder Serverfehler beim Ausführen des Schuljahreswechsels.');
|
||||||
|
} finally {
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.textContent = 'Schuljahreswechsel auslösen';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.container {
|
.container {
|
||||||
max-width: 1100px;
|
max-width: 1100px;
|
||||||
@@ -245,12 +300,17 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-primary {
|
.btn-primary {
|
||||||
background: #2563eb;
|
background: #2563eb;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary:hover {
|
.btn-primary:hover:not(:disabled) {
|
||||||
background: #1d4ed8;
|
background: #1d4ed8;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@@ -261,11 +321,21 @@
|
|||||||
border-color: #d1d5db;
|
border-color: #d1d5db;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-secondary:hover {
|
.btn-secondary:hover:not(:disabled) {
|
||||||
background: #e5e7eb;
|
background: #e5e7eb;
|
||||||
color: #111827;
|
color: #111827;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-danger {
|
||||||
|
background: #ef4444;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-danger:hover:not(:disabled) {
|
||||||
|
background: #dc2626;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.preview-card p {
|
.preview-card p {
|
||||||
margin: 0 0 10px;
|
margin: 0 0 10px;
|
||||||
line-height: 1.45;
|
line-height: 1.45;
|
||||||
@@ -283,5 +353,15 @@
|
|||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.danger-zone .card-body {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.danger-zone .btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
Reference in New Issue
Block a user