nowe funkcja statystyk i poprawki

This commit is contained in:
Mateusz Gruszczyński
2025-07-16 23:07:58 +02:00
parent 6431393baf
commit 133b91073d
5 changed files with 278 additions and 11 deletions

85
app.py
View File

@@ -125,6 +125,7 @@ class Expense(db.Model):
amount = db.Column(db.Float, nullable=False)
added_at = db.Column(db.DateTime, default=datetime.utcnow)
receipt_filename = db.Column(db.String(255), nullable=True)
list = db.relationship("ShoppingList", backref="expenses", lazy=True)
with app.app_context():
@@ -614,7 +615,7 @@ def logout():
@login_required
def create_list():
title = request.form.get("title")
is_temporary = "temporary" in request.form
is_temporary = request.form.get("temporary") == "1"
token = generate_share_token(8)
expires_at = datetime.utcnow() + timedelta(days=7) if is_temporary else None
new_list = ShoppingList(
@@ -654,6 +655,76 @@ def view_list(list_id):
)
@app.route("/user_expenses")
@login_required
def user_expenses():
from sqlalchemy.orm import joinedload
expenses = (
Expense.query
.join(ShoppingList, Expense.list_id == ShoppingList.id)
.options(joinedload(Expense.list))
.filter(ShoppingList.owner_id == current_user.id)
.order_by(Expense.added_at.desc())
.all()
)
rows = [
{
"title": e.list.title if e.list else "Nieznana",
"amount": e.amount,
"added_at": e.added_at
}
for e in expenses
]
return render_template("user_expenses.html", expense_table=rows)
@app.route("/user/expenses_data")
@login_required
def user_expenses_data():
range_type = request.args.get("range", "monthly")
start_date = request.args.get("start_date")
end_date = request.args.get("end_date")
query = (
Expense.query
.join(ShoppingList, Expense.list_id == ShoppingList.id)
.filter(ShoppingList.owner_id == current_user.id)
)
if start_date and end_date:
try:
start = datetime.strptime(start_date, "%Y-%m-%d")
end = datetime.strptime(end_date, "%Y-%m-%d") + timedelta(days=1)
query = query.filter(Expense.timestamp >= start, Expense.timestamp < end)
except ValueError:
return jsonify({"error": "Błędne daty"}), 400
expenses = query.all()
grouped = defaultdict(float)
for e in expenses:
ts = e.added_at or datetime.utcnow()
if range_type == "monthly":
key = ts.strftime("%Y-%m")
elif range_type == "quarterly":
key = f"{ts.year}-Q{((ts.month - 1) // 3) + 1}"
elif range_type == "halfyearly":
key = f"{ts.year}-H{1 if ts.month <= 6 else 2}"
elif range_type == "yearly":
key = str(ts.year)
else:
key = ts.strftime("%Y-%m-%d")
grouped[key] += e.amount
labels = sorted(grouped)
data = [round(grouped[label], 2) for label in labels]
return jsonify({"labels": labels, "expenses": data})
@app.route("/share/<token>")
@app.route("/guest-list/<int:list_id>")
def shared_list(token=None, list_id=None):
@@ -1095,7 +1166,6 @@ def edit_list(list_id):
users = User.query.all()
items = Item.query.filter_by(list_id=list_id).order_by(Item.id.desc()).all()
# Pobranie listy plików paragonów
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)]
@@ -1108,6 +1178,8 @@ def edit_list(list_id):
new_amount_str = request.form.get("amount")
is_archived = "archived" in request.form
is_public = "public" in request.form
is_temporary = "temporary" in request.form
expires_at_raw = request.form.get("expires_at")
new_owner_id = request.form.get("owner_id")
if new_title:
@@ -1115,6 +1187,15 @@ def edit_list(list_id):
l.is_archived = is_archived
l.is_public = is_public
l.is_temporary = is_temporary
if expires_at_raw:
try:
l.expires_at = datetime.strptime(expires_at_raw, "%Y-%m-%dT%H:%M")
except ValueError:
l.expires_at = None
else:
l.expires_at = None
if new_owner_id:
try: