From 4533fd64029208ca5f00d868b0e70de2d27e01c7 Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Fri, 15 May 2026 01:18:38 +0200 Subject: [PATCH 1/4] Erster View und erstes Template angelegt, URL /speisekarte registriert. --- db.sqlite3 | Bin 212992 -> 212992 bytes .../__pycache__/__init__.cpython-314.pyc | Bin 156 -> 156 bytes mensa_app/__pycache__/admin.cpython-314.pyc | Bin 958 -> 958 bytes mensa_app/__pycache__/apps.cpython-314.pyc | Bin 461 -> 461 bytes mensa_app/__pycache__/models.cpython-314.pyc | Bin 8602 -> 8602 bytes mensa_app/__pycache__/urls.cpython-314.pyc | Bin 0 -> 383 bytes mensa_app/__pycache__/views.cpython-314.pyc | Bin 0 -> 655 bytes .../__pycache__/0001_initial.cpython-314.pyc | Bin 4939 -> 4939 bytes ...r_gericht_options_and_more.cpython-314.pyc | Bin 2026 -> 2026 bytes ...cht_time_creation_and_more.cpython-314.pyc | Bin 2143 -> 2143 bytes ...cht_time_creation_and_more.cpython-314.pyc | Bin 1152 -> 1152 bytes .../__pycache__/__init__.cpython-314.pyc | Bin 167 -> 167 bytes .../templates/mensa_app/gericht_list.html | 55 ++++++++++++++++++ mensa_app/urls.py | 6 ++ mensa_app/views.py | 8 +++ .../__pycache__/__init__.cpython-314.pyc | Bin 157 -> 157 bytes .../__pycache__/settings.cpython-314.pyc | Bin 2465 -> 2465 bytes mensa_core/__pycache__/urls.cpython-314.pyc | Bin 1022 -> 1102 bytes mensa_core/__pycache__/wsgi.cpython-314.pyc | Bin 646 -> 646 bytes mensa_core/urls.py | 3 +- 20 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 mensa_app/__pycache__/urls.cpython-314.pyc create mode 100644 mensa_app/__pycache__/views.cpython-314.pyc create mode 100644 mensa_app/templates/mensa_app/gericht_list.html create mode 100644 mensa_app/urls.py diff --git a/db.sqlite3 b/db.sqlite3 index f2574ceecfb016836d55f9e9d2167ba6c454b560..f70068fcf61b755b3ac26781bc726491ac851047 100644 GIT binary patch delta 1430 zcmb7^Z%7+w7{KqnOEhQ9J+Wi8TbA`|3)NLCauJ7`Bvkqg@A;jrpP5I_UOcgY7Qrn93--56}C; z`#e9M_qpHQ{Jdp;-m+*zv85Nz8)KOB%`esxZyh}f?N}|fVumf)pvu$+ybjl?zrY48 z^*yx$>N-t-M;YtQ1do=N#?Uhezj~yFAy%-{OAAfS&(;$yC@p7HDJtc1QAM6k#>evn zW+91VCaI7gk1EsILJq^Qrlo}wSFg7mN96hsEnl9kbI}~{XL&#GaWWp(>vOGto;^!f zA?hAR-CJ9@MU`G{K*r!}5s}NdxLKtzmnh6A%4C{Rrx-pHSJL@pOcF9P8K>M?9GD2I z-O7a6-#X?nJDS<%6V0?EOSzV1TDV7sEY-NJBdu~i&Ty3{ZmRwGG16&1zcWOrxQ&(4O% z+B*Cl(SfOvVs?(5iU<2WLrN&Gwhl*Q+5Sk3KR>|cB`+UVRWH+?lZH8l^Eeo{gY*4+ zZf>uOtI>vw;64WT*Xwe(;lyzwNIq?3AFmpIIZVP$48Db1a1%D+F8l#c;Ahw>KmQI| zgBOhiLME~jO?o7&EBmU--nhK=5wdB3I~e>4zr(Na2!7Nc58xZPvus^ON6OqPdJmp6 z5F{e?VA4ai9;)3hLY{7l-1zjy+p@YJQaVUsd8gp>dIbJVwMMaRQ+CStwLl(d zf$=&ymxpE8(JHNYv{KB53JE!tq0`Ac-Iq;EdF^w`YR%~PEB%iPy8MjW>C^C>AR0A# z<2HTIke<>Y?|1v00_PK0*GmQsajg9H19ZC1h~OaxWp)F-ORX*X&?!41{&Tm3Mp`r@ zalPUvc=$;z{uP|6!3oT^Gb1Y^u*N-2=?3GliD~+6mTRr}U9g)88`{aotwbZaC;u9a z8>}@1Jl5@d48LjKZvyCE5xSl@P7ow{?Hq1+MN3jK&F>FDU0aZ$#1Uq!nKW6dO{Cqv zPp5N-v^KOy|1EKTm$17w;AX5|t3f2P+bgyZ`0m;6$|Ey&h9tEdjr$+3)4=i6Uh?~^ G_~PFy7>(!v delta 448 zcmZo@;B9E&ogmE^HBrWyHHtxR>dB2MbLHjv{xk6K&En#J$$x=wJKqKVZvI33vHa5f zhI~)?X7R7tte|k8kA>fzL1v<(#AIoGU8yn#Q3ebk#?5TZF@0hhqp&Xn|11U(3v%=#R;sd>eT@reZm@#(2WnaLR?lMm@DGqP-crhm>} z&``n1z{=Rd%G5;9*woO-z+m&ye0v2p1_1^JzB`)*8{YFz3}ByDz{JT2=Pf!Qu;~EH z12GohN2l}%U2DeKsVBE+*af00Rm+Kj&fr{QT@c-fe&i{%3E&mi4+%C0& zaTidLHiDeVyp@0Jb{+wy>p%h7Nf%g_vnVhLY-VZr1M~;? Wc5VlzpYfYn9U1D%nSf6V+2Vgvvy`veLA delta 20 acmX@he3qG8n~#@^0SJC;Fm2>M#0UT|Nd%w( diff --git a/mensa_app/__pycache__/models.cpython-314.pyc b/mensa_app/__pycache__/models.cpython-314.pyc index e0fd0fabf71bd62cb08fc39d4b165117065438a4..010479e236c544f28cdde449bb308881a3fa6055 100644 GIT binary patch delta 20 acmbQ`Jjh5I1S&%p zc}CM{V1difK^5?D2e-28;6GO2a3ws`vySmnRFSYedk>t1xNv1CNYs_?SjKBqA!ZlrgQq^YYLs_C7~ zozl_uy0g2@NY+>GV#*o&VT@aGTCjOeV9Bmoz{hOF zkslk}8Fxk&T7-FEjqQQ~pGpngbH*inb!24;;0oSgCdjND8{HMYBWt$%jO|HOEzK11BRVz53PxfPQZz~gI-`^H?XOPqxV{xTjrai z4008Uuq^#~(?O)v6^1cpsoo9K6hs?>aSy?~v<01n;D=WN7izo)^zmmlQ-XZv}&#x}bR{sCpKF}4_u>34NDz23QYM;~> zw%X|}U#t!uFE3X22H)+zH10a-a^UH^vqhNCi=m1OiBW}0nvc^5t-E2KLvF4oZ4+|q zJypGQ)6mS_u=Y$s_i1ytXR=SG`9*a^>X*eiU$c`xF5{Fn~#@^0SHV(*fw%I2m=5wsRP^q delta 20 acmX@Dc3O>Fn~#@^0SJC;Fm2>^5C#A<_XKhP diff --git a/mensa_app/migrations/__pycache__/0002_alter_bestellung_options_alter_gericht_options_and_more.cpython-314.pyc b/mensa_app/migrations/__pycache__/0002_alter_bestellung_options_alter_gericht_options_and_more.cpython-314.pyc index 973cd0960747557d4c72ec763e22ad6f0842f0de..cae7689d07f0434934ab4e04f1650c34dea42439 100644 GIT binary patch delta 20 acmaFG|B9bmn~#@^0SHV(*fw(CX9oZ>IRt+I delta 20 acmaFG|B9bmn~#@^0SJC;Fm2?%&kg`KhXoY? diff --git a/mensa_app/migrations/__pycache__/0003_schulwoche_alter_gericht_time_creation_and_more.cpython-314.pyc b/mensa_app/migrations/__pycache__/0003_schulwoche_alter_gericht_time_creation_and_more.cpython-314.pyc index a82d32da7a08008ec44840bd8947570965bdb07e..680e53de3abdfe9f000d51faa7b06044644ebd2d 100644 GIT binary patch delta 20 acmcaFa9@C1n~#@^0SHV(*fw&9Z~y==rUT&s delta 20 acmcaFa9@C1n~#@^0SKCHnKp8VZ~y=?Dg+b& diff --git a/mensa_app/migrations/__pycache__/0004_alter_gericht_time_creation_and_more.cpython-314.pyc b/mensa_app/migrations/__pycache__/0004_alter_gericht_time_creation_and_more.cpython-314.pyc index f97feed9d200ef24f107bb99f9f29217f75e83e2..c33415e3f4e0dc5dd3513491ac52f5488d2cd6db 100644 GIT binary patch delta 20 ZcmZqRY~bY9=HumJ00PqxwvF7SEC3+R12O;r delta 20 ZcmZqRY~bY9=HumJ0D=X!OdGjNSpXv)1A+hm diff --git a/mensa_app/migrations/__pycache__/__init__.cpython-314.pyc b/mensa_app/migrations/__pycache__/__init__.cpython-314.pyc index 2acbc8d967049c2e78cdf5181b7184e3380544db..cc7d1ead2f6eb275f088311aac3761e3970b40c2 100644 GIT binary patch delta 19 ZcmZ3^xSWw&n~#@^0SHV(*d}t%0RSP-19JcX delta 19 ZcmZ3^xSWw&n~#@^0SJC;Fiqs10{|t51PK5D diff --git a/mensa_app/templates/mensa_app/gericht_list.html b/mensa_app/templates/mensa_app/gericht_list.html new file mode 100644 index 0000000..4b4f375 --- /dev/null +++ b/mensa_app/templates/mensa_app/gericht_list.html @@ -0,0 +1,55 @@ + + + + + + Mensa-Speisekarte + + + + + +
+
+
+
+
+

Unsere Speisekarte

+
+
+ + + + + + + + + + {% for gericht in alle_gerichte %} + + + + + + {% empty %} + + + + {% endfor %} + +
GerichtKategorieStatus
{{ gericht.name }}{{ gericht.kategorie.name }} + {% if gericht.ist_dauerangebot %} + Dauerangebot + {% else %} + Tagesangebot + {% endif %} +
Keine Gerichte im System gefunden.
+
+
+
+
+
+ + + diff --git a/mensa_app/urls.py b/mensa_app/urls.py new file mode 100644 index 0000000..a191ae4 --- /dev/null +++ b/mensa_app/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from .views import GerichtListView + +urlpatterns = [ + path('speisekarte/', GerichtListView.as_view(), name='gericht_list'), +] diff --git a/mensa_app/views.py b/mensa_app/views.py index 91ea44a..b8aafaa 100644 --- a/mensa_app/views.py +++ b/mensa_app/views.py @@ -1,3 +1,11 @@ from django.shortcuts import render # Create your views here. +from django.views.generic import ListView +from .models import Gericht + +class GerichtListView(ListView): + model = Gericht + template_name = 'mensa_app/gericht_liste.html' # Der Pfad zum Template + context_object_name = 'alle_gerichte' # Der Name, den wir im Template nutzen + diff --git a/mensa_core/__pycache__/__init__.cpython-314.pyc b/mensa_core/__pycache__/__init__.cpython-314.pyc index c6998ecd32fa2a0f71238a59baa963077a7a4f9e..f6c0a1cb41d1d133db23f80ba154c0adfb0c6734 100644 GIT binary patch delta 19 ZcmbQsIG2%In~#@^0SHV(*d}sM0stUg162S3 delta 19 ZcmbQsIG2%In~#@^0SJC;Fiqs11OOxz1M2_) diff --git a/mensa_core/__pycache__/settings.cpython-314.pyc b/mensa_core/__pycache__/settings.cpython-314.pyc index ddbc6402d2cf83f461ca64755d1269d00834eb0b..4d35f6dbf9abb95bcff230d829bd9ee3f19d151c 100644 GIT binary patch delta 20 acmZ1|yik~1n~#@^0SHV(*fw%c;{*UFV*{=L delta 20 acmZ1|yik~1n~#@^0SJC;Fm2?X#t8r`u>?c_ diff --git a/mensa_core/__pycache__/urls.cpython-314.pyc b/mensa_core/__pycache__/urls.cpython-314.pyc index 262e0fa27a4c921217a32395638215c28e954503..05686aa83cee225a2c6a0f94ad12342534be8d68 100644 GIT binary patch delta 289 zcmeyzevU(3n~#@^0SMy4*s^??85kaeI55BtWqhuis4k!4!CJy9&k)O^$PmOF%M`!^ zQ-z=d_z-Lu%Y+HS0_$UmWd-VHHDQE^!Q}LqN;rbplo>SHH+D^6(q+2EQjl1Zaf>}O zFFB_)CAEqzF(o%MPyZG}6<=;@UU6c4VnKmkX;DtGpC;#I9cBZjB9_UK%xV7oKx08h z7uy1f56p~=j31f!8Ckw6Ffc0KXHfmf#=y$iAu+*py46Ih>Gl)tFS97$WZ~!#>I}ai Xs(P7M?J|q{2Ucc&rY7zpUZ4p8#kn?^ delta 189 zcmX@d@sC|yn~#@^0SJC;FlGH?Vqka-;=lk4l<_%kqPo0-JVPvtB0~^!EK>kj3rrP+ z4&a%XCB>!3Si&B}qRgPlx^dM6CLzXKECq=r8C7hFDY=<>`hJ=mlhc_ECeL9`w&w+E zV+7)2T_Ev+nURt4BNIO(%U1;kM#Z}fG9TF(SUEc+CYVmQnrJoMexm(l7Ud7jO#Dnu J+(q0#9RNFnB;Wu5 diff --git a/mensa_core/__pycache__/wsgi.cpython-314.pyc b/mensa_core/__pycache__/wsgi.cpython-314.pyc index b95635bf17fe848caed1b4c78e87ecd995d9a456..ebd799de991fe5f8216188c5ca42b4d57dee87b7 100644 GIT binary patch delta 20 ZcmZo;ZDZxu=HumJ00PqxwvF7?OaLJ)13CZz delta 20 ZcmZo;ZDZxu=HumJ0D|8dOdGkYnE)kv1JD2f diff --git a/mensa_core/urls.py b/mensa_core/urls.py index 29c5021..da1dfc9 100644 --- a/mensa_core/urls.py +++ b/mensa_core/urls.py @@ -15,8 +15,9 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import path +from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), + path('', include('mensa_app.urls')), # Schaltet die App-URLs frei ] From 5d6235679a02a8986be698466a844b980dbca061 Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Fri, 15 May 2026 11:18:40 +0200 Subject: [PATCH 2/4] =?UTF-8?q?Speiseplan=20f=C3=BCr=20einen=20Tag=20mit?= =?UTF-8?q?=20Pager=20erstellt.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db.sqlite3 | Bin 212992 -> 212992 bytes .../templates/mensa_app/gericht_list.html | 2 +- mensa_app/urls.py | 2 + mensa_app/views.py | 39 ++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/db.sqlite3 b/db.sqlite3 index f70068fcf61b755b3ac26781bc726491ac851047..e42d6e9edc9e29fcef7c1d82a707fe8efa10ea17 100644 GIT binary patch delta 1436 zcma)6U1(cn7(PD@%iqbnKk0C;3$;RjYh`X@LL}aUs3eJv-PUyUFFi)~&wDUsG#q)i9 z@B2RQ_dVb9oyA3BaglicIGVWhl1Gz3EKzigUp{$^LX4&>I@pE{Q^m9a@4y$P$8a3p zD8FcK1RSm)muEKGUp)eN2bvOOg^O^ROhlc{3D^sbc-NlAm@q3w<5|t+x4R}$qWnwO z{HX=9_O;}!-Z?8f5tPRQoZ=bEOoaHpXrRSTDd{dL5u>JkQm8AIpOGbhSHc^dN_L-> z!l|)dfl34h{BmK4e2pe)rjxXHQg$=Rx+uHLX0@;mig7X=pAzL7oK~{pbXMYIzB5)# z$(&NYn{F{{G2$9xx=mbLyRbqmTznbR_}?0F=h=*{$jZXBSg>U&vJ@{&HZwko6OisqXW6w!5|Y0`DV^}>m@Dc%I6q#h$2Fi51U~BfgkB#LERVlE1Dh z&F)dv$&w^fzP;RrYB8uFa0e>oLz$1^l@{EO{+Di8`Oa$VA58?55!i%p;U-*%&){eH z0ltJX{0+PCJ8V~)KR_?RF%6EQdZLP2V+{?p75&o9Rg_gJZXoao{(?W@H~3Yh_z8Z5 zTks8hty0~nG+#xR;b;S{Ly0OFt6->tzH;k2N*-(?4EGUOfe;)veP?>lL=(HjRbrCB zjjP5%!~IJ02Ktp@VT#ZpAnH0$otv(ULD4RAXfBmevI3Vhr^KvTC}d|j^O=EO->|38 z-0IxA_(|L3d^5-M0^jU1&!0d4y8c=96N5TjByF)dNUPHxF{(YHwI258c#V6BmvWnE zTle;5$BYA}>E}9f%!8{~NCBfWk{~yO-)Td^#+MEnYS0*>nmBXqf))Cl(b=49TIN5}| z(R!1An+U6HJw}^JlLqcpukr!xz&&`VR(=oq>Q!l~&`^1B3OjO8CEh{cA?&E(yKq#C zX%JL3h6dB3wV4LTK7A8wIIWVI5Y<*6fdXDItzCFzT5xC#h)1g>P_6F7iRUEVtMCE! z*FiEa^`@VW?F|N`P4~2LpSXgio>L!b+<WPgh^W-Jm8F=_+ar3|AzreSh?*e}}{~^Br{L=h} zo23-Q`K5&TnYB4`Q}c=w;}Z)C;(@HvR0anASqwT88#Tm5#hLXP5whv2MVZMNCCrn% z^rIO$H$T&_wy!rb00EV36Ax#9PggHX-;l}>v(VrOpHed?3l;OULVYKb%Ip;9Tod!C zOiN3Xkc?v20)y1Be6KL`H0=zhaAVU@mwdmxbXy|>BQsqCQ(Z$71tViCLt`srGd%+{ zLvst0#FX63JTT!Bi^sP8+fBRA3@-Dr3;KFxHnEHWZWKomvN;KD
-
+

Unsere Speisekarte

diff --git a/mensa_app/urls.py b/mensa_app/urls.py index a191ae4..60835bc 100644 --- a/mensa_app/urls.py +++ b/mensa_app/urls.py @@ -1,6 +1,8 @@ from django.urls import path from .views import GerichtListView +from .views import SpeiseplanView # Achte auf den neuen Klassennamen! urlpatterns = [ path('speisekarte/', GerichtListView.as_view(), name='gericht_list'), + path('speiseplan/', SpeiseplanView.as_view(), name='speiseplan'), ] diff --git a/mensa_app/views.py b/mensa_app/views.py index b8aafaa..5cb7a01 100644 --- a/mensa_app/views.py +++ b/mensa_app/views.py @@ -9,3 +9,42 @@ class GerichtListView(ListView): template_name = 'mensa_app/gericht_liste.html' # Der Pfad zum Template context_object_name = 'alle_gerichte' # Der Name, den wir im Template nutzen +from django.views.generic import TemplateView +from django.utils import timezone +from datetime import datetime +from .models import Menue, Gericht, SpeiseplanTag + +class SpeiseplanView(TemplateView): + template_name = 'mensa_app/speiseplan.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + # 1. Datum aus der URL holen (z.B. ?datum=2023-10-27) + # Wenn kein Datum angegeben ist, nehmen wir heute. + date_str = self.request.GET.get('datum') + if date_str: + try: + target_date = datetime.strptime(date_str, '%Y-%m-%d').date() + except ValueError: + target_date = timezone.glob.now().date() + else: + target_date = timezone.now().date() + + # 2. Menüs für diesen spezifischen Tag laden + # Wir suchen alle Menüs, deren Tag das target_date hat + context['target_date'] = target_date + context['menues_day'] = Menue.objects.filter(tag__datum=target_date) + + # 3. Dauerangebote laden (unabhängig vom Tag) + context['dauerangebote'] = Gericht.objects.filter(ist_dauerangebot=True) + + # 4. Pager-Logik: Vorherigen und nächsten Tag finden + # Wir suchen in der Tabelle SpeiseplanTag nach dem Tag davor/danach + prev_tag = SpeiseplanTag.objects.filter(datum__lt=target_date).order_by('-datum').first() + next_tag = SpeiseplanTag.objects.filter(datum__gt=target_date).order_by('datum').first() + + context['prev_date'] = prev_tag.datum.strftime('%Y-%m-%d') if prev_tag else None + context['next_date'] = next_tag.datum.strftime('%Y-%m-%d') if next_tag else None + + return context From 0a6ecda7a229fe89f7b2d82b8dc9ef6734e6d259 Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Wed, 10 Jun 2026 10:43:53 +0200 Subject: [PATCH 3/4] =?UTF-8?q?Neue=20Bestell=C3=BCbersicht=20erstellt.=20?= =?UTF-8?q?/bestellungen/summary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db.sqlite3 | Bin 212992 -> 225280 bytes .../templates/mensa_app/bestell_summary.html | 81 +++++++++++++++ mensa_app/templates/mensa_app/speiseplan.html | 92 ++++++++++++++++++ mensa_app/urls.py | 4 +- mensa_app/views.py | 51 ++++++++++ 5 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 mensa_app/templates/mensa_app/bestell_summary.html create mode 100644 mensa_app/templates/mensa_app/speiseplan.html diff --git a/db.sqlite3 b/db.sqlite3 index e42d6e9edc9e29fcef7c1d82a707fe8efa10ea17..ce6b7425fff2156feb3c10b7efdf69e2e5aff451 100644 GIT binary patch delta 4281 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 delta 1602 zcmZuxYfKbZ6uys{ea}6MvaCXb_@WxzU3OtrNDJ0Bl2|EP(-=d-%C0M@VHbHM_E#D0 zkJ?(xGT==RrHu)#HI{C+W;NAHYqU*mm6ATwfCLIwrA1AUAKK76AXbyk$-S9-zVo{0 zd^1ghN>h{4oRP8%A(SuHQn9dD!PtsCyeqz~9h5?GbUdSoJ z2sFH28&_42w0V zCq|1hG4&g}G~=4xaW&tV=qjl&QNJ~=88-?=u{9Ad-z?cMtVOU^*`rHb^?|lF8cp@P zy#B1*f-u*$n~^-Aqhv{+bABAA3B&iPJ~7kVH!D zNk}BSOS7n-eXSXLMWWXj9}f^Y@!ddyx*T^Qs9_%{KifXB{%ZAFj#{cspPSw?UNg2B z9vDgu2I(W(Ov`Xr(!CAu#dLpmAs-Fle7u~$&_?F*D$c-`Y$z@;I5)fa zp=vyjXLJw?-=L9s(z1Py)%>3rS%IIOar-_-6kgUsE?V}LuQEDwa`2lqJgSk!ID5w6 zq(-*!Q=DY;ni$FD!B!HI^9;_dc~68MYbBY|A~naySsU^37LCm3TiZxw^5G6_DsU^1 zK+q3Ah(TO{voI{0bO{ph0488uu=4EFB08l4Pjur=!m$UzL($cH@E80k90%Yx_z|wb zw<16fv_37u@euHy3;3l>g^eKLG9V1kK_|Qod!QU%1P`PGW+QR+B1?{3#S5@ovED*( z0$znVtdG6Ne9DCKsZy>`Tes~M>n-!p(-K$DSd+JY$BR-$t|ah_Q}_itfgzn{L-5&* z2DEBK*LB}aTrd|h=8sEA1)IFCvX#qyH5yJKk$AJv1Sqr%`k6?hN{B>pUz(y zZs@na3uABt?hC`8V5vmSSk^a5->6J6CWKP6S=i4$O9cJKA+}L&X_k#JhTuMo3DqEE znTU)q#wMAV@bsHZiT)8GJ3=rBgO45Wm?SYAQQV_IJ>q;G&d;9R3OR*r_#iP{HWbRO z(rsHzNh%ScNV4_RV7+agoGk_+aw@J?V7f2!WnR`n3US^HulkRWlxe>5KRU<(o3R3! zW_(IF@TntYgOtBNxRD1B6F1ID#txGNrfPOE=RsV8JsckvlD{<` zK%(m6P5fLNInFb8;C_BEj9VnIqV+L#9aW1;dGQhQg(T{nh^cp5nk6O!LxR>HLOqlK zi>nVAXXE6aO`jiu38a%;bnPZM^-;-0qS#FTA0*Qt(ZT6?Ov2=BzgzTq+}Anqc(6(N p4w>=@8ujTk>J#j^47@K&d`Zbp$H49*3SDUS<@#2-a>YN(`!8Y- + + + + Bestell-Zusammenfassung + + + + +
+ +
+
+

Bestell-Check für den {{ target_date|date:"d.m.Y" }}

+ +
+
+ + +
+
+
+
+
Gesamtanzahl Bestellungen
+

{{ total_bestellungen }}

+
+
+
+
+
+
+
Erwarteter Umsatz
+

{{ total_umsatz|floatformat:2 }} €

+
+
+
+
+ + +
+
Details pro Gericht
+
+ + + + + + + + + + + {% for stat in summary_stats %} + + + + + + + {% empty %} + + + + {% endfor %} + +
GerichtKategorieMengeUmsatz
{{ stat.menue__gericht__name }}{{ stat.menue__gericht__kategorie__name }}{{ stat.anzahl }}{{ stat.umsatz|floatformat:2 }} €
Keine Bestellungen für diesen Tag vorhanden.
+
+
+ + +
+ + + diff --git a/mensa_app/templates/mensa_app/speiseplan.html b/mensa_app/templates/mensa_app/speiseplan.html new file mode 100644 index 0000000..e5918a1 --- /dev/null +++ b/mensa_app/templates/mensa_app/speiseplan.html @@ -0,0 +1,92 @@ + + + + + + Mensa Speiseplan + + + + +
+
+
+ + +
+
+

Speiseplan für den
{{ target_date|date:"d.m.Y" }}

+ +
+ + {% if prev_date %} + « Vorheriger Tag + {% else %} + + {% endif %} + + + Heute + + + {% if next_date %} + Nächster Tag » + {% else %} + + {% endif %} +
+
+
+ + +
+
Tagesmenüs
+
+ + + + + + + + + + {% for menue in menues_day %} + + + + + + {% empty %} + + + + {% endfor %} + +
GerichtKategoriePreis
{{ menue.gericht.name }}{{ menue.gericht.kategorie.name }}{{ menue.preis|floatformat:2 }} €
Keine Tagesmenüs für diesen Tag geplant.
+
+
+ + +
+
Immer verfügbar (Dauerangebote)
+
+
    + {% for gericht in dauerangebote %} +
  • + {{ gericht.name }} + Verfügbar +
  • + {% empty %} +
  • Momentan keine Dauerangebote.
  • + {% endfor %} +
+
+
+ +
+
+
+ + + diff --git a/mensa_app/urls.py b/mensa_app/urls.py index 60835bc..c59a541 100644 --- a/mensa_app/urls.py +++ b/mensa_app/urls.py @@ -1,8 +1,10 @@ from django.urls import path from .views import GerichtListView from .views import SpeiseplanView # Achte auf den neuen Klassennamen! +from .views import BestellSummaryView urlpatterns = [ - path('speisekarte/', GerichtListView.as_view(), name='gericht_list'), + path('speisekarte/', GerichtListView.as_view(), name='speisekarte'), path('speiseplan/', SpeiseplanView.as_view(), name='speiseplan'), + path('bestellungen/summary/', BestellSummaryView.as_view(), name='bestell_summary'), ] diff --git a/mensa_app/views.py b/mensa_app/views.py index 5cb7a01..662af6f 100644 --- a/mensa_app/views.py +++ b/mensa_app/views.py @@ -48,3 +48,54 @@ class SpeiseplanView(TemplateView): context['next_date'] = next_tag.datum.strftime('%Y-%m-%d') if next_tag else None return context + + +from django.views.generic import TemplateView +from django.utils import timezone +from django.db.models import Count, Sum +from datetime import datetime +from .models import Bestellung, SpeiseplanTag, Gericht, Menue + +class BestellSummaryView(TemplateView): + template_name = 'mensa_app/bestell_summary.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + # 1. Datum aus der URL holen (wie beim Speiseplan) + date_str = self.request.GET. get('datum') + if date_str: + try: + target_date = datetime.strptime(date_str, '%Y-%m-%d').date() + except ValueError: + target_date = timezone.now().date() + else: + target_date = timezone.now().date() + + context['target_date'] = target_date + + # 2. Aggregation: Bestellungen nach Gericht gruppieren + # Wir suchen alle Bestellungen, deren Menü am target_date stattfindet + summary_stats = ( + Bestellung.objects.filter(menue__tag__datum=target_date) + .values('menue__gericht__name', 'menue__gericht__kategorie__name') # Gruppierung nach Name & Kategorie + .annotate( + anzahl=Count('id'), # Wie viele wurden bestellt? + umsatz=Sum('menue__preis') # Was macht das für einen Umsatz? + ) + .order_by('menue__gericht__name') + ) + context['summary_stats'] = summary_stats + + # 3. Pager-Logik (identisch mit dem Speiseplan-View) + prev_tag = SpeiseplanTag.objects.filter(datum__lt=target_date).order_by('-datum').first() + next_tag = SpeiseplanTag.objects.filter(datum__gt=target_date).order_by('datum').first() + + context['prev_date'] = prev_tag.datum.strftime('%Y-%m-%d') if prev_tag else None + context['next_date'] = next_tag.datum.strftime('%Y-%m-%d') if next_tag else None + + # 4. Gesamtzahlen für die Übersicht + context['total_bestellungen'] = Bestellung.objects.filter(menue__tag__datum=target_date).count() + context['total_umsatz'] = Bestellung.objects.filter(menue__tag__datum=target_date).aggregate(Sum('menue__preis'))['menue__preis__sum'] or 0 + + return context From b85e19b94ae021021c0b2f67e6e0da2c7ee2fddd Mon Sep 17 00:00:00 2001 From: Martin Putzlocher Date: Thu, 11 Jun 2026 09:35:31 +0200 Subject: [PATCH 4/4] UML-Sequenzdiagramm zum Bestellugnsprozess --- .../customer_order_process_diagram_v1.pdf | Bin 0 -> 9983 bytes mensa_app/customer_order_process_v1.puml | 65 ++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 mensa_app/customer_order_process_diagram_v1.pdf create mode 100644 mensa_app/customer_order_process_v1.puml diff --git a/mensa_app/customer_order_process_diagram_v1.pdf b/mensa_app/customer_order_process_diagram_v1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..fab8f5c62a9dbd8fbc337b71889d88a8b5480043 GIT binary patch literal 9983 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 Fe*sxb literal 0 HcmV?d00001 diff --git a/mensa_app/customer_order_process_v1.puml b/mensa_app/customer_order_process_v1.puml new file mode 100644 index 0000000..10d483d --- /dev/null +++ b/mensa_app/customer_order_process_v1.puml @@ -0,0 +1,65 @@ +@startuml + +' Teilnehmer – Standard‑Icons +actor Student as "Student" +participant Browser as "Browser" +participant WebsiteServer as "Website Server" +database OrderDB as "Order DB" +participant OrderService as "Order Service" +participant InventoryService as "Inventory Service" +participant KitchenDisplaySystem as "Kitchen Display" +participant NotificationService as "Notification Service" + +' ---------- Login ---------- +Student -> Browser : Öffnet die Webseite +Browser -> WebsiteServer : GET /login +WebsiteServer --> Browser : Liefert Login‑Seite +Student -> Browser : Gibt Benutzerdaten ein und schickt Formular +Browser -> WebsiteServer : POST /login\n{username, password} +WebsiteServer --> OrderService : Authentifiziere User +OrderService --> WebsiteServer : OK (Session‑Token) +WebsiteServer --> Browser : Setzt Session‑Cookie & leitet zur Menüseite + +' ---------- Menü auswählen ---------- +Student -> Browser : Wählt Speisen aus dem Menü +Browser -> WebsiteServer : GET /menu\n{session} +WebsiteServer --> OrderDB : Liefert aktuelle Menüpunkte +OrderDB --> WebsiteServer : Menüdaten +WebsiteServer --> Browser : Zeigt Menü + +' ---------- Artikel zum Warenkorb hinzufügen ---------- +loop Für jeden gewählten Artikel + Student -> Browser : Klickt „In den Warenkorb“ + Browser -> OrderService : POST /cart/add\n{session, articleID} + OrderService -> OrderDB : Update Cart (Add Item) + OrderDB --> OrderService : OK + OrderService --> Browser : Rückmeldung "Artikel hinzugefügt" +end + +' ---------- Bestellung prüfen ---------- +Student -> Browser : Öffnet Warenkorb und prüft Bestellübersicht +Browser -> OrderService : GET /cart\n{session} +OrderService -> OrderDB : Liefert aktuelle Cart‑Daten +OrderDB --> OrderService : Cart‑Details +OrderService --> Browser : Zeigt Cart‑Übersicht + +' ---------- Checkout (ohne Bezahlung) ---------- +Student -> Browser : Klicke „Zur Kasse“ +Browser -> WebsiteServer : GET /checkout\n{session} +WebsiteServer --> NotificationService : Sende “Bestellung anstehend” (Optional) +NotificationService --> Browser : Bestätigungsnachricht +Student -> Browser : Gibt Zahlungsinformationen für Bezahlung vor Ort ein und schickt Formular +Browser -> OrderService : POST /checkout/confirm\n{session, paymentMethod="VorOrt"} +OrderService --> OrderDB : Speichere Order & set Status “Pending Payment” +OrderDB --> OrderService : OK +OrderService --> KitchenDisplaySystem : Sende Order‑Details (Zubereitung) +KitchenDisplaySystem --> Browser : Zeigt „Bestellung in Bearbeitung“ +OrderService -> InventoryService : Update Bestand +InventoryService --> OrderService : OK +OrderService --> NotificationService : Sende “Bestellung bestätigt” (Email/SMS) + +' ---------- Fertigstellung ---------- +Student -> Browser : Empfängt Benachrichtigung “Ihr Essen ist fertig” +Browser -> KitchenDisplaySystem : Optional „Abholung bestätigen“ + +@enduml \ No newline at end of file