Files
SPA-landing/schadenprotokoll/api/app.py
Admin a9eaa81c37 Add template upload functionality to Schadenprotokoll
- New Templates tab for PDF and Word template management
- API endpoints for listing and uploading templates
- Automatic backup of old templates before replacement

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-21 11:54:00 +00:00

138 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""
Schadenprotokoll API - Flask Backend
Endpunkte: /generate, /analyze, /vorbericht, /templates
"""
from flask import Flask, request, jsonify, send_file
from flask_cors import CORS
import tempfile
import os
from processors import parse_laufzettel, fill_pdf, analyze_pdf, generate_vorbericht
app = Flask(__name__)
CORS(app)
TEMPLATES_DIR = "/opt/stacks/spa-hosting/html/schadenprotokoll/templates"
TEMPLATE_PDF = os.path.join(TEMPLATES_DIR, "protokoll.pdf")
TEMPLATE_DOCX = os.path.join(TEMPLATES_DIR, "vorbericht.docx")
@app.route("/health", methods=["GET"])
def health():
return jsonify({"status": "ok"})
@app.route("/templates", methods=["GET"])
def list_templates():
"""Listet alle verfuegbaren Templates"""
templates = []
for f in os.listdir(TEMPLATES_DIR):
path = os.path.join(TEMPLATES_DIR, f)
if os.path.isfile(path) and not f.endswith(".bak"):
templates.append({
"name": f,
"size": os.path.getsize(path),
"type": "pdf" if f.endswith(".pdf") else "docx"
})
return jsonify({"templates": templates})
@app.route("/templates/upload", methods=["POST"])
def upload_template():
"""Laedt ein neues Template hoch"""
if "file" not in request.files:
return jsonify({"error": "Keine Datei hochgeladen"}), 400
file = request.files["file"]
ttype = request.form.get("type", "pdf")
if ttype == "pdf" and not file.filename.endswith(".pdf"):
return jsonify({"error": "PDF-Template muss .pdf sein"}), 400
if ttype == "docx" and not file.filename.endswith(".docx"):
return jsonify({"error": "Word-Template muss .docx sein"}), 400
target = TEMPLATE_PDF if ttype == "pdf" else TEMPLATE_DOCX
backup = target + ".bak"
if os.path.exists(target):
if os.path.exists(backup):
os.remove(backup)
os.rename(target, backup)
file.save(target)
return jsonify({"success": True, "message": f"Template erfolgreich hochgeladen"})
@app.route("/generate", methods=["POST"])
def generate():
"""Laufzettel.docx -> vorausgefuelltes Protokoll.pdf"""
if "file" not in request.files:
return jsonify({"error": "Keine Datei hochgeladen"}), 400
file = request.files["file"]
if not file.filename.endswith(".docx"):
return jsonify({"error": "Nur .docx Dateien erlaubt"}), 400
with tempfile.NamedTemporaryFile(suffix=".docx", delete=False) as tmp_in:
file.save(tmp_in.name)
try:
data = parse_laufzettel(tmp_in.name)
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp_out:
fill_pdf(TEMPLATE_PDF, tmp_out.name, data)
os.unlink(tmp_in.name)
return send_file(tmp_out.name, mimetype="application/pdf",
as_attachment=True, download_name="Schadenprotokoll_vorbefuellt.pdf")
except Exception as e:
os.unlink(tmp_in.name)
return jsonify({"error": str(e)}), 500
@app.route("/analyze", methods=["POST"])
def analyze():
"""Ausgefuelltes PDF -> JSON mit allen Feldern"""
if "file" not in request.files:
return jsonify({"error": "Keine Datei hochgeladen"}), 400
file = request.files["file"]
if not file.filename.endswith(".pdf"):
return jsonify({"error": "Nur .pdf Dateien erlaubt"}), 400
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp:
file.save(tmp.name)
try:
result = analyze_pdf(tmp.name)
os.unlink(tmp.name)
return jsonify({"success": True, "data": result})
except Exception as e:
os.unlink(tmp.name)
return jsonify({"error": str(e)}), 500
@app.route("/vorbericht", methods=["POST"])
def vorbericht():
"""Ausgefuelltes PDF -> Vorbericht.docx"""
if "file" not in request.files:
return jsonify({"error": "Keine Datei hochgeladen"}), 400
file = request.files["file"]
if not file.filename.endswith(".pdf"):
return jsonify({"error": "Nur .pdf Dateien erlaubt"}), 400
with tempfile.NamedTemporaryFile(suffix=".pdf", delete=False) as tmp_in:
file.save(tmp_in.name)
try:
pdf_data = analyze_pdf(tmp_in.name)
with tempfile.NamedTemporaryFile(suffix=".docx", delete=False) as tmp_out:
generate_vorbericht(pdf_data, TEMPLATE_DOCX, tmp_out.name)
os.unlink(tmp_in.name)
return send_file(tmp_out.name,
mimetype="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
as_attachment=True, download_name="Vorbericht.docx")
except Exception as e:
os.unlink(tmp_in.name)
return jsonify({"error": str(e)}), 500
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5050, debug=False)