From eda1500371f9c5329af78555951fade3f7111b11 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Thu, 30 Nov 2023 19:03:29 +0530 Subject: [PATCH 01/69] Add Dockerfile and docker-compose.yml --- .gitignore | 6 +----- Dockerfile | 23 +++++++++++++++++++++++ docker-compose.yml | 15 +++++++++++++++ run.sh | 4 ++++ 4 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 run.sh diff --git a/.gitignore b/.gitignore index 7c1e2fa..8b98db4 100644 --- a/.gitignore +++ b/.gitignore @@ -165,8 +165,4 @@ cython_debug/ #.idea/ -#dockerfiles -*.yml -*.yaml -Dockerfile -*.sh + diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f20af8b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,23 @@ +# For more information, please refer to https://aka.ms/vscode-docker-python +FROM python:3.8.16 + +# Keeps Python from generating .pyc files in the container +ENV PYTHONDONTWRITEBYTECODE=1 + +# Turns off buffering for easier container logging +ENV PYTHONUNBUFFERED=1 + +# Install pip requirements +COPY requirements.txt . +RUN python -m pip install -r requirements.txt + +WORKDIR /app +COPY . /app + +# Creates a non-root user with an explicit UID and adds permission to access the /app folder +# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers +# RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app +USER root + +# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug +CMD ["sh", "run.sh"] \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..14d06d0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +version: '3.4' + +services: + campus_nightpass: + image: tiet/campus_nightpass + build: + context: . + dockerfile: ./Dockerfile + ports: + - "4376:4376" + volumes: + - ./data:/app/data + - ./static:/app/static + restart: always + # command: "gunicorn -b 0.0.0.0:4376 core.wsgi:application" diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..989f1c4 --- /dev/null +++ b/run.sh @@ -0,0 +1,4 @@ +python manage.py makemigrations +python manage.py migrate +python manage.py collectstatic --noinput +gunicorn -b 0.0.0.0:4376 core.wsgi:application \ No newline at end of file From 348a05e35c506b9d60473f978360bd74c2e01ff6 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Fri, 1 Dec 2023 16:27:29 +0530 Subject: [PATCH 02/69] added kiosk extension --- .gitignore | 1 - apps/nightpass/static/styles.css | 215 ++++++++++++++++++++ apps/nightpass/templates/lmao.html | 218 +------------------- apps/users/static/login.css | 98 +++++++++ apps/validation/static/info.css | 178 ++++++++++++++++ apps/validation/static/info.js | 235 ++++++++++++++++++++++ apps/validation/templates/extenstion.html | 52 +++++ apps/validation/urls.py | 1 + apps/validation/views.py | 62 ++++++ 9 files changed, 842 insertions(+), 218 deletions(-) create mode 100644 apps/nightpass/static/styles.css create mode 100644 apps/users/static/login.css create mode 100644 apps/validation/static/info.css create mode 100644 apps/validation/static/info.js create mode 100644 apps/validation/templates/extenstion.html diff --git a/.gitignore b/.gitignore index 8b98db4..afe85b6 100644 --- a/.gitignore +++ b/.gitignore @@ -61,7 +61,6 @@ local_settings.py db.sqlite3 db.sqlite3-journal staticfiles -static *.xlsx *.csv *.xls diff --git a/apps/nightpass/static/styles.css b/apps/nightpass/static/styles.css new file mode 100644 index 0000000..5aedf33 --- /dev/null +++ b/apps/nightpass/static/styles.css @@ -0,0 +1,215 @@ +body { + font-family: Arial, sans-serif; + background-color: #f5f5f5; + margin: 0; + padding: 0; +} + +.header { + display: flex; + align-items: center; + justify-content: space-between; + background-color: #eb1b23; + color: #fff; + text-align: center; + padding: 2px; /* Reduced header padding */ +} + +.header-logo { + width: 100px; /* Set the width of your college logo */ + height: auto; /* Maintain aspect ratio */ +} + +.logout-button { + background-color: #fff; + color: #eb1b23; + border: none; + padding: 5px 10px; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.2s; + margin-right: 20px; +} + +.logout-button:hover { + background-color: #ccc; +} + +.container { + display: flex; + flex-wrap: nowrap; + justify-content: center; + align-items: center; +} + + +.profile-card, .resource-card { + background-color: #fff; + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin: 20px; + width: 300px; + text-align: center; + padding: 20px; + transition: transform 0.2s; +} + +.profile-card:hover, .resource-card:hover { + transform: scale(1.05); +} + +.profile-img { + width: 100px; + border-radius: 50%; + object-fit: cover; + margin-bottom: 20px; +} + +.qr-code { + width: 100px; + height: 100px; + margin-bottom: 20px; +} + +.profile-details { + font-size: 18px; + margin-bottom: 20px; + text-align: left; +} + +.safe { + color: green; +} + +.unsafe { + color: red; +} + +.book-button { + background-color: #eb1b23; + color: #fff; + border: none; + padding: 10px 20px; + border-radius: 10px; + cursor: pointer; + transition: background-color 0.2s; +} + +.booked { + background-color: grey; +} + +.book-button:hover { + background-color: #ff3336; +} + +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); +} + +.modal-content { + background-color: #fff; + width: 80%; + max-width: 400px; + margin: 20% auto; + padding: 20px; + border-radius: 5px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); + text-align: center; + position: relative; + display: flex; +} + +.modal-image { + flex: 1; +} + +.modal-image img { + width: 100%; + height: auto; + object-fit: cover; +} + +.modal-details { + flex: 2; + padding: 10px; + text-align: left; +} + +/* Close button for the modal */ +.close { + position: absolute; + top: 10px; + right: 10px; + cursor: pointer; +} + +.modal-button { + background-color: #eb1b23; + color: #fff; + border: none; + padding: 10px 20px; + border-radius: 10px; + cursor: pointer; + transition: background-color 0.2s; +} + +.modal-button:hover { + background-color: #ff3336; +} + +select { + width: 100%; + padding: 10px; + margin: 10px 0; +} +.resource-card { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +} +.resource-card img { + width: 100px; + height: 100px; + object-fit: cover; + border-radius: 5px; + margin-right: 5px; +} +.resource-details { + flex: 1; + padding: 10px; + text-align: left; +} +.resource-details h2 { + margin: 0; +} +.resource-details p { + margin: 0; +} +.location-cards +{ + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; +} + + +@media (max-width: 768px) { + .profile-card, .resource-card { + width: 90%; + } + .container { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; +} +} \ No newline at end of file diff --git a/apps/nightpass/templates/lmao.html b/apps/nightpass/templates/lmao.html index 49fcef3..cee0c73 100644 --- a/apps/nightpass/templates/lmao.html +++ b/apps/nightpass/templates/lmao.html @@ -8,223 +8,7 @@ - +
diff --git a/apps/users/static/login.css b/apps/users/static/login.css new file mode 100644 index 0000000..d7a23f7 --- /dev/null +++ b/apps/users/static/login.css @@ -0,0 +1,98 @@ +body { + background-color: #940d0d; + font-family: Arial, sans-serif; + margin: 0; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; +} + +.container { + background-color: white; + max-width: 300px; + padding: 20px; + width: 45%; + border-radius: 8px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); +} + +.logo { + text-align: center; +} + +.logo img { + height: 100px; +} + +.login-box { + text-align: center; +} + +.login-box h2 { + margin-bottom: 20px; +} + +.container form { + display: flex; + flex-direction: column; +} + +.container input { + padding: 10px; + margin-bottom: 10px; + border: 1px solid #ccc; + border-radius: 4px; +} + +.container button { + padding: 10px; + background-color: #940d0d; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.container button:hover { + background-color: #ed0505; +} + +/* "activate-account" link */ +.activate-account { + text-align: center; + margin-top: 15px; +} + +.activate-account a { + color: #7240ce; + text-decoration: none; +} + +.activate-account a:hover { + text-decoration: underline; +} + +/* Animation */ +.container { + animation: fadeIn 1s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* Responsive styles */ +@media screen and (max-width: 500px) { + .container { + max-width: 90%; + width: 70%; + } +} diff --git a/apps/validation/static/info.css b/apps/validation/static/info.css new file mode 100644 index 0000000..6e9abe2 --- /dev/null +++ b/apps/validation/static/info.css @@ -0,0 +1,178 @@ +body { + font-family: Arial, sans-serif; + background-color: #f5f5f5; + margin: 0; + padding: 0; +} + +/* Your existing styles... */ + +.header { + display: flex; + align-items: center; + justify-content: space-between; + background-color: #eb1b23; + color: #fff; + text-align: center; + padding: 2px; /* Reduced header padding */ +} + +.header-logo { + width: 100px; /* Set the width of your college logo */ + height: auto; /* Maintain aspect ratio */ +} + +.logout-button { + background-color: #fff; + color: #eb1b23; + border: none; + padding: 5px 10px; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.2s; + margin-right: 20px; +} + +.logout-button:hover { + background-color: #ccc; +} +.container { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-items: center; +} + +.main-card { + background-color: #fff; + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin: 20px; + width: 600px; + text-align: center; + padding: 20px; + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; +} + +.main-card .profile-card, +.main-card .pass-card { + min-height: 350px; + background-color: #fff; + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + margin: 10px; + flex: 1; + padding: 20px; +} +.tempimg{ + max-width: 100%; +} +#scan-line { + position: absolute; + width: 100%; + height: 2px; + background-color: red; /* Change the color as needed */ + animation: scanAnimation 2s linear infinite; + } + + @keyframes scanAnimation { + 0% { + transform: translateY(0); + } + 100% { + transform: translateY(100%); + } + } + +.profile-card .image, +.pass-card img { + width: 100px; + height: 100px; + border-radius: 50%; + object-fit: cover; + margin-right: 20px; +} + +.profile-details, +.pass-details { + text-align: left; +} + +.profile-details h2, +.pass-details h2 { + font-size: 20px; + margin-top: 10px; +} + +.profile-details p, +.pass-details p { + font-size: 16px; + margin: 10px 0; +} + +.action-button { + background-color: #eb1b23; + color: #fff; + border: none; + padding: 10px 20px; + border-radius: 10px; + cursor: pointer; + transition: background-color 0.2s; + margin: 20px auto; +} + +.action-button:hover { + background-color: #ff3336; +} + +.camera-card { + background-color: #fff; + border-radius: 10px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + width: 300px; + text-align: center; + padding: 20px; + display: flex; + flex-direction: column; + align-items: center; +} + +.camera-card video { + width: 100%; + max-width: 280px; + border-radius: 10px; + object-fit: cover; +} + +.qr-result { + margin-top: 10px; + font-size: 16px; +} + +.location-selector { + margin-top: 10px; +} + +.location-selector label { + font-weight: bold; +} + +.location-selector select { + width: 100%; + padding: 10px; + border: 1px solid #ccc; + border-radius: 5px; + font-size: 14px; +} + +.roll-num { + width: 100%; + padding: 10px; + border: 1px solid #ccc; + border-radius: 5px; + font-size: 14px; + margin-bottom: 10px; +} \ No newline at end of file diff --git a/apps/validation/static/info.js b/apps/validation/static/info.js new file mode 100644 index 0000000..24016c0 --- /dev/null +++ b/apps/validation/static/info.js @@ -0,0 +1,235 @@ +function resetProfile() { + document.querySelector('.profile-card').innerHTML=` + Profile Picture +
`; + resetPass(); +} +function resetPass() { + const passDetails = document.querySelector('.pass-details'); + const passIdElement = passDetails.querySelector('p:nth-child(2)'); + const accessElement = passDetails.querySelector('p:nth-child(3)'); + const checkinElement = passDetails.querySelector('p:nth-child(4)'); + const entryTimeElement = passDetails.querySelector('p:nth-child(5)'); + const checkoutElement = passDetails.querySelector('p:nth-child(6)'); + const exitTimeElement = passDetails.querySelector('p:nth-child(7)'); + const actionButton = document.getElementById('action-button') + document.getElementById('pass-card').style.backgroundColor = '#FFFFFF' + passIdElement.textContent = `Pass ID: `; + accessElement.textContent = `Access: `; + checkinElement.textContent = `Check-in: `; + entryTimeElement.textContent = `Entry Time: `; + checkoutElement.textContent = `Check-out: `; + exitTimeElement.textContent = `Exit Time: `; + + actionButton.style.visibility = 'hidden'; + actionButton.innerHTML = ``; + actionButton.style.setProperty('priority', 'important'); + actionButton.onclick = function() {} + + } + +function updateProfile(data) { + document.querySelector('.profile-card').innerHTML=` + Student Picture +
+

+

Registration Number:

+

Hostel:

+

Room Number:

+

In Hostel:

+

Hostel Check-in Time:

+

Hostel Check-out Time:

+

Last Check-out Time:

+

Has Booked:

+
`; + const profileDetails = document.querySelector('.profile-details'); + const nameElement = profileDetails.querySelector('h2'); + const regNumberElement = profileDetails.querySelector('p:nth-child(2)'); + const hostelElement = profileDetails.querySelector('p:nth-child(3)'); + const roomNumberElement = profileDetails.querySelector('p:nth-child(4)'); + const inHostelElement = profileDetails.querySelector('p:nth-child(5)'); + const hostelCheckinElement = profileDetails.querySelector('p:nth-child(6)'); + const hostelCheckoutElement = profileDetails.querySelector('p:nth-child(7)'); + const lastCheckoutElement = profileDetails.querySelector('p:nth-child(8)'); + const hasBookedElement = profileDetails.querySelector('p:nth-child(9)'); + const options = { hour: '2-digit', minute: '2-digit', hour12: true, month: 'long', day: '2-digit' }; + const checkinTime = new Date(data.hostel_checkin_time).toLocaleString('en-US', options); + const checkoutTime = new Date(data.hostel_checkout_time).toLocaleString('en-US', options); + const lastCheckoutTime = new Date(data.last_checkout_time).toLocaleString('en-US', options); + document.getElementById('user_picture').src = data.picture; + nameElement.textContent = data.name; + regNumberElement.textContent = `Registration Number: ${data.registration_number}`; + hostelElement.textContent = `Hostel: ${data.hostel}`; + roomNumberElement.textContent = `Room Number: ${data.room_number}`; + inHostelElement.textContent = `In Hostel: ${data.is_checked_in ? 'Yes' : 'No'}`; + hostelCheckinElement.textContent = `Hostel Check-in Time: ${checkinTime}`; + hostelCheckoutElement.textContent = `Hostel Check-out Time: ${checkoutTime}`; + lastCheckoutElement.textContent = `Last Check-out Time: ${lastCheckoutTime}`; + hasBookedElement.textContent = `Has Booked: ${data.has_booked ? 'Yes' : 'No'}`; + setTimeout(function(){resetProfile();}, 10000); +} + +// Function to update the user pass section with data +function updateUserPass(data,user_data, task) { + const passDetails = document.querySelector('.pass-details'); + const passIdElement = passDetails.querySelector('p:nth-child(2)'); + const accessElement = passDetails.querySelector('p:nth-child(3)'); + const checkinElement = passDetails.querySelector('p:nth-child(4)'); + const entryTimeElement = passDetails.querySelector('p:nth-child(5)'); + const checkoutElement = passDetails.querySelector('p:nth-child(6)'); + const exitTimeElement = passDetails.querySelector('p:nth-child(7)'); + const actionButton = document.getElementById('action-button') + + passIdElement.textContent = `Pass ID: ${data.pass_id}`; + accessElement.textContent = `Access: ${data.campus_resource}`; + checkinElement.textContent = `Check-in: ${data.check_in}`; + entryTimeElement.textContent = `Entry Time: ${data.check_in_time}`; + checkoutElement.textContent = `Check-out: ${data.check_out}`; + exitTimeElement.textContent = `Exit Time: ${data.check_out_time}`; + + if (task['check_out']) { + actionButton.style.visibility = 'visible'; + actionButton.innerHTML = `Check Out`; + actionButton.onclick = function() {checkOut(user_data.registration_number);} + } else if (task['check_in']) { + actionButton.style.visibility = 'visible'; + actionButton.innerHTML = `Check In`; + actionButton.onclick = function(){checkIn(user_data.registration_number);}} +} + +function fetch_data(dump) { + urls = "" + $.ajax({ + method: "POST", + url: urls, + data:dump, + dataType: "json", + timeout: 12000, + success: function (response) { + let res = response.status; + if (res) { + updateProfile(response.user); + updateUserPass(response.user_pass, response.user, response.task); + if (response.user_pass.pass_id) { + document.getElementById('pass-card').style.backgroundColor = '#90EE90' + } else [ + document.getElementById('pass-card').style.backgroundColor = '#FF7F7F' + ] + toastr.success(response.message); + } + else { + toastr.error(response.message); + } + }, + error: function (xhr, textStatus, errorThrown) { + toastr.error("Something went wrong, please try again later"); + } +}); +} + + +function fetch_data(dump) { + urls = "" + $.ajax({ + method: "POST", + url: urls, + data:dump, + dataType: "json", + timeout: 12000, + success: function (response) { + let res = response.status; + if (res) { + updateProfile(response.user); + updateUserPass(response.user_pass, response.user, response.task); + if (response.user_pass.pass_id) { + document.getElementById('pass-card').style.backgroundColor = '#90EE90' + } else [ + document.getElementById('pass-card').style.backgroundColor = '#FF7F7F' + ] + toastr.success(response.message); + } + else { + toastr.error(response.message); + } + }, + error: function (xhr, textStatus, errorThrown) { + toastr.error("Something went wrong, please try again later"); + } +}); +} + +function checkIn(registration_number) { + urls = "checkin/" + $.ajax({ + method: "POST", + url: urls, + data:{'registration_number':registration_number}, + dataType: "json", + timeout: 120000, + success: function (response) { + let res = response.status; + if (res) { + // resetProfile(); + // updateProfile(response.user); + // updateUserPass(response.user_pass, response.user); + toastr.success(response.message); + setTimeout(function(){ resetProfile(); }, 3000); + + } + else { + toastr.error(response.message); + } + }, + error: function (xhr, textStatus, errorThrown) { + toastr.error("Something went wrong, please try again later"); + } +}); +} + +function checkOut(registration_number) { + urls = "checkout/" + $.ajax({ + method: "POST", + url: urls, + data:{'registration_number':registration_number}, + dataType: "json", + timeout: 120000, + success: function (response) { + let res = response.status; + if (res) { + + // updateProfile(response.user); + // updateUserPass(response.user_pass, response.user); + toastr.success(response.message); + setTimeout(function(){ resetProfile(); }, 3000); + } + else { + toastr.error(response.message); + } + }, + error: function (xhr, textStatus, errorThrown) { + toastr.error("Something went wrong, please try again later"); + } +}); +} + + +let enteredIntegers = 0; +function checkInput() { + const inputElement = document.getElementById('roll_num'); + + if (inputElement.value.length >= 0 && inputElement.value.length == 9) { + enteredIntegers = inputElement.value.length; + if (enteredIntegers === 9) { + fetch_data({'registration_number':inputElement.value}) + var audio = new Audio('../static/beep.mp3'); + audio.play(); + inputElement.value = ''; + enteredIntegers = 0; + } + } +} + +setInterval(function () { + checkInput() +}, 1000); \ No newline at end of file diff --git a/apps/validation/templates/extenstion.html b/apps/validation/templates/extenstion.html new file mode 100644 index 0000000..e17c851 --- /dev/null +++ b/apps/validation/templates/extenstion.html @@ -0,0 +1,52 @@ + + + + + + Student Information + + + + + + +
+ +

Thapar NightPass

+ +
+ +
+
+
+ + {% if data.status %} + + Student Picture +
+

{{ data.user.name }}

+

Registration Number: {{ data.user.registration_number }}

+

Hostel: {{ data.user.hostel }}

+

Hostel Check-out Time: {{ data.user.hostel_checkout_time }}

+

Access: {{ data.user_pass.campus_resource }}

+

Check-in: {{ data.user_pass.check_in }}

+

Entry Time: {{ data.user_pass.check_in_time }}

+

Check-out: {{ data.user_pass.check_out }}

+

Exit Time: {{ data.user_pass.check_out_time }}

+
+ {% else %} + Profile Picture + {% endif %} +
+
+
+ + diff --git a/apps/validation/urls.py b/apps/validation/urls.py index 3cf5525..81a3b0d 100644 --- a/apps/validation/urls.py +++ b/apps/validation/urls.py @@ -6,4 +6,5 @@ path('', scanner), path('checkin/', check_in), path('checkout/', check_out), + path('extension/fetchuser/performtask/', kiosk_extension) ] diff --git a/apps/validation/views.py b/apps/validation/views.py index adad950..c409606 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -228,3 +228,65 @@ def scanner(request): +@csrf_exempt +def kiosk_extension(request): + if request.user.is_staff: + data = request.GET + try: + user = Student.objects.get(registration_number=data['registration_number']) + user_pass = NightPass.objects.filter(user=user.user, valid=True).first() + admin_campus_resource = request.user.security.campus_resource if request.user.security.campus_resource else request.user.security.hostel + if user_pass: + data = { + 'status':True, + 'message':'Successfully fetched!', + 'user':{ + 'name':user.name, + 'registration_number':user.registration_number, + 'hostel':user.hostel.name if user.hostel else None, + 'room_number':user.room_number, + 'picture':user.picture, + 'is_checked_in':user.is_checked_in, + 'hostel_checkin_time':str(user.hostel_checkin_time), + 'hostel_checkout_time':str(user.hostel_checkout_time), + 'last_checkout_time':str(user.last_checkout_time), + 'has_booked':user.has_booked, + }, + 'user_pass':{ + 'pass_id':user_pass.pass_id, + 'campus_resource':user_pass.campus_resource.name, + 'check_in':user_pass.check_in, + 'check_out':user_pass.check_out, + 'check_in_time':str(user_pass.check_in_time), + 'check_out_time':str(user_pass.check_out_time), + } + } + if type(admin_campus_resource) == Hostel: + if not user.is_checked_in: + checkin_to_hostel(user) + data['colour'] = '#ffff80' + else: + checkout_from_hostel(user_pass) + data['colour'] = '#8aff8a' + return render('extension.html', {'data':data}) + elif type(admin_campus_resource) == CampusResource and admin_campus_resource == (user_pass.campus_resource if user_pass else None): + if not user_pass.check_in: + checkin_to_location(user_pass) + data['colour'] = '#8aff8a' + elif not user_pass.check_out and user_pass.check_in: + checkout_from_location(user_pass) + data['colour'] = '#ffff80' + return render('extension.html', {'data':data}) + return + else: + data = { + 'status':False, + 'message':'Pass does not exist!' + } + return render('extension.html', {'data':data}) + except Student.DoesNotExist: + data = { + 'status':False, + 'message':'Invalid!' + } + return HttpResponse(json.dumps(data)) From a93ccaed35cb9415c021df71a356c30114036020 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Fri, 1 Dec 2023 16:33:28 +0530 Subject: [PATCH 03/69] bug fix --- apps/validation/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/validation/views.py b/apps/validation/views.py index c409606..b125288 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -289,4 +289,5 @@ def kiosk_extension(request): 'status':False, 'message':'Invalid!' } - return HttpResponse(json.dumps(data)) + return render('extension.html', {'data':data}) + From 2459076e6891b41830489cf702f5b483bf45ea7a Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Sat, 2 Dec 2023 14:14:10 +0530 Subject: [PATCH 04/69] updated check flow for campus_resources --- apps/validation/static/info.js | 19 ++++++++++++++----- apps/validation/templates/info.html | 2 +- apps/validation/views.py | 2 ++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/validation/static/info.js b/apps/validation/static/info.js index 24016c0..e886b64 100644 --- a/apps/validation/static/info.js +++ b/apps/validation/static/info.js @@ -70,7 +70,7 @@ function updateProfile(data) { } // Function to update the user pass section with data -function updateUserPass(data,user_data, task) { +function updateUserPass(data,user_data, task, request_user_location) { const passDetails = document.querySelector('.pass-details'); const passIdElement = passDetails.querySelector('p:nth-child(2)'); const accessElement = passDetails.querySelector('p:nth-child(3)'); @@ -88,13 +88,23 @@ function updateUserPass(data,user_data, task) { exitTimeElement.textContent = `Exit Time: ${data.check_out_time}`; if (task['check_out']) { + if (request_user_location == 'campus_resource') { + checkOut(user_data.registration_number); + document.getElementById('pass-card').style.backgroundColor = '#F0E68C'; + } else { actionButton.style.visibility = 'visible'; actionButton.innerHTML = `Check Out`; - actionButton.onclick = function() {checkOut(user_data.registration_number);} + document.getElementById('pass-card').style.backgroundColor = '#90EE90' + actionButton.onclick = function() {checkOut(user_data.registration_number);}} } else if (task['check_in']) { + if (request_user_location == 'campus_resource') { + checkIn(user_data.registration_number); + document.getElementById('pass-card').style.backgroundColor = '#90EE90'; + } else { + document.getElementById('pass-card').style.backgroundColor = '#F0E68C'; actionButton.style.visibility = 'visible'; actionButton.innerHTML = `Check In`; - actionButton.onclick = function(){checkIn(user_data.registration_number);}} + actionButton.onclick = function(){checkIn(user_data.registration_number);}}} } function fetch_data(dump) { @@ -109,9 +119,8 @@ function fetch_data(dump) { let res = response.status; if (res) { updateProfile(response.user); - updateUserPass(response.user_pass, response.user, response.task); + updateUserPass(response.user_pass, response.user, response.task, response.request_user_location); if (response.user_pass.pass_id) { - document.getElementById('pass-card').style.backgroundColor = '#90EE90' } else [ document.getElementById('pass-card').style.backgroundColor = '#FF7F7F' ] diff --git a/apps/validation/templates/info.html b/apps/validation/templates/info.html index 8cf40c3..2a585ea 100644 --- a/apps/validation/templates/info.html +++ b/apps/validation/templates/info.html @@ -100,7 +100,7 @@

QR Code Scanner

setInterval(function () { lastScannedBarcode = null; - }, 2000); + }, 5000); diff --git a/apps/validation/views.py b/apps/validation/views.py index b125288..d44dec2 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -70,12 +70,14 @@ def fetch_user_status(request): 'check_in':True if not user.is_checked_in else False, 'check_out':True if user.is_checked_in else False } + data['request_user_location'] = 'hostel' return HttpResponse(json.dumps(data)) elif type(admin_campus_resource) == CampusResource and admin_campus_resource == (user_pass.campus_resource if user_pass else None): data['task'] = { 'check_in':True if not user_pass.check_in else False, 'check_out':True if (not user_pass.check_out and user_pass.check_in) else False } + data['request_user_location'] = 'campus_resource' return HttpResponse(json.dumps(data)) else: data = { From e995871c848778d4ad1b35c0f771859201e9b936 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Sat, 2 Dec 2023 14:19:53 +0530 Subject: [PATCH 05/69] minor check --- apps/validation/static/info.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/validation/static/info.js b/apps/validation/static/info.js index e886b64..1cf5cf6 100644 --- a/apps/validation/static/info.js +++ b/apps/validation/static/info.js @@ -118,6 +118,7 @@ function fetch_data(dump) { success: function (response) { let res = response.status; if (res) { + console.log(response.request_user_location) updateProfile(response.user); updateUserPass(response.user_pass, response.user, response.task, response.request_user_location); if (response.user_pass.pass_id) { From f7efbd7bfae1f0462864f6408e569a4e7c22e336 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Sat, 2 Dec 2023 14:25:29 +0530 Subject: [PATCH 06/69] minor bug fix --- apps/validation/static/info.js | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/apps/validation/static/info.js b/apps/validation/static/info.js index 1cf5cf6..eddf7da 100644 --- a/apps/validation/static/info.js +++ b/apps/validation/static/info.js @@ -138,36 +138,6 @@ function fetch_data(dump) { } -function fetch_data(dump) { - urls = "" - $.ajax({ - method: "POST", - url: urls, - data:dump, - dataType: "json", - timeout: 12000, - success: function (response) { - let res = response.status; - if (res) { - updateProfile(response.user); - updateUserPass(response.user_pass, response.user, response.task); - if (response.user_pass.pass_id) { - document.getElementById('pass-card').style.backgroundColor = '#90EE90' - } else [ - document.getElementById('pass-card').style.backgroundColor = '#FF7F7F' - ] - toastr.success(response.message); - } - else { - toastr.error(response.message); - } - }, - error: function (xhr, textStatus, errorThrown) { - toastr.error("Something went wrong, please try again later"); - } -}); -} - function checkIn(registration_number) { urls = "checkin/" $.ajax({ From 6c9beeefe5b93d00202f96a510a40ae2777d7762 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Sat, 2 Dec 2023 14:29:24 +0530 Subject: [PATCH 07/69] fixed colour coding --- apps/validation/static/info.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/validation/static/info.js b/apps/validation/static/info.js index eddf7da..e113513 100644 --- a/apps/validation/static/info.js +++ b/apps/validation/static/info.js @@ -104,7 +104,10 @@ function updateUserPass(data,user_data, task, request_user_location) { document.getElementById('pass-card').style.backgroundColor = '#F0E68C'; actionButton.style.visibility = 'visible'; actionButton.innerHTML = `Check In`; - actionButton.onclick = function(){checkIn(user_data.registration_number);}}} + actionButton.onclick = function(){checkIn(user_data.registration_number);}} + } else { + document.getElementById('pass-card').style.backgroundColor = '#FF7F7F'; + } } function fetch_data(dump) { @@ -153,7 +156,7 @@ function checkIn(registration_number) { // updateProfile(response.user); // updateUserPass(response.user_pass, response.user); toastr.success(response.message); - setTimeout(function(){ resetProfile(); }, 3000); + setTimeout(function(){ resetProfile(); }, 7000); } else { @@ -181,7 +184,7 @@ function checkOut(registration_number) { // updateProfile(response.user); // updateUserPass(response.user_pass, response.user); toastr.success(response.message); - setTimeout(function(){ resetProfile(); }, 3000); + setTimeout(function(){ resetProfile(); }, 7000); } else { toastr.error(response.message); From fad4a9cc822834dd6cb2ae771efe4e7b1e32f62e Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Sat, 2 Dec 2023 14:45:31 +0530 Subject: [PATCH 08/69] bug fix --- apps/validation/static/info.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/validation/static/info.js b/apps/validation/static/info.js index e113513..905c497 100644 --- a/apps/validation/static/info.js +++ b/apps/validation/static/info.js @@ -89,8 +89,11 @@ function updateUserPass(data,user_data, task, request_user_location) { if (task['check_out']) { if (request_user_location == 'campus_resource') { - checkOut(user_data.registration_number); + actionButton.style.visibility = 'visible'; + actionButton.innerHTML = `Check Out`; + // checkOut(user_data.registration_number); document.getElementById('pass-card').style.backgroundColor = '#F0E68C'; + actionButton.onclick = function() {checkOut(user_data.registration_number);} } else { actionButton.style.visibility = 'visible'; actionButton.innerHTML = `Check Out`; @@ -98,8 +101,11 @@ function updateUserPass(data,user_data, task, request_user_location) { actionButton.onclick = function() {checkOut(user_data.registration_number);}} } else if (task['check_in']) { if (request_user_location == 'campus_resource') { - checkIn(user_data.registration_number); + // checkIn(user_data.registration_number); document.getElementById('pass-card').style.backgroundColor = '#90EE90'; + actionButton.style.visibility = 'visible'; + actionButton.innerHTML = `Check In`; + actionButton.onclick = function(){checkIn(user_data.registration_number);} } else { document.getElementById('pass-card').style.backgroundColor = '#F0E68C'; actionButton.style.visibility = 'visible'; From bfb43a48b4bef7bf0fe84c9a726748a4e0708382 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Sat, 2 Dec 2023 18:14:16 +0530 Subject: [PATCH 09/69] integrated with library logs through req --- apps/validation/views.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/apps/validation/views.py b/apps/validation/views.py index d44dec2..61ddfa0 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -5,6 +5,7 @@ from django.contrib.auth.decorators import login_required import json from datetime import datetime +import requests # Create your views here. @@ -93,6 +94,21 @@ def fetch_user_status(request): 'message':'Invalid!' } return HttpResponse(json.dumps(data)) + + +def req_library_logs(registration_number): + req = requests.session() + url = "https://library.thapar.edu/inout/login_verify.php" + data = { + "name": "user", + "pass": "$#**123", + "loc": "TESTLIB", + "submit": "Login" + } + response = req.post(url, data=data, verify=False) + req.get(f"https://library.thapar.edu/inout/user.php?id={registration_number}") + req.close() + @csrf_exempt @login_required @@ -112,6 +128,8 @@ def check_out(request): if type(admin_campus_resource) == Hostel: return checkout_from_hostel(user_pass) elif type(admin_campus_resource) == CampusResource: + if admin_campus_resource.name == 'Library': + req_library_logs(user.registration_number) return checkout_from_location(user_pass) except Student.DoesNotExist: data = { @@ -169,6 +187,8 @@ def check_in(request): 'message':'Pass does not exist!' } return HttpResponse(json.dumps(data)) + if admin_campus_resource.name == 'Library': + req_library_logs(user.registration_number) return checkin_to_location(user_pass) except Student.DoesNotExist: data = { From b63dc02457da22d18642a34ac3f2a599e91a7a7e Mon Sep 17 00:00:00 2001 From: akarsh911 Date: Sat, 2 Dec 2023 19:09:32 +0530 Subject: [PATCH 10/69] Add autofocus to roll number input field --- apps/validation/templates/info.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/validation/templates/info.html b/apps/validation/templates/info.html index 2a585ea..cc7f3f0 100644 --- a/apps/validation/templates/info.html +++ b/apps/validation/templates/info.html @@ -39,7 +39,7 @@

User Pass Information

QR Code Scanner

- +
+ {% if request.user.security.campus_resource %} +
+

+ {{ request.user.security.campus_resource }} +

+

Students: {{ check_in_count }}


+

Booking: {{ total_count }}


+
+ {% endif %} + From 056806d64f4ba5819ab725496ee4af976766871d Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Wed, 6 Dec 2023 19:03:37 +0530 Subject: [PATCH 56/69] preventing unwanted duplicate scan --- apps/validation/static/info.js | 55 +++++++++++++---------- apps/validation/views.py | 79 +++++++++++++++++++++------------- 2 files changed, 82 insertions(+), 52 deletions(-) diff --git a/apps/validation/static/info.js b/apps/validation/static/info.js index 8468171..ea05514 100644 --- a/apps/validation/static/info.js +++ b/apps/validation/static/info.js @@ -1,24 +1,41 @@ -toastr.options = { - "closeButton": false, - "newestOnTop": true, - "progressBar": false, - "positionClass": "toast-bottom-full-width", - "preventDuplicates": true, - "onclick": null, - "showDuration": "300", - "hideDuration": "1000", - "timeOut": "3000", - "extendedTimeOut": "1000", - "showEasing": "swing", - "hideEasing": "linear", - "showMethod": "fadeIn", - "hideMethod": "fadeOut" -} + function is_mobile() { if (navigator.userAgentData.mobile) { + toastr.options = { + "closeButton": false, + "newestOnTop": true, + "progressBar": false, + "positionClass": "toast-top-right", + "preventDuplicates": true, + "onclick": null, + "showDuration": "300", + "hideDuration": "1000", + "timeOut": "3000", + "extendedTimeOut": "1000", + "showEasing": "swing", + "hideEasing": "linear", + "showMethod": "fadeIn", + "hideMethod": "fadeOut" + } return true; } else { + toastr.options = { + "closeButton": false, + "newestOnTop": true, + "progressBar": false, + "positionClass": "toast-bottom-full-width", + "preventDuplicates": true, + "onclick": null, + "showDuration": "300", + "hideDuration": "1000", + "timeOut": "3000", + "extendedTimeOut": "1000", + "showEasing": "swing", + "hideEasing": "linear", + "showMethod": "fadeIn", + "hideMethod": "fadeOut" + } return false; } } @@ -171,7 +188,6 @@ function fetch_data(dump) { } else [ document.getElementById('pass-card').style.backgroundColor = '#FF7F7F' ] - // toastr.success(response.message); } else { toastr.error(response.message); @@ -197,9 +213,6 @@ function checkIn(registration_number) { let res = response.status; if (res) { if (response.student_stats) {updateStats(response.student_stats);} - // resetProfile(); - // updateProfile(response.user); - // updateUserPass(response.user_pass, response.user); toastr.success(response.message); setTimeout(function(){ resetProfile(); }, 5000); @@ -227,8 +240,6 @@ function checkOut(registration_number) { let res = response.status; if (res) { if (response.student_stats) {updateStats(response.student_stats);} - // updateProfile(response.user); - // updateUserPass(response.user_pass, response.user); toastr.success(response.message); setTimeout(function(){ resetProfile(); }, 7000); } diff --git a/apps/validation/views.py b/apps/validation/views.py index 0b1c7ac..04ca0fa 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -4,7 +4,7 @@ from django.views.decorators.csrf import csrf_exempt from django.contrib.auth.decorators import login_required import json -from datetime import datetime, date +from datetime import datetime, date, timedelta import requests # Create your views here. @@ -157,21 +157,26 @@ def checkout_from_hostel(user_pass:NightPass, direct:bool=True): def checkout_from_location(user_pass, admin_campus_resource:CampusResource ,direct:bool=True, ): user = user_pass.user - user.student.last_checkout_time = datetime.now() if direct else None - user.student.has_booked = False - user.student.save() - user_pass.check_out = True if direct else False - user_pass.check_out_time = datetime.now() if direct else None - user_pass.save() - data = { - 'status':True, - 'message':'Successfully checked out!' - } - data['student_stats'] = { - 'check_in_count':NightPass.objects.filter(check_in=True, check_out=False,valid=True, date=date.today(), campus_resource=admin_campus_resource).count(), - 'total_count':NightPass.objects.filter(valid=True, date=date.today(), campus_resource=admin_campus_resource).count() - } - + if not is_repeated_scan(user_pass): + user.student.last_checkout_time = datetime.now() if direct else None + user.student.has_booked = False + user.student.save() + user_pass.check_out = True if direct else False + user_pass.check_out_time = datetime.now() if direct else None + user_pass.save() + data = { + 'status':True, + 'message':'Successfully checked out!' + } + data['student_stats'] = { + 'check_in_count':NightPass.objects.filter(check_in=True, check_out=False,valid=True, date=date.today(), campus_resource=admin_campus_resource).count(), + 'total_count':NightPass.objects.filter(valid=True, date=date.today(), campus_resource=admin_campus_resource).count() + } + else: + data = { + 'status':False, + 'message':'You just checked out! Please wait for 10mins before checking in again' + } return HttpResponse(json.dumps(data)) @csrf_exempt @@ -184,7 +189,6 @@ def check_in(request): user = Student.objects.get(registration_number=data['registration_number']) user_pass = NightPass.objects.filter(user=user.user, valid=True).first() admin_campus_resource = request.user.security.campus_resource if request.user.security.campus_resource else request.user.security.hostel - if type(admin_campus_resource) == Hostel: return checkin_to_hostel(user) elif type(admin_campus_resource) == CampusResource: @@ -209,20 +213,27 @@ def check_in(request): def checkin_to_hostel(user:Student): if not user.is_checked_in: user_pass = NightPass.objects.filter(user=user.user, valid=True).first() - user.is_checked_in = True - user.hostel_checkin_time = user_pass.hostel_checkin_time= datetime.now() - user.save() - user_pass.valid = False - user_pass.save() - if (not user_pass.check_out if user_pass else False): - checkout_from_location(user_pass, direct=False) - data = { - 'status':True, - 'message':'Successfully checked in!' - } - data['student_stats'] = None + if not is_repeated_scan(user_pass): + user.is_checked_in = True + user.hostel_checkin_time = user_pass.hostel_checkin_time= datetime.now() + user.save() + user_pass.valid = False + user_pass.save() + if (not user_pass.check_out if user_pass else False): + checkout_from_location(user_pass, direct=False) + data = { + 'status':True, + 'message':'Successfully checked in!' + } + data['student_stats'] = None - return HttpResponse(json.dumps(data)) + return HttpResponse(json.dumps(data)) + else: + data = { + 'status':False, + 'message':'You just checked out! Please wait for 10mins before checking in again' + } + return HttpResponse(json.dumps(data)) else: data = { 'status':False, @@ -263,6 +274,14 @@ def scanner(request): return HttpResponse('Invalid Operation') +def is_repeated_scan(user_pass:NightPass): + if (user_pass.check_in and not user_pass.check_out) and (datetime.now()-user_pass.check_in_time Date: Wed, 6 Dec 2023 19:05:56 +0530 Subject: [PATCH 57/69] Update toast position in lmao.html --- apps/nightpass/templates/lmao.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/nightpass/templates/lmao.html b/apps/nightpass/templates/lmao.html index 80563e0..f9a5965 100644 --- a/apps/nightpass/templates/lmao.html +++ b/apps/nightpass/templates/lmao.html @@ -125,7 +125,7 @@ "closeButton": false, "newestOnTop": true, "progressBar": false, - "positionClass": "toast-bottom-full-width", + "positionClass": "toast-top-right", "preventDuplicates": true, "onclick": null, "showDuration": "300", From a20816b144f7e2d048ca34991a43b597f3600c0a Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Wed, 6 Dec 2023 19:14:10 +0530 Subject: [PATCH 58/69] added gender field to student model --- apps/users/admin.py | 3 ++- ...08_student_gender_alter_nightpass_valid.py | 23 +++++++++++++++++++ apps/users/models.py | 1 + apps/users/resources.py | 2 +- 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 apps/users/migrations/0008_student_gender_alter_nightpass_valid.py diff --git a/apps/users/admin.py b/apps/users/admin.py index 8b50f78..f82626b 100644 --- a/apps/users/admin.py +++ b/apps/users/admin.py @@ -40,12 +40,13 @@ def hostel_check_in(self, obj): hostel_check_in.short_description = 'Hostel In' def export_as_xlsx(modeladmin, request, queryset): - headers = ['User', 'Email', 'Hostel', 'Pass ID', 'Date', 'Campus Resource', 'Check In', 'Check Out', 'Hostel Check Out Time', 'Check In Time', 'Check Out Time' ,'Hostel Check In Time', 'Defaulter', 'Remarks'] + headers = ['User', 'Email', 'Hostel', 'Gender','Pass ID', 'Date', 'Campus Resource', 'Check In', 'Check Out', 'Hostel Check Out Time', 'Check In Time', 'Check Out Time' ,'Hostel Check In Time', 'Defaulter', 'Remarks'] data = [] for obj in queryset: data.append([obj.user.student.name, obj.user.email , obj.user.student.hostel.name, + obj.user.student.gender, obj.pass_id, obj.date.strftime('%d/%m/%y'), obj.campus_resource.name, diff --git a/apps/users/migrations/0008_student_gender_alter_nightpass_valid.py b/apps/users/migrations/0008_student_gender_alter_nightpass_valid.py new file mode 100644 index 0000000..10fc460 --- /dev/null +++ b/apps/users/migrations/0008_student_gender_alter_nightpass_valid.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.7 on 2023-12-06 13:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0007_alter_nightpass_check_in_alter_nightpass_check_out_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='student', + name='gender', + field=models.CharField(blank=True, choices=[('male', 'Male'), ('female', 'Female')], max_length=10, null=True), + ), + migrations.AlterField( + model_name='nightpass', + name='valid', + field=models.BooleanField(default=True), + ), + ] diff --git a/apps/users/models.py b/apps/users/models.py index 88770c0..9841238 100644 --- a/apps/users/models.py +++ b/apps/users/models.py @@ -90,6 +90,7 @@ class Student(models.Model): registration_number = models.CharField(max_length=20, unique=True) branch = models.CharField(max_length=50, null=True, blank=True) date_of_birth = models.DateField(null=True, blank=True) + gender = models.CharField(max_length=10, null=True, blank=True, choices=(('male','Male'), ('female','Female'))) father_name = models.CharField(max_length=100, null=True, blank=True) mother_name = models.CharField(max_length=100, null=True, blank=True) course = models.CharField(max_length=50, null=True, blank=True) diff --git a/apps/users/resources.py b/apps/users/resources.py index e324672..dc7c497 100644 --- a/apps/users/resources.py +++ b/apps/users/resources.py @@ -4,7 +4,7 @@ class StudentResource(resources.ModelResource): class Meta: model = Student - fields = ('name', 'contact_number', 'registration_number', 'branch', 'date_of_birth', 'father_name', 'mother_name', 'course', 'semester', 'parent_contact', 'address', 'picture', 'hostel', 'room_number', 'email') + fields = ('name', 'contact_number', 'registration_number','gender', 'branch', 'date_of_birth', 'father_name', 'mother_name', 'course', 'semester', 'parent_contact', 'address', 'picture', 'hostel', 'room_number', 'email') def save_instance(self, instance, is_create, using_transactions=True, dry_run=False): user = CustomUser.objects.filter(email=instance.email).first() From 4ec4b3cd53a70539bb305c2ac507df9706a15f09 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Wed, 6 Dec 2023 19:22:21 +0530 Subject: [PATCH 59/69] force int to import values --- apps/users/resources.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/users/resources.py b/apps/users/resources.py index dc7c497..9d017ca 100644 --- a/apps/users/resources.py +++ b/apps/users/resources.py @@ -13,6 +13,8 @@ def save_instance(self, instance, is_create, using_transactions=True, dry_run=Fa return super().save_instance(instance, is_create, using_transactions, dry_run) else: if not user.student: + instance.registration_number = int(instance.registration_number) + instance.semester = int(instance.semester) instance.user = user return super().save_instance(instance, is_create, using_transactions, dry_run) From 5eae42408c30fa26bc9b4cb356a228f815afbc51 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Wed, 6 Dec 2023 19:33:20 +0530 Subject: [PATCH 60/69] fixed bug in preventing duplicate scan --- apps/nightpass/models.py | 7 +++---- apps/nightpass/templates/change_list.html | 8 ++++++++ apps/validation/views.py | 8 +++++--- 3 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 apps/nightpass/templates/change_list.html diff --git a/apps/nightpass/models.py b/apps/nightpass/models.py index 953b1d7..ed42976 100644 --- a/apps/nightpass/models.py +++ b/apps/nightpass/models.py @@ -1,6 +1,8 @@ from django.db import models from django.utils.translation import gettext_lazy as _ from django.db import models +from django.db.models.signals import post_save +from django.dispatch import receiver class Hostel(models.Model): @@ -26,7 +28,4 @@ class CampusResource(models.Model): def __str__(self): - return self.name - - - + return self.name \ No newline at end of file diff --git a/apps/nightpass/templates/change_list.html b/apps/nightpass/templates/change_list.html new file mode 100644 index 0000000..f5617c3 --- /dev/null +++ b/apps/nightpass/templates/change_list.html @@ -0,0 +1,8 @@ +{% extends "admin/change_list.html" %} + +{% block object-tools %} + {{ block.super }} + +{% endblock %} diff --git a/apps/validation/views.py b/apps/validation/views.py index 04ca0fa..8979f15 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -6,7 +6,7 @@ import json from datetime import datetime, date, timedelta import requests - +from django.utils import timezone # Create your views here. def fetch_user_status(request): @@ -275,13 +275,15 @@ def scanner(request): def is_repeated_scan(user_pass:NightPass): - if (user_pass.check_in and not user_pass.check_out) and (datetime.now()-user_pass.check_in_time Date: Wed, 6 Dec 2023 19:37:08 +0530 Subject: [PATCH 61/69] fixed duplicate scan message --- apps/validation/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/validation/views.py b/apps/validation/views.py index 8979f15..22afd76 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -175,7 +175,7 @@ def checkout_from_location(user_pass, admin_campus_resource:CampusResource ,dire else: data = { 'status':False, - 'message':'You just checked out! Please wait for 10mins before checking in again' + 'message':'You just checked in! Please wait for 10mins before checking out' } return HttpResponse(json.dumps(data)) From f9d98a9e4f1d644de51585830f51a5671c358a61 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Wed, 6 Dec 2023 19:46:26 +0530 Subject: [PATCH 62/69] fixed manual pass delete non coherency --- apps/nightpass/views.py | 61 ++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/apps/nightpass/views.py b/apps/nightpass/views.py index c680862..467c80c 100644 --- a/apps/nightpass/views.py +++ b/apps/nightpass/views.py @@ -51,46 +51,45 @@ def generate_pass(request, campus_resource): return HttpResponse(json.dumps(data)) user_pass = NightPass.objects.filter(user=user, date=date.today()).first() - if not user.student.has_booked and not user_pass: - campus_resource.refresh_from_db() - if campus_resource.slots_booked < campus_resource.max_capacity: - while True: - pass_id = ''.join(random.choices(string.ascii_uppercase + - string.digits, k=16)) + if not user_pass: + campus_resource.refresh_from_db() + if campus_resource.slots_booked < campus_resource.max_capacity: + while True: + pass_id = ''.join(random.choices(string.ascii_uppercase + + string.digits, k=16)) - if not NightPass.objects.filter(pass_id=pass_id).count(): - break - generated_pass = NightPass(campus_resource=campus_resource, pass_id=pass_id, user=user , date=date.today(), start_time=datetime.now(), end_time=datetime.now()) - generated_pass.save() + if not NightPass.objects.filter(pass_id=pass_id).count(): + break + generated_pass = NightPass(campus_resource=campus_resource, pass_id=pass_id, user=user , date=date.today(), start_time=datetime.now(), end_time=datetime.now()) + generated_pass.save() - user.student.has_booked = True - campus_resource.slots_booked += 1 - user.student.save() - campus_resource.save() - data = { - 'pass_qr':None, - 'status':True, - 'message':f"Pass generated successfully for {campus_resource.name}!" - } - return HttpResponse(json.dumps(data)) - else: - data={ - 'status':False, - 'message':f"No more slots available for {campus_resource.name}!" - } - return HttpResponse(json.dumps(data)) - elif user.student.has_booked: - user_nightpass = NightPass.objects.filter(user=user, check_out = False).first() - if user_nightpass.check_in: + user.student.has_booked = True + campus_resource.slots_booked += 1 + user.student.save() + campus_resource.save() + data = { + 'pass_qr':None, + 'status':True, + 'message':f"Pass generated successfully for {campus_resource.name}!" + } + return HttpResponse(json.dumps(data)) + else: + data={ + 'status':False, + 'message':f"No more slots available for {campus_resource.name}!" + } + return HttpResponse(json.dumps(data)) + elif user_pass.valid: + if user_pass.check_in: data={ 'status':False, - 'message':f"New slot can be booked once you exit {user_nightpass.campus_resource}." + 'message':f"New slot can be booked once you exit {user_pass.campus_resource}." } return HttpResponse(json.dumps(data)) else: data={ 'status':False, - 'message':f"Cancel the booking for {user_nightpass.campus_resource} to book a new slot!" + 'message':f"Cancel the booking for {user_pass.campus_resource} to book a new slot!" } return HttpResponse(json.dumps(data)) elif user_pass: From 7eb5d09d40375df9ac5c6d71139c9ac942ab9c92 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Wed, 6 Dec 2023 20:00:58 +0530 Subject: [PATCH 63/69] Fix checkout_from_location function parameter --- apps/validation/views.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/validation/views.py b/apps/validation/views.py index 22afd76..0271d76 100644 --- a/apps/validation/views.py +++ b/apps/validation/views.py @@ -6,7 +6,7 @@ import json from datetime import datetime, date, timedelta import requests -from django.utils import timezone +from django.utils import timezone # Create your views here. def fetch_user_status(request): @@ -155,7 +155,7 @@ def checkout_from_hostel(user_pass:NightPass, direct:bool=True): data['student_stats'] = None return HttpResponse(json.dumps(data)) -def checkout_from_location(user_pass, admin_campus_resource:CampusResource ,direct:bool=True, ): +def checkout_from_location(user_pass, admin_campus_resource:CampusResource=None ,direct:bool=True, ): user = user_pass.user if not is_repeated_scan(user_pass): user.student.last_checkout_time = datetime.now() if direct else None @@ -220,7 +220,7 @@ def checkin_to_hostel(user:Student): user_pass.valid = False user_pass.save() if (not user_pass.check_out if user_pass else False): - checkout_from_location(user_pass, direct=False) + checkout_from_location(user_pass,admin_campus_resource=user_pass.campus_resource ,direct=False) data = { 'status':True, 'message':'Successfully checked in!' From e7fb325dc80805d77e13b1bd22d3c94d09242662 Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Fri, 8 Dec 2023 00:45:09 +0530 Subject: [PATCH 64/69] Update reset_users.py to set has_booked=False --- apps/users/management/commands/reset_users.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/users/management/commands/reset_users.py b/apps/users/management/commands/reset_users.py index 4165757..d521c35 100644 --- a/apps/users/management/commands/reset_users.py +++ b/apps/users/management/commands/reset_users.py @@ -6,5 +6,5 @@ class Command(BaseCommand): def handle(self, *args, **options): self.stdout.write(self.style.SUCCESS('Running your cron job...')) - Student.objects.all().update(is_checked_in=True, last_checkout_time=None, hostel_checkin_time=None, hostel_checkout_time=None) + Student.objects.all().update(is_checked_in=True, last_checkout_time=None, hostel_checkin_time=None, hostel_checkout_time=None, has_booked=False) self.stdout.write(self.style.SUCCESS('Cron job completed successfully')) \ No newline at end of file From 09ed4af65d62bbf3bdbe0d375b7c7744d1e865ec Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Fri, 8 Dec 2023 18:15:54 +0530 Subject: [PATCH 65/69] Add notification verification and cancel booking confirmation --- apps/nightpass/templates/lmao.html | 73 +++++++++++++++++++----------- apps/users/admin.py | 1 + 2 files changed, 47 insertions(+), 27 deletions(-) diff --git a/apps/nightpass/templates/lmao.html b/apps/nightpass/templates/lmao.html index f9a5965..b971c66 100644 --- a/apps/nightpass/templates/lmao.html +++ b/apps/nightpass/templates/lmao.html @@ -120,6 +120,17 @@ + + diff --git a/apps/users/admin.py b/apps/users/admin.py index f82626b..a2da4bc 100644 --- a/apps/users/admin.py +++ b/apps/users/admin.py @@ -83,6 +83,7 @@ class StudentAdmin(ImportExportModelAdmin): autocomplete_fields = ('user',) resource_class = StudentResource readonly_fields = ('hostel_checkin_time', 'hostel_checkout_time', 'last_checkout_time',) + list_filter = ('hostel', 'has_booked', 'violation_flags') class SecurityAdmin(admin.ModelAdmin): list_display = ('name', 'admin_incharge', 'user') From 7f790ffaf8ccf6bcb790df82fbbed3a5bcbc982d Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Fri, 8 Dec 2023 18:30:47 +0530 Subject: [PATCH 66/69] Update notification text for nightpass facility --- apps/nightpass/templates/lmao.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/nightpass/templates/lmao.html b/apps/nightpass/templates/lmao.html index b971c66..5e4f89d 100644 --- a/apps/nightpass/templates/lmao.html +++ b/apps/nightpass/templates/lmao.html @@ -164,7 +164,7 @@ if (book) { document.getElementById('modal-resource-book').innerHTML = 'Book'; var urls = "book/" + name; - var notif_text = "Make sure you you use your slot else cancel before 8:00 PM. Not showing up at the location will lead to a defaulter record."; + var notif_text = "Make sure you use your slot else cancel before 8:00 PM. Not showing up at the location will lead to revocation of nightpass facility."; } else { document.getElementById('modal-resource-book').innerHTML = 'Cancel Booking' var urls = "cancel/"; From ac92f8b0f3a6abf12cca46ac1ad2d50ede1b7fee Mon Sep 17 00:00:00 2001 From: Pancham Agarwal Date: Fri, 8 Dec 2023 21:30:50 +0530 Subject: [PATCH 67/69] Add default incident view in nightpass home --- apps/nightpass/static/styles.css | 45 +++++++++++++++++++++++++++++- apps/nightpass/templates/lmao.html | 28 +++++++++++++++++++ apps/nightpass/views.py | 3 +- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/apps/nightpass/static/styles.css b/apps/nightpass/static/styles.css index 5aedf33..f2ea7b0 100644 --- a/apps/nightpass/static/styles.css +++ b/apps/nightpass/static/styles.css @@ -3,6 +3,7 @@ body { background-color: #f5f5f5; margin: 0; padding: 0; + line-height: 1.6; } .header { @@ -77,6 +78,10 @@ body { text-align: left; } +.profile-details p { + margin-bottom: 10px; +} + .safe { color: green; } @@ -201,6 +206,36 @@ select { align-items: center; } +.table-section { + margin-top: 10px; + overflow-x: auto; + /* Add horizontal scroll for small screens */ +} + +.activity-table { + width: 100%; + max-width: 100%; /* Set a maximum width for the table */ + border-collapse: collapse; + margin-top: 20px; + white-space: nowrap; /* Prevent text wrapping */ + overflow: hidden; +} + +.activity-table th, .activity-table td { + border: 1px solid #ddd; + padding: 8px; + text-align: left; + overflow: hidden; + text-overflow: ellipsis; /* Display ellipsis for overflowed text */ + white-space: wrap; +} + +.activity-table th { + background-color: #eb1b23; + color: #fff; +} + + @media (max-width: 768px) { .profile-card, .resource-card { @@ -212,4 +247,12 @@ select { justify-content: center; align-items: center; } -} \ No newline at end of file + + .activity-table { + font-size: 14px; + } + + .activity-table th, .activity-table td { + padding: 5px; + } +} diff --git a/apps/nightpass/templates/lmao.html b/apps/nightpass/templates/lmao.html index 5e4f89d..5658de9 100644 --- a/apps/nightpass/templates/lmao.html +++ b/apps/nightpass/templates/lmao.html @@ -120,6 +120,32 @@ +
+
+
+

Incident History

+ + + + + + + + + + {% for incident in user_incidents %} + + + + + + {% endfor %} + +
DateLocationRemarks
{{ incident.date }}{{ incident.campus_resource.name }}{{ incident.defaulter_remarks }}
+
+
+
+