CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i...
Transcript of CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i...
![Page 1: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/1.jpg)
CPSC 471 Final Report
eBooking Database Management System for
Clinics
Justin Karlo Flores
Nathaniel Habtegergesa
![Page 2: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/2.jpg)
Table of Contents
CPSC 471 Final Report 1
eBooking Database Management System for Clinics 1
Table of Contents 2
Abstract 3
Introduction 4
System Features 4
Authentication 5
Patient Page 6
Booking Appointment 7
Cancelling Appointment 8
Extended Entity Relational Model 8
Relational Model 8
PostgreSQL 9
User Manual for the Front End Application 14
Appendix 24
References 24
![Page 3: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/3.jpg)
![Page 4: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/4.jpg)
Abstract
Managing appointments in clinic settings is a complex process. We
implemented an eBooking Database Management System for clinics to solve this
problem. We were able to successfully implement this application in:
● Database Client: PGCLI, PGADMIN
● Backend: Node.js, Express.js
● Frontend: jQuery, Bootstrap, Dust
● Other: Docker, AWS RDS, AWS EC2, consolidate
This allows the patients to interact through a web interface to schedule and manage
medical appointments online. Through this application we can provide users 24/7
service and save clinics from wasting necessary resources on an old system proven
to be ineffective. This system will be designed to keep the records of the patients,
doctors, and allow patients to schedule or enter new appointments, store the result
of an appointment, cancel any existing appointments and see any openings for the
day, week or month with their preferred doctor! We are not going to replace
receptionist but aid them in being more efficient, and for patients, it’s a much more
effective way to book and cancel appointments. With this, we can solve several
problems, that we’ll delve into more detail later.
![Page 5: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/5.jpg)
Introduction
For the longest time and even now, most clinics use receptionist to book
appointments for patients, rebook appointments, remind patients of their
appointments, and cancel appointments. Managing appointments is a complex
process and this process of managing appointments for a patient causes no-shows,
longer wait times (due to high call volumes), and cancelled appointments, which are
costly and unfortunately a reality for many healthcare providers in Canada. In 2014,
90% of surveyed Canadians expressed a desire for online appointment booking, yet
only 7% of Canadian family physicians offered it. This falls far below the 66% of
Swedish physicians and 30% of American physicians who offer online appointment
requests (2012). To better support clinicians we are seeking to fill that gap and offer
an eBooking service for clinics to offer their patients. This system seeks to reduce
the burden on clinics and to aid patients in choosing, cancelling and making an
online appointment for a specific doctor just by sitting at home! Our second objective
was to facilitate clinics with the amount of manual single data entry from a middle
man and give greater efficiency and flexibility for both the patient and clinic side. So,
this eBooking system represents a win-win situation for both patients and clinics.
System Features
The main emphasis around our project was around patients. We thought this
would be the best approach at attacking the core problems around clinics and their
insane workload. So we designed this system to increase work efficiency and overall
![Page 6: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/6.jpg)
satisfactory for everyone involved. Through this web interface patients will also be
able to cancel, view and book with a doctor of their preference. For a better
understanding we are going to delve into more detail of the components that make
up our system design.
Authentication
Patients are required to sign up or login if they don't already have an account.
For signups we require:
● First name
● Last name
● Alberta Personal Health Care Card
● And Password
All fields are required for authentication. We ensure validation of passwords with a
confirm password field. We are also requiring valid inputs for all fields. We’ll delve
into further detail on how we authenticate a user once he logs in.
COOKIE-BASED AUTHENTICATION
Upon user validation during signup if the request is granted i.e. if the user details are
correct then a user session is created. This user session will be unique and given to
the client through the browser. Now on each subsequent request, the browser will
present this session and then it’s verified against the database. Based on the
session_id (user_id), the website will identify the session belonging to the client and
give access to the request(s). Every time you do any requests to the server, it will
![Page 7: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/7.jpg)
check the cookie header file for the user_id and make sure it matches with the id in
the request parameter. When user logs in, we redirect a user to his/her own specific
page with their user_id as the session_id cookie. Nice thing about this as well is,
another client once logged in, can’t simply try to redirect to get access to another
session. Once logged out the session is then destroyed both server and client-side.
HASHED PASSWORDS
The passwords were not stored in plaintext. This was to add an additional layer of
security and prevent any potential attackers which have gotten through the
authentication stage, from simply reading the passwords and having access to any
user data.
Patient Page
Once the patient has logged into their account, they are redirected to a calendar
page which shows all the available appointments that are not booked, and they will
also see their own appointments. The system achieves this by sending a GET
request to a route in the server and the server will build the query and send that to
the DB server. Once the query is over the database will send the results back to the
server, which the server will relay to the client-side, but before that, the server adds
extra attributes to each row so that it is in a proper event object format, and ready to
be displayed in the frontend page. The booked and available appointments are
shown properly in the proper spot in the calendar by checking their date, start and
end time, which will also be available for the users to see. For each displayed
appointment, the patient can see details about it, such as the name of the clinic,
![Page 8: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/8.jpg)
address, and the doctor. The appointments booked by the user are shown as blue,
and the available appointments are shown as green.
Booking Appointment
If the user clicks on an available appointment, a pop-up box will appear showing all
the appointment details, and at the bottom of the pop-up box, there is a “Book”
button. If the patient clicks the button, it will send a POST request to a route in our
server. Once the POST request reaches the route in the server, the server checks
for authentication and then proceeds to build a template and send that to the DB
server along with the body of the request which contains the necessary info to
INSERT to our APPOINTMENT table. Once the request reaches the DB, it then
unpacks the request body into a proper parameter object since our queries uses
parametrize querying. How the query works is that it checks other appointments with
that doctor and make sure that there is no overlap between the start times and end
times, it will also check the other appointments of the patient and make sure no
overlaps occur. Lastly, the booking will also find available rooms in the clinic which is
done by checking other appointments in that clinic and make sure there are no
overlaps. Once the query is done, the DB will send its response, which the server will
relay to client-side. The client-side will look at the response’s rowCount to determine
if the booking/insert is successful. If the insert is successful then the client side
proceeds on changing some of the attributes of that appointment in the front-end so
that it displays properly. When it is not successful, then an error message will pop-up
in the pop-up box which will tell the user that the insert/booking was not successful.
![Page 9: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/9.jpg)
Cancelling Appointment
If the user clicks on the appointment they already booked, a modal will appear showing the
appointment details and a button to cancel the appointment. When “Cancel Appointment” is
clicked, a DELETE request is sent to a specific route in the server. The request is first
checked for authentication, and when it passes, it will proceed to the function that queries a
DELETE in the Appointment table. Once the query is done, the DB will send a response to
the server, and the server will relay the response to the client-side. The client-side will check
the response message, specifically, the rowCount which tells us if the appointment was
deleted successfully. If there was an error, then an error message will pop-up giving the user
some info about the error without showing critical info about the system. In the case where it
is successful, then the client-side will change some attributes in the event object that
represents the appointment so that it has the attributes and look of an available appointment.
Changes Made (Diagrams at the end of report)
We decided to remove the E-Booking entity and Contract entity as we decided that
we want to add more features to the patient side of the app, instead of the
business/clinic side of it. The reason on focusing more on the patient side is because
this app was made to make it easier for patients to book appointments and
encourage them to book an appointment when they feel something is not right with
their body. Also, it was very unrealistic since we do not have the time and resources
to support the whole business end to make keeping contracts relevant. If we kept,
only the admin would be able to interact with this entity completely out of the whole
![Page 10: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/10.jpg)
system. We removed some redundancy of few attributes that we found to be
unnecessary.
PostgreSQL
PostgreSQL, also known as Postgres, is a free and open-source relational
database management system emphasizing extensibility and technical standards
compliance. Postgres was our first choice for this project because we thought of
using PostgreSQL’s features and it has a lot of support online. PostgreSQL features
a pretty robust set of operators and functions for testing, comparing, manipulating,
and converting arrays. One of those features that we found to be particularly helpful
was it’s ease of making functions. The backend of our system mainly acts as routers
which decides which queries to send to our PostgreSQL server. The backend
receives an HTTP request from the client-side, which contains the necessary
parameters for the query need and also the route, which identifies what query to use.
We also found PostgresSQL’s pgAdmin tool to be have a fairly complete and yet
easy to use GUI. This turned out to be pretty useful and helped us increase our
efficiency.
Additionally we used a “knex”. Knex is query builder which prevents SQL injection
attacks and for passing values as a parameter, we used parameter binding so the
query string was passed separately to the database driver for protecting queries from
SQL injection.
![Page 11: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/11.jpg)
Here's a list of all our SQL query statements:
const knex = require('./knex'); // the database connection module.exports = { getAllUsers() { return knex('users'); }, getUserByID(id) { return knex('users').where('userid', id).first(); }, getAllUserEmail(email) { return knex('users').where('email', email); }, getOneByEmail: function (email) { return knex('users').where('email', email).first(); }, addUser(user) { return knex('users').insert(user); }, addUser2(user) { const params = { fname: user.fname, lname: user.lname, email: user.email, password: user.password, health_c: user.health_care } return knex.raw('WITH new_userID as (\ INSERT INTO "users" (fname, lname, email, password, health_care)\ VALUES (:fname, :lname, :email, :password, :health_c)\ RETURNING userid\ ), new_patientID as (\ INSERT INTO "patient" (userid)\
![Page 12: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/12.jpg)
SELECT newID.userid\ FROM new_userID as newID\ RETURNING userid\ )\ INSERT INTO "records" (p_userid)\ SELECT newID.userid\ FROM new_patientID as newID', params) }, addAdmin(username, password) { const admin_info = { username: username, password: password } return knex('admin').insert(admin_info) }, updateDOB(id, date) { return knex('users').where('userid', id).update({ dob: date }) }, async getAllDoc() { try { res = await knex.raw('SELECT d.userid, u.lname, u.fname \ FROM doctor AS d, users AS u WHERE d.userid = u.userid;') console.log(res.rows) return res.rows } catch (error) { throw error } }, getAllAvailableApt() { return knex.raw('SELECT u.fname AS doctor_fname, u.lname AS doctor_lname, \ doc.userid AS doc_id, doc.start_time AS start, doc.end_time AS end, \ clin.clinic_id AS clinic_id, clin.name AS clinic_name, clin.street AS street,\ clin.city AS city, clin.province AS province\ FROM "availabilities" as doc, "users" as u, "clinic" as clin, \
![Page 13: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/13.jpg)
"doctor" as dc\ WHERE doc.userid = u.userid AND dc.clinic_id = clin.clinic_id \ AND doc.userid = dc.userid\ AND NOT EXISTS (SELECT * FROM "appointment" as apt \ WHERE apt.doctor_id = doc.userid \ AND ((doc.start_time, doc.end_time)OVERLAPS(apt.start_time, apt.end_time)));') }, getAllApt(id) { try { let result = knex.raw('SELECT u.fname AS doctor_fname, u.lname AS doctor_lname, doctor_id AS doc_id, \ a.start_time AS start, a.end_time as end, \ clin.clinic_id AS clinic_id, clin.name AS clinic_name, clin.street AS street,\ clin.city AS city, clin.province AS province\ FROM "appointment" as a, "users" as u, "clinic" as clin, "room" as r\ WHERE a.patient_id = ?\ AND a.doctor_id = u.userid\ AND a.room_id = r.room_number\ AND r.clinic_id = clin.clinic_id', [id]) return result } catch (error) { throw error } }, addApt(id, apt) { try { let params = { dID: parseInt(apt.doctor_id), uID: parseInt(id), startT: apt.start_time, endT: apt.end_time, reas: apt.reason, cID: apt.clinic_id } console.log(params)
![Page 14: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/14.jpg)
let result = knex.raw('WITH AVAILABLE_ROOM(rID)\ AS\ (SELECT room.room_number\ FROM "room" AS room\ WHERE room.clinic_id = :cID\ AND room.room_number NOT IN(SELECT apt.room_id\ FROM "appointment" AS apt\ WHERE (apt.start_time, apt.end_time) OVERLAPS (:startT, :endT))\ LIMIT 1\ )\ \ INSERT INTO "appointment" (doctor_id, patient_id, start_time, end_time, room_id, reason)\ SELECT :dID, :uID, :startT, :endT, ab.rID, :reas\ FROM AVAILABLE_ROOM as ab\ WHERE NOT EXISTS (SELECT * FROM "appointment" AS apt\ WHERE (apt.doctor_id = :dID\ AND apt.start_time = :startT\ AND apt.end_time = :endT)\ OR (apt.patient_id = :uID\ AND (apt.start_time,apt.end_time)\ OVERLAPS (:startT, :endT))\ )', params); return result } catch (error) { throw error } }, deleteApt(id, apt) { try { let params = { dID: parseInt(apt.doctor_id), uID: id, startT: apt.start_time, endT: apt.end_time }
![Page 15: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/15.jpg)
let result = knex.raw('DELETE FROM "appointment" \ WHERE doctor_id = :dID\ AND patient_id = :uID\ AND start_time = :startT\ AND end_time = :endT', params) return result } catch (error) { throw error } } }
User Manual for the Front End Application
Upon initializing the website, the user is presented with the following login page
If the user does not have an account already, there’s a sign up button for the user to
reference
![Page 16: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/16.jpg)
This button should link the user to another webpage where one is then asked to fill
the necessary required fields
If the user attempts to sign up with an email that already exists, he is prompted with
a warning
![Page 17: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/17.jpg)
OR if a user enters passwords that’s too short, he is prompted with an invalid user
message
OR if a user enters passwords that don’t match he/she is warned once again
![Page 18: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/18.jpg)
Once the user successfully meets all the correct sign up requirements one would
then successfully be added to the database and redirected to login once again with
their now existing information. For an extra layer of security we also hashed the
users passwords.
![Page 19: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/19.jpg)
The same restrictions are in play again, we sanitized inputs through our back end
and restricted invalid inputs through our front end as well to ensure no vulnerabilities.
Finally once the user is successfully authenticated, they will then be redirected using
a cookie to ensure secure redirect
Now, the user is presented with a presented with an interactive calendar where
he/she will be able to book, cancel, and dynamically view their appointment by day,
week, month or even as a list of events! They would also be able to filter their
appointments and filter the weekends out of their view as well, and with today's date
highlighted
![Page 20: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/20.jpg)
![Page 21: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/21.jpg)
They also have the option to print they’re view as well, to keep a physical copy of
their schedule
To book, one would simply need to click on an appointment they would like to book
and give
![Page 22: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/22.jpg)
And hit book!
![Page 23: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/23.jpg)
The process goes for appointment cancellations
![Page 24: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/24.jpg)
And that concludes how a user can interactively create, read, update, and delete
Appendix
![Page 25: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/25.jpg)
![Page 26: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/26.jpg)
References
https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4288107/
https://www.theseus.fi/bitstream/handle/10024/152390/Tufail_Maryam.pdf?sequence
=1&isAllowed=y
https://www.academia.edu/32409989/Clinic_Appointment_System
https://iamsickblog.wordpress.com/2015/08/21/e-booking-case-study/
https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web
_server
![Page 27: CPSC 471 Final Report - Nathaniel Habtegergesa 471 Final R… · CPSC 471 Final Report 1 e Bo o k i n g Da ta b a s e Ma n a g e me n t S y s te m fo r Cl i n i c s 1 Table of Contents](https://reader033.fdocuments.in/reader033/viewer/2022051900/5fee8dd26ae7115c87267717/html5/thumbnails/27.jpg)
Use of Communication: Facebook, GitHub, Trello
DB Schema Queries: In the .sql file with this submission.