porzucobe paragony
This commit is contained in:
45
app.py
45
app.py
@@ -1526,10 +1526,8 @@ def admin_panel():
|
||||
purchased_count = l.purchased_count
|
||||
percent = (purchased_count / total_count * 100) if total_count > 0 else 0
|
||||
comments_count = len([i for i in items if i.note and i.note.strip() != ""])
|
||||
receipt_pattern = f"list_{l.id}"
|
||||
receipt_files = [f for f in all_files if receipt_pattern in f]
|
||||
receipts_count = Receipt.query.filter_by(list_id=l.id).count()
|
||||
|
||||
# obliczenie czy wygasła
|
||||
if l.is_temporary and l.expires_at:
|
||||
expires_at = l.expires_at
|
||||
if expires_at.tzinfo is None:
|
||||
@@ -1545,7 +1543,7 @@ def admin_panel():
|
||||
"purchased_count": purchased_count,
|
||||
"percent": round(percent),
|
||||
"comments_count": comments_count,
|
||||
"receipts_count": len(receipt_files),
|
||||
"receipts_count": receipts_count,
|
||||
"total_expense": l.total_expense,
|
||||
"expired": is_expired,
|
||||
}
|
||||
@@ -1743,7 +1741,44 @@ def admin_receipts(id):
|
||||
flash("Nieprawidłowe ID listy.", "danger")
|
||||
return redirect(url_for("admin_panel"))
|
||||
|
||||
return render_template("admin/receipts.html", receipts=receipts)
|
||||
# Przeszukaj folder upload pod kątem „sierot”
|
||||
upload_folder = app.config["UPLOAD_FOLDER"]
|
||||
db_filenames = set(r.filename for r in receipts)
|
||||
all_db_filenames = set(r.filename for r in Receipt.query.all()) # Wszystko z bazy
|
||||
files_on_disk = set(os.listdir(upload_folder))
|
||||
stale_files = [
|
||||
f for f in files_on_disk
|
||||
if f.endswith(".webp") and f not in all_db_filenames and f.startswith("list_")
|
||||
]
|
||||
# Przekaż do template: receipts (z bazy) i orphan_files (sieroty)
|
||||
return render_template(
|
||||
"admin/receipts.html",
|
||||
receipts=receipts,
|
||||
orphan_files=stale_files,
|
||||
orphan_files_count=len(stale_files)
|
||||
)
|
||||
|
||||
|
||||
@app.route("/admin/delete_orphan_receipt_file/<filename>")
|
||||
@login_required
|
||||
@admin_required
|
||||
def delete_orphan_receipt_file(filename):
|
||||
upload_folder = app.config["UPLOAD_FOLDER"]
|
||||
safe_filename = os.path.basename(filename)
|
||||
file_path = os.path.join(upload_folder, safe_filename)
|
||||
# Dowolnego pliku nie kasujemy jeśli jest w bazie (Receipt.filename)
|
||||
if Receipt.query.filter_by(filename=safe_filename).first():
|
||||
flash("Nie możesz usunąć pliku powiązanego z bazą!", "danger")
|
||||
return redirect(url_for("admin_receipts", id="all"))
|
||||
if not os.path.exists(file_path):
|
||||
flash("Plik już nie istnieje.", "warning")
|
||||
else:
|
||||
try:
|
||||
os.remove(file_path)
|
||||
flash(f"Usunięto plik: {safe_filename}", "success")
|
||||
except Exception as e:
|
||||
flash(f"Błąd przy usuwaniu pliku: {e}", "danger")
|
||||
return redirect(url_for("admin_receipts", id="all"))
|
||||
|
||||
|
||||
@app.route("/admin/rotate_receipt/<int:receipt_id>")
|
||||
|
@@ -64,6 +64,31 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if orphan_files %}
|
||||
<hr class="my-4">
|
||||
<h4 class="mt-3 mb-2 text-warning">🧐 Znalezione nieprzypisane pliki ({{ orphan_files_count }})</h4>
|
||||
<div class="row g-3">
|
||||
{% for f in orphan_files %}
|
||||
<div class="col-6 col-md-4 col-lg-3">
|
||||
<div class="card bg-dark border-warning text-warning h-100">
|
||||
<img src="{{ url_for('uploaded_file', filename=f) }}" class="card-img-top" style="object-fit: cover; height: 200px;">
|
||||
<div class="card-body text-center">
|
||||
<p class="small mb-1 fw-bold">{{ f }}</p>
|
||||
<div class="alert alert-warning small py-1 mb-2">Brak powiązania z listą!</div>
|
||||
<a href="{{ url_for('delete_orphan_receipt_file', filename=f) }}"
|
||||
class="btn btn-sm btn-outline-danger w-100 mb-2"
|
||||
onclick="return confirm('Na pewno usunąć WYŁĄCZNIE plik {{ f }} z dysku?');">
|
||||
🗑 Usuń plik z serwera
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
<div class="modal fade" id="cropModal" tabindex="-1" aria-labelledby="cropModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-centered">
|
||||
<div class="modal-content bg-dark text-white">
|
||||
|
Reference in New Issue
Block a user