Allow user to select PDF template before generating
- Tab 1 now has two upload zones: PDF Template + Laufzettel DOCX - API accepts both files in /generate endpoint - Removed hardcoded template path 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,4 @@
|
||||
#!/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
|
||||
@@ -12,126 +8,92 @@ from processors import parse_laufzettel, fill_pdf, analyze_pdf, generate_vorberi
|
||||
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")
|
||||
TEMPLATES_DIR = '/opt/stacks/spa-hosting/html/schadenprotokoll/templates'
|
||||
|
||||
|
||||
@app.route("/health", methods=["GET"])
|
||||
@app.route('/health', methods=['GET'])
|
||||
def health():
|
||||
return jsonify({"status": "ok"})
|
||||
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"])
|
||||
@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
|
||||
# Akzeptiert template (PDF) und laufzettel (DOCX)
|
||||
if 'template' not in request.files or 'laufzettel' not in request.files:
|
||||
return jsonify({'error': 'template und laufzettel erforderlich'}), 400
|
||||
|
||||
template_file = request.files['template']
|
||||
laufzettel_file = request.files['laufzettel']
|
||||
|
||||
if not template_file.filename.endswith('.pdf'):
|
||||
return jsonify({'error': 'Template muss PDF sein'}), 400
|
||||
if not laufzettel_file.filename.endswith('.docx'):
|
||||
return jsonify({'error': 'Laufzettel muss DOCX sein'}), 400
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as tmp_tpl:
|
||||
template_file.save(tmp_tpl.name)
|
||||
with tempfile.NamedTemporaryFile(suffix='.docx', delete=False) as tmp_lz:
|
||||
laufzettel_file.save(tmp_lz.name)
|
||||
try:
|
||||
data = parse_laufzettel(tmp_lz.name)
|
||||
with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as tmp_out:
|
||||
fill_pdf(tmp_tpl.name, tmp_out.name, data)
|
||||
os.unlink(tmp_tpl.name)
|
||||
os.unlink(tmp_lz.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_tpl.name)
|
||||
os.unlink(tmp_lz.name)
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@app.route("/analyze", methods=["POST"])
|
||||
@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:
|
||||
if 'file' not in request.files:
|
||||
return jsonify({'error': 'Keine Datei'}), 400
|
||||
file = request.files['file']
|
||||
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})
|
||||
return jsonify({'success': True, 'data': result})
|
||||
except Exception as e:
|
||||
os.unlink(tmp.name)
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
@app.route("/vorbericht", methods=["POST"])
|
||||
@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:
|
||||
if 'file' not in request.files:
|
||||
return jsonify({'error': 'Keine Datei'}), 400
|
||||
file = request.files['file']
|
||||
template_docx = os.path.join(TEMPLATES_DIR, 'vorbericht.docx')
|
||||
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)
|
||||
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")
|
||||
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
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(host="0.0.0.0", port=5050, debug=False)
|
||||
@app.route('/templates', methods=['GET'])
|
||||
def list_templates():
|
||||
templates = []
|
||||
for f in os.listdir(TEMPLATES_DIR):
|
||||
if not f.endswith('.bak'):
|
||||
path = os.path.join(TEMPLATES_DIR, f)
|
||||
templates.append({'name': f, 'size': os.path.getsize(path)})
|
||||
return jsonify({'templates': templates})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=5050, debug=False)
|
||||
|
||||
Reference in New Issue
Block a user