From 31e5a6bc296c98ba82f0535cdf3e4b30bce05a93 Mon Sep 17 00:00:00 2001 From: h3r7 Date: Sun, 1 Mar 2026 07:31:05 +0100 Subject: [PATCH] =?UTF-8?q?v1.4=20-=20Cat=C3=A9gories=20auto=20+=20Budget?= =?UTF-8?q?=20+=20R=C3=A9current=20+=20PDF=20+=20Tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/app.cpython-312.pyc | Bin 0 -> 22125 bytes app.py | 90 +++++++- depenses.db | Bin 28672 -> 32768 bytes templates/index.html | 378 +++++++++++++++++++++++++------- 4 files changed, 384 insertions(+), 84 deletions(-) create mode 100644 __pycache__/app.cpython-312.pyc diff --git a/__pycache__/app.cpython-312.pyc b/__pycache__/app.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..885d387dbe6c64ff544edfcd6340ada3c333fbcd GIT binary patch literal 22125 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') +def del_recurring(id): + conn = get_db() + c = conn.cursor() + c.execute('DELETE FROM recurring WHERE id=?', (id,)) + conn.commit() + conn.close() + return redirect('/?page=config') + +# Get monthly stats +@app.route('/api/stats/monthly') +def get_monthly_stats(): + conn = get_db() + c = conn.cursor() + c.execute('''SELECT strftime('%Y-%m', date) as month, SUM(montant) as total + FROM depenses GROUP BY month ORDER BY month''') + rows = c.fetchall() + conn.close() + return jsonify([{'month': r[0], 'total': r[1]} for r in rows]) + +# Get stats by category +@app.route('/api/stats/category') +def get_stats_category(): + conn = get_db() + c = conn.cursor() + c.execute('''SELECT category, SUM(montant) as total FROM depenses GROUP BY category''') + rows = c.fetchall() + conn.close() + return jsonify([{'category': r[0] or 'Autre', 'total': r[1]} for r in rows]) + if __name__ == '__main__': - app.run(host='0.0.0.0', port=8769, debug=False) + app.run(host='0.0.0.0', port=8769, debug=False) \ No newline at end of file diff --git a/depenses.db b/depenses.db index 646c52c9c3dfc4e398d3c748dee73756fdda1c29..0166dde1995b8fdb6594ee7d0c9eae91564e7528 100644 GIT binary patch delta 1406 zcmZ{jTWs4@7{`z8HWxegX_7^eag#V2w<-=KFJp9yrHNQ!#;a(aG<8 z-#Op^`~KOyLu_u6TS8a>00huy|M7JsSrEVzFTc%lN#JL$gHVgR0=Kv}dx8Cpxqi() z%8b|k^8s}Q7p)PM2MpIkuEdo=s%0yie>l2eTMeJecGMjhaf)8hw8h@Kbq4MTk9L|v&Uv-Hr#5aEv}62$8-IW)XKAc_CV7;-MKAM|k_g6BK- zywm2g1av;)7W$Bgt&aUpP^0{Do+s?0^B6ZXEs5tg&abN0(weSWFSObss;xG}GS7lo zV3C0D(fx2F_$m8+=<}eTJ{!0~|HZ~aa_|hZ!@S9=T%7)zyUSe)EMBuSfiov#K@dyJ zL|PW6mDzgYYP}7@c(=g|Q z?t%Wpvfv~Wl}H!Q`7s_PF#aYnwU6s8#!sSX-uXjN!p9p;Q`cttFdcH~C&|e!ohLCJ zcIjejx=R-Wn3mo9^u+N~Q>gEzYCavom?zURn3iXYUcH5EVWiS{Ro7Io`JfiOC+3Gs zg*!v5sA2W+2|qpgZGEU6>k}*su(Bfx~djh3^Yh z51tHRn0I9>gJq`M4fZRL@7P)9tPgLGqnwlzP1X+8jfQ5f>xOlL+0WyhcL&R1uYl(U zFvZ;xoPI$OyIQ#=!0r1TfNDPu!nMbpW^&xC<5(C&0l}2>?L$woy^By@xnqyLRy~9R zGXLX)u3MX`S$ME-*ek9Fa;4#1x1eeiA2x~(0|%zU4R%en>`e&S$}rRw^n+KlNB`Sc zxnfB!s1!bJ&TZ`9$$3xE5`kgGg;!HEQFjC^QbWPp0R9ethPOWpi{HT!mZDNb?;lHs zNGd^`SJzbynIy&#lt8Q-s-~}*eQq|l4Y+N%4Ox`^C0CjBQR!C>)OYnsifO9avMP1Q zDS5V)yeUb&=1Oi=_9%1)%3lyc=VrMWx`Qgb1>i0C3%rl+xB<%?l_n0Z@F5MfH%*%2 zi51;gYgj?NL>_CkbjZSA0SR{j{0Z*j7dqr7bas~_hf!A4%j|vA@E!`@1E?Q+@E-gV z1^)n@Jw1{{A(38~yTJNMxC7u_xZ}n>9wvPtO7Mho^w=p+B8(C~5GVOyO>e6PdD^4@ E0D~QE>Hq)$ delta 629 zcmX}pO=uHA6bJB`og|yQ?Ci@%L)>n+t@a?H)(@gcsWo5-k;c%JD3VhQxQftxkd#6R zLV{krwd_GWixoTw(vxDqs}zr((nCOV@(Yxr;KhAu?Z6y<`~LGE*y(hX&VX-NhMzH} zdi(zpo2QbdpPgQNB=s#8kZp!cf2mLC>#{9>Y#UQTx^4M1R1#|3Gm{@;jiJx;YIih zy;ofq;F1w!vEvq>PP!*1&O<&zJfnJS*cr$nafY~IrJ<-3=ZT-J9OUI;_^z3OtVTRX zRhP$8kPRPl%1%KBh_f^eSPQTeA||Qo^|3762oh7odt-UXsl+)7N6j=`4-gk<`fmIh zWcDnj&m|+i5tpmeVrATv)u(bZYf#%eSAG4Bw;lUWcRT&iUL(>J1m}PU<3j@!AFq z2e^087CH;UG-D$cN?t diff --git a/templates/index.html b/templates/index.html index 062702f..92899c2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -5,8 +5,10 @@ 💸 Dépenses Trello + +

💸 Dépenses Trello

- - + + +