diff --git a/app.py b/app.py index 98df9ec..2d99525 100644 --- a/app.py +++ b/app.py @@ -65,6 +65,15 @@ class Zbiorka(db.Model): passive_deletes=True, ) + wydatki = db.relationship( + "Wydatek", + backref="zbiorka", + lazy=True, + order_by="Wydatek.data.desc()", + cascade="all, delete-orphan", + passive_deletes=True, + ) + class Wplata(db.Model): id = db.Column(db.Integer, primary_key=True) @@ -80,6 +89,18 @@ class Wplata(db.Model): zbiorka = db.relationship("Zbiorka", back_populates="wplaty") +class Wydatek(db.Model): + id = db.Column(db.Integer, primary_key=True) + zbiorka_id = db.Column( + db.Integer, + db.ForeignKey("zbiorka.id", ondelete="CASCADE"), + nullable=False, + ) + kwota = db.Column(db.Float, nullable=False) + data = db.Column(db.DateTime, default=datetime.utcnow) + opis = db.Column(db.Text, nullable=True) + + class GlobalSettings(db.Model): id = db.Column(db.Integer, primary_key=True) numer_konta = db.Column(db.String(50), nullable=False) @@ -193,10 +214,20 @@ def page_not_found(e): @app.route("/zbiorka/") def zbiorka(zbiorka_id): zb = Zbiorka.query.get_or_404(zbiorka_id) - # Jeżeli zbiórka jest ukryta i użytkownik nie jest administratorem, zwróć 404 if zb.ukryta and (not current_user.is_authenticated or not current_user.is_admin): abort(404) - return render_template("zbiorka.html", zbiorka=zb) + + # scalona oś czasu: wpłaty + wydatki + aktywnosci = [ + {"typ": "wpłata", "kwota": w.kwota, "opis": w.opis, "data": w.data} + for w in zb.wplaty + ] + [ + {"typ": "wydatek", "kwota": x.kwota, "opis": x.opis, "data": x.data} + for x in zb.wydatki + ] + aktywnosci.sort(key=lambda a: a["data"], reverse=True) + + return render_template("zbiorka.html", zbiorka=zb, aktywnosci=aktywnosci) # TRASY LOGOWANIA I REJESTRACJI @@ -551,6 +582,31 @@ def admin_ustawienia(): ) +@app.route("/admin/zbiorka//wydatek/dodaj", methods=["GET", "POST"]) +@login_required +def dodaj_wydatek(zbiorka_id): + if not current_user.is_admin: + flash("Brak uprawnień", "danger") + return redirect(url_for("index")) + zb = Zbiorka.query.get_or_404(zbiorka_id) + if request.method == "POST": + try: + kwota = float(request.form["kwota"]) + if kwota <= 0: + raise ValueError + except (KeyError, ValueError): + flash("Nieprawidłowa kwota", "danger") + return redirect(url_for("dodaj_wydatek", zbiorka_id=zbiorka_id)) + opis = request.form.get("opis", "") + nowy_wydatek = Wydatek(zbiorka_id=zb.id, kwota=kwota, opis=opis) + zb.stan -= kwota + db.session.add(nowy_wydatek) + db.session.commit() + flash("Wydatek został dodany", "success") + return redirect(url_for("admin_dashboard")) + return render_template("admin/dodaj_wydatek.html", zbiorka=zb) + + @app.route( "/admin/zbiorka/oznacz/niezrealizowana/", methods=["POST"], diff --git a/static/js/dodaj_wydatek.js b/static/js/dodaj_wydatek.js new file mode 100644 index 0000000..13ac70d --- /dev/null +++ b/static/js/dodaj_wydatek.js @@ -0,0 +1,5 @@ +document.addEventListener('input', (e) => { + if (e.target && e.target.id === 'opis') { + document.getElementById('opisCount').textContent = e.target.value.length; + } +}); \ No newline at end of file diff --git a/templates/admin/dashboard.html b/templates/admin/dashboard.html index f0015e0..bf4c473 100644 --- a/templates/admin/dashboard.html +++ b/templates/admin/dashboard.html @@ -90,6 +90,11 @@ href="{{ url_for('dodaj_wplate', zbiorka_id=z.id) }}">Dodaj wpłatę +
  • + Dodaj + wydatek +
  • Edytuj stan @@ -198,6 +203,11 @@ href="{{ url_for('dodaj_wplate', zbiorka_id=z.id) }}">Dodaj wpłatę
  • +
  • + Dodaj + wydatek +
  • Edytuj stan diff --git a/templates/admin/dodaj_wydatek.html b/templates/admin/dodaj_wydatek.html new file mode 100644 index 0000000..e9dea75 --- /dev/null +++ b/templates/admin/dodaj_wydatek.html @@ -0,0 +1,63 @@ +{% extends 'base.html' %} +{% block title %}Dodaj wydatek{% endblock %} + +{% block content %} +
    + + + +
    +
    +

    Dodaj wydatek: {{ zbiorka.nazwa }}

    +
    + {% if zbiorka.cel %} + Cel: {{ zbiorka.cel|round(2) }} + PLN + {% endif %} + Stan: {{ zbiorka.stan|round(2) + }} PLN +
    +
    + +
    +
    +
    + +
    + PLN + +
    +
    Podaj kwotę w złotówkach (min. 0,01).
    +
    + +
    + + +
    + Krótka notatka do wydatku (widoczna w + systemie). + 0/300 +
    +
    + +
    + + Anuluj +
    +
    +
    +
    +
    +{% endblock %} + +{% block extra_scripts %} +{{ super() }} + +{% endblock %} \ No newline at end of file diff --git a/templates/zbiorka.html b/templates/zbiorka.html index 30af220..38df64e 100644 --- a/templates/zbiorka.html +++ b/templates/zbiorka.html @@ -97,8 +97,11 @@ {% if current_user.is_authenticated and current_user.is_admin %} + {% endif %} @@ -106,35 +109,40 @@ - +
    -
    Historia wpłat
    - {% if zbiorka.wplaty|length > 0 %} - Łącznie pozycji: {{ zbiorka.wplaty|length }} +
    Aktywność
    + {% if aktywnosci and aktywnosci|length > 0 %} + Łącznie pozycji: {{ aktywnosci|length }} {% endif %}
    - {% if zbiorka.wplaty and zbiorka.wplaty|length > 0 %} + {% if aktywnosci and aktywnosci|length > 0 %}
      - {% for w in zbiorka.wplaty %} + {% for a in aktywnosci %}
    • - {{ w.data.strftime('%Y-%m-%d %H:%M:%S') }} - {% if w.opis %} - — {{ w.opis }} + {{ a.data.strftime('%Y-%m-%d %H:%M:%S') }} + + {{ a.typ|capitalize }} + + {% if a.opis %} + — {{ a.opis }} {% endif %}
      + {% if not zbiorka.ukryj_kwote %} - {{ w.kwota|round(2) }} PLN + {% if a.typ == 'wpłata' %}+{% else %}-{% endif %} {{ a.kwota|round(2) }} PLN + {% endif %}
    • {% endfor %}
    {% else %}
    -
    Brak wpłat
    -

    Gdy pojawią się pierwsze wpłaty, zobaczysz je tutaj.

    +
    Brak aktywności
    +

    Gdy pojawią się pierwsze wpłaty lub wydatki, zobaczysz je tutaj.

    {% endif %}