crop dla userów i przeniesienie listy na inny miesiac
This commit is contained in:
145
app.py
145
app.py
@@ -64,13 +64,17 @@ app = Flask(__name__)
|
||||
app.config.from_object(Config)
|
||||
|
||||
# Konfiguracja nagłówków bezpieczeństwa z .env
|
||||
csp_policy = {
|
||||
"default-src": "'self'",
|
||||
"script-src": "'self' 'unsafe-inline'",
|
||||
"style-src": "'self' 'unsafe-inline'",
|
||||
"img-src": "'self' data:",
|
||||
"connect-src": "'self'",
|
||||
} if app.config.get("ENABLE_CSP", True) else None
|
||||
csp_policy = (
|
||||
{
|
||||
"default-src": "'self'",
|
||||
"script-src": "'self' 'unsafe-inline'",
|
||||
"style-src": "'self' 'unsafe-inline'",
|
||||
"img-src": "'self' data:",
|
||||
"connect-src": "'self'",
|
||||
}
|
||||
if app.config.get("ENABLE_CSP", True)
|
||||
else None
|
||||
)
|
||||
|
||||
permissions_policy = {"browsing-topics": "()"} if app.config.get("ENABLE_PP") else None
|
||||
|
||||
@@ -424,9 +428,38 @@ def generate_new_receipt_filename(list_id):
|
||||
return f"list_{list_id}_{timestamp}_{random_part}.webp"
|
||||
|
||||
|
||||
def handle_crop_receipt(receipt_id, file):
|
||||
if not receipt_id or not file:
|
||||
return {"success": False, "error": "Brak danych"}
|
||||
|
||||
receipt = Receipt.query.get_or_404(receipt_id)
|
||||
old_path = os.path.join(app.config["UPLOAD_FOLDER"], receipt.filename)
|
||||
|
||||
try:
|
||||
new_filename = generate_new_receipt_filename(receipt.list_id)
|
||||
new_path = os.path.join(app.config["UPLOAD_FOLDER"], new_filename)
|
||||
|
||||
save_resized_image(file, new_path)
|
||||
|
||||
if os.path.exists(old_path):
|
||||
os.remove(old_path)
|
||||
|
||||
receipt.filename = os.path.basename(new_path)
|
||||
db.session.commit()
|
||||
recalculate_filesizes(receipt.id)
|
||||
return {"success": True}
|
||||
except Exception as e:
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
|
||||
def get_expenses_aggregated_by_list_created_at(
|
||||
user_only=False, admin=False, show_all=False,
|
||||
range_type="monthly", start_date=None, end_date=None, user_id=None
|
||||
user_only=False,
|
||||
admin=False,
|
||||
show_all=False,
|
||||
range_type="monthly",
|
||||
start_date=None,
|
||||
end_date=None,
|
||||
user_id=None,
|
||||
):
|
||||
"""
|
||||
Wspólna logika: sumujemy najnowszy wydatek z każdej listy,
|
||||
@@ -455,8 +488,7 @@ def get_expenses_aggregated_by_list_created_at(
|
||||
except Exception:
|
||||
return {"error": "Błędne daty", "labels": [], "expenses": []}
|
||||
lists_query = lists_query.filter(
|
||||
ShoppingList.created_at >= dt_start,
|
||||
ShoppingList.created_at < dt_end
|
||||
ShoppingList.created_at >= dt_start, ShoppingList.created_at < dt_end
|
||||
)
|
||||
lists = lists_query.all()
|
||||
|
||||
@@ -464,8 +496,7 @@ def get_expenses_aggregated_by_list_created_at(
|
||||
data = []
|
||||
for sl in lists:
|
||||
latest_exp = (
|
||||
Expense.query
|
||||
.filter_by(list_id=sl.id)
|
||||
Expense.query.filter_by(list_id=sl.id)
|
||||
.order_by(Expense.added_at.desc())
|
||||
.first()
|
||||
)
|
||||
@@ -1002,15 +1033,31 @@ def edit_my_list(list_id):
|
||||
abort(403, description="Nie jesteś właścicielem tej listy.")
|
||||
|
||||
if request.method == "POST":
|
||||
# Obsługa zmiany miesiąca utworzenia listy
|
||||
move_to_month = request.form.get("move_to_month")
|
||||
if move_to_month:
|
||||
try:
|
||||
year, month = map(int, move_to_month.split("-"))
|
||||
new_created_at = datetime(year, month, 1, tzinfo=timezone.utc)
|
||||
l.created_at = new_created_at
|
||||
db.session.commit()
|
||||
flash(
|
||||
f"Zmieniono datę utworzenia listy na {new_created_at.strftime('%Y-%m-%d')}",
|
||||
"success",
|
||||
)
|
||||
return redirect(url_for("edit_my_list", list_id=list_id))
|
||||
except ValueError:
|
||||
flash("Nieprawidłowy format miesiąca", "danger")
|
||||
return redirect(url_for("edit_my_list", list_id=list_id))
|
||||
|
||||
# Pozostała aktualizacja pól
|
||||
new_title = request.form.get("title", "").strip()
|
||||
is_public = "is_public" in request.form
|
||||
is_temporary = "is_temporary" in request.form
|
||||
is_archived = "is_archived" in request.form
|
||||
|
||||
expires_date = request.form.get("expires_date")
|
||||
expires_time = request.form.get("expires_time")
|
||||
|
||||
# Walidacja tytułu
|
||||
if not new_title:
|
||||
flash("Podaj poprawny tytuł", "danger")
|
||||
return redirect(url_for("edit_my_list", list_id=list_id))
|
||||
@@ -1020,7 +1067,6 @@ def edit_my_list(list_id):
|
||||
l.is_temporary = is_temporary
|
||||
l.is_archived = is_archived
|
||||
|
||||
# Obsługa daty wygaśnięcia
|
||||
if expires_date and expires_time:
|
||||
try:
|
||||
combined = f"{expires_date} {expires_time}"
|
||||
@@ -1160,7 +1206,7 @@ def view_list(list_id):
|
||||
expenses=expenses,
|
||||
total_expense=total_expense,
|
||||
is_share=False,
|
||||
is_owner=is_owner
|
||||
is_owner=is_owner,
|
||||
)
|
||||
|
||||
|
||||
@@ -1254,7 +1300,7 @@ def user_expenses_data():
|
||||
range_type=range_type,
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
user_id=current_user.id
|
||||
user_id=current_user.id,
|
||||
)
|
||||
if "error" in result:
|
||||
return jsonify({"error": result["error"]}), 400
|
||||
@@ -1545,6 +1591,22 @@ def analyze_receipts_for_list(list_id):
|
||||
return jsonify({"results": results, "total": round(total, 2)})
|
||||
|
||||
|
||||
@app.route("/user_crop_receipt", methods=["POST"])
|
||||
@login_required
|
||||
def crop_receipt_user():
|
||||
receipt_id = request.form.get("receipt_id")
|
||||
file = request.files.get("cropped_image")
|
||||
|
||||
receipt = Receipt.query.get_or_404(receipt_id)
|
||||
list_obj = ShoppingList.query.get_or_404(receipt.list_id)
|
||||
|
||||
if list_obj.owner_id != current_user.id and not current_user.is_admin:
|
||||
return jsonify(success=False, error="Brak dostępu"), 403
|
||||
|
||||
result = handle_crop_receipt(receipt_id, file)
|
||||
return jsonify(result)
|
||||
|
||||
|
||||
@app.route("/admin")
|
||||
@login_required
|
||||
@admin_required
|
||||
@@ -1775,8 +1837,11 @@ def admin_receipts(id):
|
||||
all_db_filenames = set(r.filename for r in receipts)
|
||||
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_")
|
||||
f
|
||||
for f in files_on_disk
|
||||
if f.endswith(".webp")
|
||||
and f not in all_db_filenames
|
||||
and f.startswith("list_")
|
||||
]
|
||||
else:
|
||||
list_id = int(id)
|
||||
@@ -1794,7 +1859,7 @@ def admin_receipts(id):
|
||||
"admin/receipts.html",
|
||||
receipts=receipts,
|
||||
orphan_files=stale_files,
|
||||
orphan_files_count=len(stale_files)
|
||||
orphan_files_count=len(stale_files),
|
||||
)
|
||||
|
||||
|
||||
@@ -1995,6 +2060,18 @@ def edit_list(list_id):
|
||||
flash("Niepoprawna kwota", "danger")
|
||||
return redirect(url_for("edit_list", list_id=list_id))
|
||||
|
||||
created_month = request.form.get("created_month")
|
||||
if created_month:
|
||||
try:
|
||||
year, month = map(int, created_month.split("-"))
|
||||
l.created_at = datetime(year, month, 1, tzinfo=timezone.utc)
|
||||
except ValueError:
|
||||
flash(
|
||||
"Nieprawidłowy format miesiąca (przeniesienie daty utworzenia)",
|
||||
"danger",
|
||||
)
|
||||
return redirect(url_for("edit_list", list_id=list_id))
|
||||
|
||||
db.session.add(l)
|
||||
db.session.commit()
|
||||
flash("Zapisano zmiany listy", "success")
|
||||
@@ -2232,31 +2309,11 @@ def demote_user(user_id):
|
||||
@app.route("/admin/crop_receipt", methods=["POST"])
|
||||
@login_required
|
||||
@admin_required
|
||||
def crop_receipt():
|
||||
def crop_receipt_admin():
|
||||
receipt_id = request.form.get("receipt_id")
|
||||
file = request.files.get("cropped_image")
|
||||
|
||||
if not receipt_id or not file:
|
||||
return jsonify(success=False, error="Brak danych")
|
||||
|
||||
receipt = Receipt.query.get_or_404(receipt_id)
|
||||
old_path = os.path.join(app.config["UPLOAD_FOLDER"], receipt.filename)
|
||||
|
||||
try:
|
||||
new_filename = generate_new_receipt_filename(receipt.list_id)
|
||||
new_path = os.path.join(app.config["UPLOAD_FOLDER"], new_filename)
|
||||
|
||||
save_resized_image(file, new_path)
|
||||
|
||||
if os.path.exists(old_path):
|
||||
os.remove(old_path)
|
||||
|
||||
receipt.filename = os.path.basename(new_path)
|
||||
db.session.commit()
|
||||
recalculate_filesizes(receipt.id)
|
||||
return jsonify(success=True)
|
||||
except Exception as e:
|
||||
return jsonify(success=False, error=str(e))
|
||||
result = handle_crop_receipt(receipt_id, file)
|
||||
return jsonify(result)
|
||||
|
||||
|
||||
@app.route("/admin/recalculate_filesizes")
|
||||
|
Reference in New Issue
Block a user