Uvix's picture
```
aff706e verified
Raw
History Blame Contribute Delete
4.89 kB
```python
from flask import Flask, request, jsonify, send_file
import os
import uuid
import pandas as pd
import fitz # PyMuPDF
from werkzeug.utils import secure_filename
import zipfile
from io import BytesIO
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['TEMPLATE_FOLDER'] = os.path.join(app.config['UPLOAD_FOLDER'], 'templates')
app.config['OUTPUT_FOLDER'] = os.path.join(app.config['UPLOAD_FOLDER'], 'outputs')
# Ensure upload directories exist
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
os.makedirs(app.config['TEMPLATE_FOLDER'], exist_ok=True)
os.makedirs(app.config['OUTPUT_FOLDER'], exist_ok=True)
# Sample field mapping (would normally come from config)
FIELD_MAPPING = {
"invoice_number": {"page": 0, "x": 150, "y": 200, "font_size": 10},
"therapist_name": {"page": 0, "x": 150, "y": 220, "font_size": 10},
"parent_id": {"page": 0, "x": 300, "y": 240, "font_size": 10}
}
@app.route('/')
def index():
return send_file('index.html')
@app.route('/upload_template', methods=['POST'])
def upload_template():
if 'template' not in request.files:
return jsonify({"error": "No file uploaded"}), 400
file = request.files['template']
if file.filename == '':
return jsonify({"error": "No file selected"}), 400
if file and file.filename.lower().endswith('.pdf'):
filename = secure_filename("template.pdf")
filepath = os.path.join(app.config['TEMPLATE_FOLDER'], filename)
file.save(filepath)
return jsonify({"message": "Template uploaded successfully", "filename": filename})
return jsonify({"error": "Invalid file type"}), 400
@app.route('/generate', methods=['POST'])
def generate_pdf():
data = request.get_json()
if not data or 'rows' not in data or 'headers' not in data or 'data' not in data:
return jsonify({"error": "Invalid request data"}), 400
template_path = os.path.join(app.config['TEMPLATE_FOLDER'], 'template.pdf')
if not os.path.exists(template_path):
return jsonify({"error": "Template PDF not found"}), 404
selected_rows = data['rows']
headers = data['headers']
csv_data = data['data']
if len(selected_rows) == 1:
# Single PDF generation
row_data = csv_data[selected_rows[0]]
output_path = generate_single_pdf(template_path, headers, row_data)
return send_file(output_path, as_attachment=True)
else:
# Multiple PDFs - return as ZIP
zip_buffer = generate_multiple_pdfs(template_path, headers, csv_data, selected_rows)
return send_file(
zip_buffer,
mimetype='application/zip',
as_attachment=True,
download_name='generated_pdfs.zip'
)
def generate_single_pdf(template_path, headers, row_data):
doc = fitz.open(template_path)
page = doc[0]
for i, header in enumerate(headers):
if header in FIELD_MAPPING:
mapping = FIELD_MAPPING[header]
text = str(row_data[i]) if i < len(row_data) else ""
# Create a text annotation (similar to form field)
annot = page.add_text_annot(
point=(mapping['x'], mapping['y']),
text=text
)
annot.set_fontsize(mapping['font_size'])
output_filename = f"output_{uuid.uuid4().hex[:8]}.pdf"
output_path = os.path.join(app.config['OUTPUT_FOLDER'], output_filename)
doc.save(output_path)
doc.close()
return output_path
def generate_multiple_pdfs(template_path, headers, csv_data, selected_rows):
zip_buffer = BytesIO()
with zipfile.ZipFile(zip_buffer, 'w', zipfile.ZIP_DEFLATED) as zip_file:
for row_idx in selected_rows:
if row_idx < len(csv_data):
row_data = csv_data[row_idx]
doc = fitz.open(template_path)
page = doc[0]
for i, header in enumerate(headers):
if header in FIELD_MAPPING:
mapping = FIELD_MAPPING[header]
text = str(row_data[i]) if i < len(row_data) else ""
annot = page.add_text_annot(
point=(mapping['x'], mapping['y']),
text=text
)
annot.set_fontsize(mapping['font_size'])
pdf_filename = f"output_row_{row_idx + 1}.pdf"
pdf_path = os.path.join(app.config['OUTPUT_FOLDER'], pdf_filename)
doc.save(pdf_path)
doc.close()
zip_file.write(pdf_path, pdf_filename)
os.remove(pdf_path)
zip_buffer.seek(0)
return zip_buffer
if __name__ == '__main__':
app.run(debug=True, port=5000)
```