<repo_name>deekshati/GetADoc-Flask<file_sep>/app/models.py
from app import db, login
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from datetime import datetime 

@login.user_loader
def load_user(id):
    if(id[0] == 'P'):
        return Patient.query.get(id)
    else:
        return Doctor.query.get(id)

class Patient(UserMixin, db.Model):
    id = db.Column(db.String(120), primary_key=True)
    full_name = db.Column(db.String(64), index=True)
    city = db.Column(db.String(20))
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(120))
    appointments = db.relationship('Appointment', backref='patient', lazy='dynamic')

    def __repr__(self):
        return '<Patient {}>'.format(self.full_name)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)


class Doctor(UserMixin, db.Model):
    id = db.Column(db.String(120), primary_key=True)
    full_name = db.Column(db.String(64), index=True)
    city = db.Column(db.String(20))
    qual = db.Column(db.String(20))
    fees = db.Column(db.Integer)
    phone = db.Column(db.Integer)
    address = db.Column(db.String(120))
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(120))
    appointments = db.relationship('Appointment', backref='doctor', lazy='dynamic')

    def __repr__(self):
        return '<Doctor {}>'.format(self.full_name)

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)


class Appointment(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    requested_date = db.Column(db.Date)
    appointment_date = db.Column(db.Date)
    appointment_time = db.Column(db.Time)
    doctor_id = db.Column(db.String(120), db.ForeignKey('doctor.id'))
    patient_id = db.Column(db.String(120), db.ForeignKey('patient.id'))
    reject_msg = db.Column(db.String(120))
    status = db.Column(db.Integer)<file_sep>/app/forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, SelectField, IntegerField, TextField
from wtforms.fields.html5 import DateField, TimeField, DateTimeField
from wtforms.validators import ValidationError, DataRequired, Email, Length, Optional
from app.models import Doctor, Patient

class LoginForm(FlaskForm):
    choice = SelectField('Are you a Patient or Doctor?', choices=['Patient', 'Doctor'])
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('<PASSWORD>', validators=[DataRequired()])
    remember_me = BooleanField('Remember me')
    submit = SubmitField('Log In')

class DoctorRegister(FlaskForm):
    name = StringField('Full Name', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('<PASSWORD>', validators=[DataRequired()])
    city = StringField('City', validators=[DataRequired()])
    phone = IntegerField('Phone No.', validators=[DataRequired()])
    address = StringField('Address', validators=[DataRequired()])
    qual = StringField('Qualifications', validators=[DataRequired()])
    fees = IntegerField('Fees per Person', validators=[DataRequired()])
    submit = SubmitField('Register')

    def validate_email(self, email):
        doctor = Doctor.query.filter_by(email=email.data).first()
        if doctor is not None:
            raise ValidationError('Email is already Registered!!')

class PatientRegister(FlaskForm):
    name = StringField('Full Name', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('<PASSWORD>', validators=[DataRequired()])
    city = StringField('City', validators=[DataRequired()])
    submit = SubmitField('Register')

    def validate_email(self, email):
        patient = Patient.query.filter_by(email=email.data).first()
        if patient is not None:
            raise ValidationError('Email is already Registered!!')

class AppointmentForm(FlaskForm):
    doctor_id = StringField('Doctor ID', validators=[Optional()])
    patient_id = StringField('Patient ID', validators=[Optional()])
    patient_name = StringField('Patient Name', validators=[DataRequired()])
    mobile = IntegerField('Mobile Number', validators=[DataRequired()])
    date = DateField('Enter Appointment Date', validators=[DataRequired()])
    submit = SubmitField('Submit Request Form', validators=[DataRequired()])

class confirmAppointment(FlaskForm):
    appoint_date = DateField("Appointment Date", validators=[DataRequired()])
    appoint_time = TimeField("Appointment Time", validators=[DataRequired()])
    submit = SubmitField("Confirm Appointment")

class rejectAppointment(FlaskForm):
    rejectMessage = TextField('Reject Message', validators=[DataRequired()])
    submit = SubmitField('Reject Appointment')
<file_sep>/getadoc.py
from app import app, db
from app.models import Patient, Doctor, Appointment

@app.shell_context_processor
def make_shell_context():
    return {'db': db, 'Patient': Patient, 'Doctor': Doctor, 'Appointment': Appointment}<file_sep>/migrations/versions/cbe32a1e2540_doctor_patients_table.py
"""Doctor & Patients table

Revision ID: cbe32a1e2540
Revises: 
Create Date: 2020-08-24 19:11:23.284040

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = '<KEY>'
down_revision = None
branch_labels = None
depends_on = None


def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('doctor',
    sa.Column('id', sa.String(length=120), nullable=False),
    sa.Column('full_name', sa.String(length=64), nullable=True),
    sa.Column('city', sa.String(length=20), nullable=True),
    sa.Column('qual', sa.String(length=20), nullable=True),
    sa.Column('fees', sa.Integer(), nullable=True),
    sa.Column('phone', sa.Integer(), nullable=True),
    sa.Column('address', sa.String(length=120), nullable=True),
    sa.Column('email', sa.String(length=120), nullable=True),
    sa.Column('password_hash', sa.String(length=120), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_doctor_email'), 'doctor', ['email'], unique=True)
    op.create_index(op.f('ix_doctor_full_name'), 'doctor', ['full_name'], unique=False)
    op.create_table('patient',
    sa.Column('id', sa.String(length=120), nullable=False),
    sa.Column('full_name', sa.String(length=64), nullable=True),
    sa.Column('city', sa.String(length=20), nullable=True),
    sa.Column('email', sa.String(length=120), nullable=True),
    sa.Column('password_hash', sa.String(length=120), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_patient_email'), 'patient', ['email'], unique=True)
    op.create_index(op.f('ix_patient_full_name'), 'patient', ['full_name'], unique=False)
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_patient_full_name'), table_name='patient')
    op.drop_index(op.f('ix_patient_email'), table_name='patient')
    op.drop_table('patient')
    op.drop_index(op.f('ix_doctor_full_name'), table_name='doctor')
    op.drop_index(op.f('ix_doctor_email'), table_name='doctor')
    op.drop_table('doctor')
    # ### end Alembic commands ###
<file_sep>/app/routes.py
from secrets import token_hex
from flask import render_template, url_for, redirect, flash, request
from app import app, db
from flask_login import current_user, login_user, logout_user, login_required
from app.forms import LoginForm, DoctorRegister, PatientRegister, AppointmentForm, confirmAppointment, rejectAppointment
from app.models import Patient, Doctor, Appointment
from werkzeug.urls import url_parse
from datetime import datetime

@app.route('/')
def home():
    date = datetime.utcnow()
    return render_template('home.html', date=date)

@app.route('/about')
@login_required
def about():
	return render_template('about.html')

@app.route('/finddoctor')
@login_required
def finddoctor():
    doctors = Doctor.query.filter_by(city=current_user.city).all()
    return render_template('doctorlist.html', doclist=doctors)

@app.route('/book/<Did>', methods=['GET', 'POST'])
@login_required
def book(Did):
    app = Appointment(doctor_id=Did, patient_id=current_user.id)
    form = AppointmentForm(obj=app)
    if form.validate_on_submit():
        appoint = Appointment(requested_date=form.date.data, doctor_id=form.doctor_id.data, patient_id=form.patient_id.data, status=0)
        db.session.add(appoint)
        db.session.commit()
        flash('Congratulations, your appointment is successfully booked!')
        return redirect(url_for('home'))
    return render_template('bookdoctor.html', form=form)

@app.route('/myappointments')
@login_required
def myappointments():
    if(current_user.id[0] == 'P'):
        pending_data = Appointment.query.filter_by(patient_id=current_user.id, status=0).all()
        confirmed_data = Appointment.query.filter_by(patient_id=current_user.id, status=1).all()
        rejected_data = Appointment.query.filter_by(patient_id=current_user.id, status=-1).all()
        return render_template('pat_appointment.html', confirm=confirmed_data, pending=pending_data, reject=rejected_data)
    else:
        pending_data = Appointment.query.filter_by(doctor_id=current_user.id, status=0).all()
        confirmed_data = Appointment.query.filter_by(doctor_id=current_user.id, status=1).all()
        #print(pending_data)
        return render_template('doc_appointment.html', confirm=confirmed_data, pending=pending_data)
    

@app.route('/confirmappointment/<aid>', methods=['GET', 'POST'])
@login_required
def confirmappointment(aid):
    app = Appointment.query.filter_by(id=aid).first()
    if(current_user.id[0] == 'P'):
        return redirect(url_for('home'))
    form = confirmAppointment()
    if form.validate_on_submit():
        app.appointment_date = form.appoint_date.data
        app.appointment_time = form.appoint_time.data
        #print(app.appointment_date, app.appointment_time)
        app.status = 1
        db.session.commit()
        return redirect(url_for('myappointments'))
    return render_template('confirm.html', form=form, request = app.requested_date)

@app.route('/rejectappointment/<aid>', methods=['GET', 'POST'])
@login_required
def rejectappointment(aid):
    app = Appointment.query.filter_by(id=aid).first()
    if(current_user.id[0] == 'P'):
        return redirect(url_for('home'))
    form = rejectAppointment()
    if form.validate_on_submit():
        app.reject_msg = form.rejectMessage.data
        app.status = -1
        db.session.commit()
        return redirect(url_for('myappointments'))
    return render_template('reject.html', form=form)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('home'))
    form = LoginForm()
    if form.validate_on_submit():
        if(form.choice.data == 'Patient'):
            daba = Patient
        else:
            daba = Doctor
        user = daba.query.filter_by(email=form.email.data).first()
        if user is None or not user.check_password(form.password.data):
            flash('Invalid Username or Password')
            return redirect(url_for('login'))
        login_user(user, remember=form.remember_me.data)
        next_page = request.args.get('next')
        if not next_page or url_parse(next_page).netloc != '':
            next_page = url_for('home')
        return redirect(next_page)
    return render_template('login.html', form=form)

@app.route('/register/<choice>', methods=['GET', 'POST'])
def register(choice):
    if current_user.is_authenticated:
        return redirect(url_for('home'))
    idd = token_hex(16)
    if(choice=='doctor'):
        idd = 'D'+idd
        form = DoctorRegister()
        if form.validate_on_submit():
            user = Doctor(id = idd, full_name=form.name.data, email=form.email.data, city=form.city.data, phone=form.phone.data, address=form.address.data, qual=form.qual.data, fees=form.fees.data)
            user.set_password(form.password.data)
            db.session.add(user)
            db.session.commit()
            flash('Congratulations, you are now a registered user!')
            return redirect(url_for('login'))
    else:
        idd = 'P'+idd
        form = PatientRegister()
        if form.validate_on_submit():
            user = Patient(id=idd, full_name=form.name.data, email=form.email.data, city=form.city.data)
            user.set_password(form.password.data)
            db.session.add(user)
            db.session.commit()
            flash('Congratulations, you are now a registered user!')
            return redirect(url_for('login'))
    
    return render_template('register.html', choice=choice, form=form)

@app.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('home'))