jgrivolla commited on
Commit
42a477c
1 Parent(s): bf56a31

Upload 4 files

Browse files
Files changed (4) hide show
  1. Dockerfile +14 -0
  2. app.py +116 -0
  3. index.html +143 -0
  4. requirements.txt +173 -0
Dockerfile ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Use the official Python 3.10.9 image
2
+ FROM python:3.12.7
3
+
4
+ # Copy the current directory contents into the container at .
5
+ COPY . .
6
+
7
+ # Set the working directory to /
8
+ WORKDIR /
9
+
10
+ # Install requirements.txt
11
+ RUN pip install --no-cache-dir --upgrade -r /requirements.txt
12
+
13
+ # Start the FastAPI app on port 7860, the default port expected by Spaces
14
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # coding: utf-8
3
+ # # Bibliothek
4
+ #!pip install PyMySQL
5
+
6
+
7
+ import pprint
8
+ import json
9
+ import pymysql.cursors
10
+ from fastapi import FastAPI
11
+ from fastapi.responses import JSONResponse
12
+ import os
13
+
14
+ # Connect to the database
15
+ connection = pymysql.connect(host='134.0.14.99',
16
+ user='marcadm',
17
+ password=os.environ['MURMEL_DB_PASSWORD'],
18
+ database='murmel',
19
+ cursorclass=pymysql.cursors.DictCursor)
20
+
21
+ app = FastAPI()
22
+
23
+
24
+ @app.get("/groups")
25
+ def get_groups():
26
+ with connection.cursor() as cursor:
27
+ # Read a single record
28
+ sql = "SELECT Gruppe, idGruppe FROM `gruppe` WHERE aktuell is True ORDER BY idGruppe ASC;"
29
+ cursor.execute(sql, ())
30
+ result = cursor.fetchall()
31
+ #pprint.pprint(result)
32
+ return result
33
+
34
+ @app.get("/students/{idGruppe}")
35
+ def get_students(idGruppe):
36
+ with connection.cursor() as cursor:
37
+ #sql = "SELECT Gruppe, idGruppe FROM `gruppe` WHERE idGruppe=%s ORDER BY name ASC;"
38
+ sql = "select concat(`ki`.`Vorname`,' ',`ki`.`Nachnamen`) AS `Kind`, `ki`.`idKind` AS `idKind` from (((`kind` `ki` join `gruppe` `gr`) join `kind_x_gruppe_x_schuljahr` `kgs`) join `schuljahr` `sch`) where `ki`.`idKind` = `kgs`.`x_kind` and `sch`.`idschuljahr` = `kgs`.`x_schuljahr` and `gr`.`idGruppe` = `kgs`.`x_gruppe` and `sch`.`aktuell` = 1 and (`gr`.`Gruppe` = %s or `gr`.`idGruppe` = %s) order by 1"
39
+ cursor.execute(sql, (idGruppe,idGruppe))
40
+ result = cursor.fetchall()
41
+ #pprint.pprint(result)
42
+ return result
43
+
44
+ @app.get("/return/{idBuch}")
45
+ def rueckgabe(idBuch, grund='rueckgabe'):
46
+ """
47
+ Updates the database to mark a book as returned.
48
+
49
+ Parameters:
50
+ - idBuch (int): The ID of the book to be returned.
51
+ - grund (str): The reason for the return (default: 'rueckgabe').
52
+
53
+ Returns:
54
+ - int: 0 if the book was not found or already returned.
55
+
56
+ """
57
+ with connection.cursor() as cursor:
58
+ # check if the book is already returned
59
+ sql = "SELECT `idBuch`, `idKind`, `ausleihe`, `rueckgabe`, `rueckGrund` FROM `ausleihe` WHERE `idBuch` = %s AND `rueckgabe` is NULL;"
60
+ cursor.execute(sql, (idBuch,))
61
+ result = cursor.fetchall()
62
+ if len(result) == 0:
63
+ return 0
64
+ # return the book
65
+ sql = "UPDATE `ausleihe` SET `rueckgabe` = NOW(), `rueckGrund` = %s WHERE `idBuch` = %s AND `rueckgabe` is NULL;"
66
+ cursor.execute(sql, (grund, idBuch))
67
+ connection.commit()
68
+ #pprint.pprint(result)
69
+ # return if the book was returned or not and who had it before
70
+ return result
71
+
72
+ @app.get("/borrow/{idBuch}/{idKind}")
73
+ def ausleihe(idBuch, idKind):
74
+ """
75
+ Performs a book loan operation by inserting a new record into the 'ausleihe' table.
76
+
77
+ Parameters:
78
+ - idBuch (int): The ID of the book being loaned.
79
+ - idKind (int): The ID of the child borrowing the book.
80
+
81
+ Returns:
82
+ - rueckgabe_result (str): The result of the book return operation, indicating if the book was returned or not and who had it before, or if there was an error.
83
+ """
84
+ rueckgabe_result = rueckgabe(idBuch, grund="neu-ausleihe") # Buch kann nicht durch andere ausgeliehen sein
85
+ sql = "INSERT INTO `ausleihe` (`idBuch`, `idKind`, `ausleihe`) VALUES (%s, %s, NOW());"
86
+ with connection.cursor() as cursor:
87
+ cursor.execute(sql, (idBuch, idKind))
88
+ connection.commit()
89
+ #pprint.pprint(result)
90
+ # return if the book was returned or not and who had it before or if there was an error
91
+ return rueckgabe_result
92
+
93
+ @app.get("/borrowed/{idKind}")
94
+ def ausgeliehen(idKind):
95
+ """
96
+ Retrieves the books that are currently borrowed by a specific child.
97
+
98
+ Args:
99
+ idKind (int): The ID of the child.
100
+
101
+ Returns:
102
+ list: A list of tuples containing the book ID and the borrowing date for each book that is currently borrowed by the child.
103
+ """
104
+ with connection.cursor() as cursor:
105
+ sql = "SELECT `idBuch`, `ausleihe` FROM `ausleihe` WHERE `idKind` = %s AND `rueckgabe` IS NULL;"
106
+ cursor.execute(sql, (idKind,))
107
+ result = cursor.fetchall()
108
+ #pprint.pprint(result)
109
+ return result
110
+
111
+
112
+ # run the app
113
+ if __name__ == '__main__':
114
+ app.run(host='localhost', port=5000)
115
+
116
+ # %%
index.html ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Library App</title>
7
+ </head>
8
+ <body>
9
+ <h1>Library App</h1>
10
+
11
+ <!-- Borrow a Book -->
12
+ <section id="borrow-section">
13
+ <h2>Borrow a Book</h2>
14
+ <button onclick="loadGroups('borrow')">Select Group</button>
15
+ <div id="borrow-controls" style="display: none;">
16
+ <select id="group-select-borrow" onchange="loadStudents('borrow')"></select>
17
+ <select id="student-select-borrow"></select>
18
+ <input type="text" id="book-id-borrow" placeholder="Enter Book ID">
19
+ <button onclick="borrowBook()">Borrow Book</button>
20
+ </div>
21
+ <div id="borrow-result"></div>
22
+ </section>
23
+
24
+ <!-- Return Books -->
25
+ <section id="return-section">
26
+ <h2>Return Books</h2>
27
+ <input type="text" id="book-id-return" placeholder="Enter Book ID">
28
+ <button onclick="returnBook()">Return Book</button>
29
+ <div id="return-result"></div>
30
+ </section>
31
+
32
+ <!-- List Outstanding Books -->
33
+ <section id="list-section">
34
+ <h2>List Outstanding Books</h2>
35
+ <button onclick="loadGroups('list')">Select Group</button>
36
+ <div id="list-controls" style="display: none;">
37
+ <select id="group-select-list" onchange="loadStudents('list')"></select>
38
+ <select id="student-select-list"></select>
39
+ <button onclick="listOutstandingBooks()">Show Outstanding Books</button>
40
+ </div>
41
+ <div id="list-result"></div>
42
+ </section>
43
+
44
+ <!-- Inventory -->
45
+ <section id="inventory-section">
46
+ <h2>Inventory</h2>
47
+ <input type="text" id="book-id-inventory" placeholder="Enter Book ID">
48
+ <button onclick="inventoryBook()">Inventory Book</button>
49
+ <div id="inventory-result"></div>
50
+ </section>
51
+
52
+ <script>
53
+ const apiUrl = 'http://localhost:8000'; // Replace with your actual API URL
54
+
55
+ // Load groups for selection
56
+ function loadGroups(mode) {
57
+ fetch(`${apiUrl}/groups`)
58
+ .then(response => response.json())
59
+ .then(groups => {
60
+ let groupSelect = document.getElementById(`group-select-${mode}`);
61
+ groupSelect.innerHTML = '<option value="">Select Group</option>';
62
+ groups.forEach(group => {
63
+ groupSelect.innerHTML += `<option value="${group.id}">${group.name}</option>`;
64
+ });
65
+ document.getElementById(`${mode}-controls`).style.display = 'block';
66
+ });
67
+ }
68
+
69
+ // Load students based on selected group
70
+ function loadStudents(mode) {
71
+ const groupId = document.getElementById(`group-select-${mode}`).value;
72
+ if (groupId) {
73
+ fetch(`${apiUrl}/students/${groupId}`)
74
+ .then(response => response.json())
75
+ .then(students => {
76
+ let studentSelect = document.getElementById(`student-select-${mode}`);
77
+ studentSelect.innerHTML = '<option value="">Select Student</option>';
78
+ students.forEach(student => {
79
+ studentSelect.innerHTML += `<option value="${student.id}">${student.name}</option>`;
80
+ });
81
+ });
82
+ }
83
+ }
84
+
85
+ // Borrow a book
86
+ function borrowBook() {
87
+ const studentId = document.getElementById('student-select-borrow').value;
88
+ const bookId = document.getElementById('book-id-borrow').value;
89
+ if (studentId && bookId) {
90
+ fetch(`${apiUrl}/borrow/${bookId}/${studentId}`)
91
+ .then(response => response.json())
92
+ .then(result => {
93
+ document.getElementById('borrow-result').innerText = JSON.stringify(result);
94
+ });
95
+ } else {
96
+ alert('Please select a student and enter a book ID.');
97
+ }
98
+ }
99
+
100
+ // Return a book
101
+ function returnBook() {
102
+ const bookId = document.getElementById('book-id-return').value;
103
+ if (bookId) {
104
+ fetch(`${apiUrl}/return/${bookId}?grund=rueckgabe`)
105
+ .then(response => response.json())
106
+ .then(result => {
107
+ document.getElementById('return-result').innerText = JSON.stringify(result);
108
+ });
109
+ } else {
110
+ alert('Please enter a book ID.');
111
+ }
112
+ }
113
+
114
+ // List outstanding books
115
+ function listOutstandingBooks() {
116
+ const studentId = document.getElementById('student-select-list').value;
117
+ if (studentId) {
118
+ fetch(`${apiUrl}/borrowed/${studentId}`)
119
+ .then(response => response.json())
120
+ .then(result => {
121
+ document.getElementById('list-result').innerText = JSON.stringify(result);
122
+ });
123
+ } else {
124
+ alert('Please select a student.');
125
+ }
126
+ }
127
+
128
+ // Inventory a book
129
+ function inventoryBook() {
130
+ const bookId = document.getElementById('book-id-inventory').value;
131
+ if (bookId) {
132
+ fetch(`${apiUrl}/return/${bookId}?grund=inventory`)
133
+ .then(response => response.json())
134
+ .then(result => {
135
+ document.getElementById('inventory-result').innerText = JSON.stringify(result);
136
+ });
137
+ } else {
138
+ alert('Please enter a book ID.');
139
+ }
140
+ }
141
+ </script>
142
+ </body>
143
+ </html>
requirements.txt ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiohttp==3.9.5
2
+ aiosignal==1.3.1
3
+ aiosqlite==0.20.0
4
+ annotated-types==0.7.0
5
+ anyio==4.3.0
6
+ appnope==0.1.4
7
+ argon2-cffi==23.1.0
8
+ argon2-cffi-bindings==21.2.0
9
+ arrow==1.3.0
10
+ asttokens==2.4.1
11
+ async-lru==2.0.4
12
+ async-timeout==4.0.3
13
+ attrs==23.2.0
14
+ Babel==2.15.0
15
+ beautifulsoup4==4.12.3
16
+ bleach==6.1.0
17
+ certifi==2024.2.2
18
+ cffi==1.16.0
19
+ charset-normalizer==3.3.2
20
+ click==8.1.7
21
+ cloudpickle==3.0.0
22
+ comm==0.2.2
23
+ contourpy==1.2.1
24
+ cycler==0.12.1
25
+ dask==2024.6.0
26
+ dataclasses-json==0.6.7
27
+ debugpy==1.8.1
28
+ decorator==5.1.1
29
+ deepmerge==1.1.1
30
+ defusedxml==0.7.1
31
+ distributed==2024.6.0
32
+ dnspython==2.6.1
33
+ email_validator==2.2.0
34
+ exceptiongroup==1.2.1
35
+ executing==2.0.1
36
+ faiss-cpu==1.8.0
37
+ fastapi==0.112.2
38
+ fastapi-cli==0.0.5
39
+ fastjsonschema==2.19.1
40
+ fonttools==4.51.0
41
+ fqdn==1.5.1
42
+ frozenlist==1.4.1
43
+ fsspec==2024.6.0
44
+ h11==0.14.0
45
+ httpcore==1.0.5
46
+ httptools==0.6.1
47
+ httpx==0.27.0
48
+ idna==3.7
49
+ importlib_metadata==7.1.0
50
+ importlib_resources==6.4.0
51
+ ipykernel==6.29.4
52
+ ipython==8.18.1
53
+ ipywidgets==8.1.2
54
+ isoduration==20.11.0
55
+ jedi==0.19.1
56
+ Jinja2==3.1.4
57
+ json5==0.9.25
58
+ jsonpatch==1.33
59
+ jsonpath-ng==1.6.1
60
+ jsonpointer==2.4
61
+ jsonschema==4.22.0
62
+ jsonschema-specifications==2023.12.1
63
+ jupyter==1.0.0
64
+ jupyter-console==6.6.3
65
+ jupyter-events==0.10.0
66
+ jupyter-lsp==2.2.5
67
+ jupyter_ai==2.17.0
68
+ jupyter_ai_magics==2.17.0
69
+ jupyter_client==8.6.1
70
+ jupyter_core==5.7.2
71
+ jupyter_server==2.14.0
72
+ jupyter_server_terminals==0.5.3
73
+ jupyterlab==4.1.8
74
+ jupyterlab_pygments==0.3.0
75
+ jupyterlab_server==2.27.1
76
+ jupyterlab_widgets==3.0.10
77
+ kiwisolver==1.4.5
78
+ lab==8.2
79
+ langchain==0.1.20
80
+ langchain-community==0.0.38
81
+ langchain-core==0.1.52
82
+ langchain-text-splitters==0.0.2
83
+ langsmith==0.1.77
84
+ locket==1.0.0
85
+ markdown-it-py==3.0.0
86
+ MarkupSafe==2.1.5
87
+ marshmallow==3.21.3
88
+ matplotlib==3.8.4
89
+ matplotlib-inline==0.1.7
90
+ mdurl==0.1.2
91
+ mistune==3.0.2
92
+ msgpack==1.0.8
93
+ multidict==6.0.5
94
+ mypy-extensions==1.0.0
95
+ nbclient==0.10.0
96
+ nbconvert==7.16.4
97
+ nbformat==5.10.4
98
+ nest-asyncio==1.6.0
99
+ notebook==7.1.3
100
+ notebook_shim==0.2.4
101
+ numpy==1.26.4
102
+ orjson==3.10.5
103
+ overrides==7.7.0
104
+ packaging==23.2
105
+ pandocfilters==1.5.1
106
+ parso==0.8.4
107
+ partd==1.4.2
108
+ pexpect==4.9.0
109
+ pillow==10.3.0
110
+ platformdirs==4.2.1
111
+ ply==3.11
112
+ prometheus_client==0.20.0
113
+ prompt-toolkit==3.0.43
114
+ psutil==5.9.8
115
+ ptyprocess==0.7.0
116
+ pure-eval==0.2.2
117
+ pycparser==2.22
118
+ pydantic==2.7.4
119
+ pydantic_core==2.18.4
120
+ Pygments==2.18.0
121
+ PyMySQL==1.1.0
122
+ pyparsing==3.1.2
123
+ python-dateutil==2.9.0.post0
124
+ python-dotenv==1.0.1
125
+ python-json-logger==2.0.7
126
+ python-multipart==0.0.9
127
+ PyYAML==6.0.1
128
+ pyzmq==26.0.3
129
+ qtconsole==5.5.2
130
+ QtPy==2.4.1
131
+ referencing==0.35.1
132
+ requests==2.31.0
133
+ rfc3339-validator==0.1.4
134
+ rfc3986-validator==0.1.1
135
+ rich==13.8.0
136
+ rpds-py==0.18.1
137
+ Send2Trash==1.8.3
138
+ shellingham==1.5.4
139
+ simplejson==3.19.2
140
+ six==1.16.0
141
+ sniffio==1.3.1
142
+ sortedcontainers==2.4.0
143
+ soupsieve==2.5
144
+ SQLAlchemy==2.0.30
145
+ stack-data==0.6.3
146
+ starlette==0.38.4
147
+ tblib==3.0.0
148
+ tenacity==8.3.0
149
+ terminado==0.18.1
150
+ tinycss2==1.3.0
151
+ tomli==2.0.1
152
+ toolz==0.12.1
153
+ tornado==6.4
154
+ traitlets==5.14.3
155
+ txt2tags==3.9
156
+ typer==0.12.5
157
+ types-python-dateutil==2.9.0.20240316
158
+ typing-inspect==0.9.0
159
+ typing_extensions==4.11.0
160
+ uri-template==1.3.0
161
+ urllib3==2.2.1
162
+ uvicorn==0.30.6
163
+ uvloop==0.20.0
164
+ watchfiles==0.24.0
165
+ wcwidth==0.2.13
166
+ webcolors==1.13
167
+ webencodings==0.5.1
168
+ websocket-client==1.8.0
169
+ websockets==13.0.1
170
+ widgetsnbextension==4.0.10
171
+ yarl==1.9.4
172
+ zict==3.0.0
173
+ zipp==3.18.1