webp support
This commit is contained in:
136
app.py
136
app.py
@@ -142,6 +142,14 @@ class Expense(db.Model):
|
||||
receipt_filename = db.Column(db.String(255), nullable=True)
|
||||
list = db.relationship("ShoppingList", backref="expenses", lazy=True)
|
||||
|
||||
class Receipt(db.Model):
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
list_id = db.Column(db.Integer, db.ForeignKey("shopping_list.id"), nullable=False)
|
||||
filename = db.Column(db.String(255), nullable=False)
|
||||
uploaded_at = db.Column(db.DateTime, default=datetime.utcnow)
|
||||
|
||||
shopping_list = db.relationship("ShoppingList", backref="receipts", lazy=True)
|
||||
|
||||
|
||||
with app.app_context():
|
||||
db.create_all()
|
||||
@@ -215,11 +223,12 @@ def allowed_file(filename):
|
||||
def get_list_details(list_id):
|
||||
shopping_list = ShoppingList.query.get_or_404(list_id)
|
||||
items = Item.query.filter_by(list_id=list_id).order_by(Item.position.asc()).all()
|
||||
receipt_pattern = f"list_{list_id}"
|
||||
all_files = os.listdir(app.config["UPLOAD_FOLDER"])
|
||||
receipt_files = [f for f in all_files if receipt_pattern in f]
|
||||
expenses = Expense.query.filter_by(list_id=list_id).all()
|
||||
total_expense = sum(e.amount for e in expenses)
|
||||
|
||||
receipts = Receipt.query.filter_by(list_id=list_id).all()
|
||||
receipt_files = [r.filename for r in receipts]
|
||||
|
||||
return shopping_list, items, receipt_files, expenses, total_expense
|
||||
|
||||
|
||||
@@ -243,16 +252,15 @@ def enrich_list_data(l):
|
||||
l.total_expense = sum(e.amount for e in expenses)
|
||||
return l
|
||||
|
||||
|
||||
def save_resized_image(file, path):
|
||||
image = Image.open(file)
|
||||
image.thumbnail((2000, 2000))
|
||||
|
||||
if image.format == "HEIF":
|
||||
path = path.rsplit(".", 1)[0] + ".jpg"
|
||||
image = image.convert("RGB")
|
||||
image.save(path, format="JPEG")
|
||||
else:
|
||||
image.save(path)
|
||||
new_path = path.rsplit(".", 1)[0] + ".webp"
|
||||
image = image.convert("RGB")
|
||||
image.save(new_path, format="WEBP", quality=85)
|
||||
|
||||
|
||||
def redirect_with_flash(
|
||||
message: str, category: str = "info", endpoint: str = "main_page"
|
||||
@@ -927,54 +935,46 @@ def upload_receipt(list_id):
|
||||
return redirect(request.referrer) """
|
||||
|
||||
|
||||
|
||||
@app.route("/upload_receipt/<int:list_id>", methods=["POST"])
|
||||
def upload_receipt(list_id):
|
||||
if "receipt" not in request.files:
|
||||
if (
|
||||
request.is_json
|
||||
or request.headers.get("X-Requested-With") == "XMLHttpRequest"
|
||||
):
|
||||
return jsonify({"success": False, "message": "Brak pliku"}), 400
|
||||
flash("Brak pliku", "danger")
|
||||
return redirect(request.referrer)
|
||||
return _receipt_error("Brak pliku")
|
||||
|
||||
file = request.files["receipt"]
|
||||
|
||||
if file.filename == "":
|
||||
if (
|
||||
request.is_json
|
||||
or request.headers.get("X-Requested-With") == "XMLHttpRequest"
|
||||
):
|
||||
return jsonify({"success": False, "message": "Nie wybrano pliku"}), 400
|
||||
flash("Nie wybrano pliku", "danger")
|
||||
return redirect(request.referrer)
|
||||
return _receipt_error("Nie wybrano pliku")
|
||||
|
||||
if file and allowed_file(file.filename):
|
||||
filename = secure_filename(file.filename)
|
||||
full_filename = f"list_{list_id}_{filename}"
|
||||
file_path = os.path.join(app.config["UPLOAD_FOLDER"], full_filename)
|
||||
base_name = f"list_{list_id}_{filename.rsplit('.', 1)[0]}"
|
||||
webp_filename = base_name + ".webp"
|
||||
file_path = os.path.join(app.config["UPLOAD_FOLDER"], webp_filename)
|
||||
|
||||
save_resized_image(file, file_path)
|
||||
|
||||
if (
|
||||
request.is_json
|
||||
or request.headers.get("X-Requested-With") == "XMLHttpRequest"
|
||||
):
|
||||
url = url_for("uploaded_file", filename=full_filename)
|
||||
new_receipt = Receipt(list_id=list_id, filename=webp_filename)
|
||||
db.session.add(new_receipt)
|
||||
db.session.commit()
|
||||
|
||||
if request.is_json or request.headers.get("X-Requested-With") == "XMLHttpRequest":
|
||||
url = url_for("uploaded_file", filename=webp_filename)
|
||||
socketio.emit("receipt_added", {"url": url}, to=str(list_id))
|
||||
|
||||
return jsonify({"success": True, "url": url})
|
||||
|
||||
flash("Wgrano paragon", "success")
|
||||
return redirect(request.referrer)
|
||||
|
||||
return _receipt_error("Niedozwolony format pliku")
|
||||
|
||||
def _receipt_error(message):
|
||||
if request.is_json or request.headers.get("X-Requested-With") == "XMLHttpRequest":
|
||||
return jsonify({"success": False, "message": "Niedozwolony format pliku"}), 400
|
||||
flash("Niedozwolony format pliku", "danger")
|
||||
return jsonify({"success": False, "message": message}), 400
|
||||
flash(message, "danger")
|
||||
return redirect(request.referrer)
|
||||
|
||||
|
||||
|
||||
@app.route("/uploads/<filename>")
|
||||
def uploaded_file(filename):
|
||||
response = send_from_directory(app.config["UPLOAD_FOLDER"], filename)
|
||||
@@ -1196,29 +1196,32 @@ def delete_user(user_id):
|
||||
return redirect(url_for("list_users"))
|
||||
|
||||
|
||||
import os
|
||||
|
||||
@app.route("/admin/receipts/<id>")
|
||||
@login_required
|
||||
@admin_required
|
||||
def admin_receipts(id):
|
||||
all_files = os.listdir(app.config["UPLOAD_FOLDER"])
|
||||
image_files = [f for f in all_files if allowed_file(f)]
|
||||
|
||||
if id == "all":
|
||||
filtered_files = image_files
|
||||
else:
|
||||
try:
|
||||
try:
|
||||
if id == "all":
|
||||
receipts = Receipt.query.order_by(Receipt.uploaded_at.desc()).all()
|
||||
else:
|
||||
list_id = int(id)
|
||||
receipt_prefix = f"list_{list_id}_"
|
||||
filtered_files = [f for f in image_files if f.startswith(receipt_prefix)]
|
||||
except ValueError:
|
||||
flash("Nieprawidłowe ID listy.", "danger")
|
||||
return redirect(url_for("admin_panel"))
|
||||
receipts = (
|
||||
Receipt.query.filter_by(list_id=list_id)
|
||||
.order_by(Receipt.uploaded_at.desc())
|
||||
.all()
|
||||
)
|
||||
except ValueError:
|
||||
flash("Nieprawidłowe ID listy.", "danger")
|
||||
return redirect(url_for("admin_panel"))
|
||||
|
||||
for r in receipts:
|
||||
path = os.path.join(app.config["UPLOAD_FOLDER"], r.filename)
|
||||
r.filesize = os.path.getsize(path) if os.path.exists(path) else 0
|
||||
|
||||
return render_template("admin/receipts.html", receipts=receipts)
|
||||
|
||||
return render_template(
|
||||
"admin/receipts.html",
|
||||
image_files=filtered_files,
|
||||
upload_folder=app.config["UPLOAD_FOLDER"],
|
||||
)
|
||||
|
||||
|
||||
@app.route("/admin/delete_receipt/<filename>")
|
||||
@@ -1226,16 +1229,31 @@ def admin_receipts(id):
|
||||
@admin_required
|
||||
def delete_receipt(filename):
|
||||
file_path = os.path.join(app.config["UPLOAD_FOLDER"], filename)
|
||||
removed_file = False
|
||||
removed_db = False
|
||||
|
||||
# Usuń plik z dysku
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
flash("Plik usunięty", "success")
|
||||
else:
|
||||
flash("Plik nie istnieje", "danger")
|
||||
removed_file = True
|
||||
|
||||
# Usuń rekord z bazy
|
||||
receipt = Receipt.query.filter_by(filename=filename).first()
|
||||
if receipt:
|
||||
db.session.delete(receipt)
|
||||
db.session.commit()
|
||||
removed_db = True
|
||||
|
||||
# Komunikat
|
||||
if removed_file or removed_db:
|
||||
flash("Paragon usunięty", "success")
|
||||
else:
|
||||
flash("Paragon nie istnieje", "danger")
|
||||
|
||||
# Powrót
|
||||
next_url = request.args.get("next")
|
||||
if next_url:
|
||||
return redirect(next_url)
|
||||
return redirect(url_for("admin_receipts"))
|
||||
return redirect(next_url or url_for("admin_receipts", id="all"))
|
||||
|
||||
|
||||
|
||||
@app.route("/admin/delete_selected_lists", methods=["POST"])
|
||||
@@ -1273,9 +1291,7 @@ def edit_list(list_id):
|
||||
db.session.query(Item).filter_by(list_id=list_id).order_by(Item.id.desc()).all()
|
||||
)
|
||||
|
||||
receipt_pattern = f"list_{list_id}_"
|
||||
all_files = os.listdir(app.config["UPLOAD_FOLDER"])
|
||||
receipts = [f for f in all_files if f.startswith(receipt_pattern)]
|
||||
receipts = Receipt.query.filter_by(list_id=list_id).order_by(Receipt.uploaded_at.desc()).all()
|
||||
|
||||
if request.method == "POST":
|
||||
action = request.form.get("action")
|
||||
|
Reference in New Issue
Block a user