<repo_name>RobertPecz/PatientRegistry<file_sep>/UserInput.py
import re
from datetime import *


class UserInput:
    """Patient registry input by the user"""

    def __init__(self):
        self.FirstName = None
        self.LastName = None
        self.Dob = None
        self.Phone_number = None
        self.AppointmentDate = None
        self.AppointmentTime = None
        self.MotherMaidenName = None

    def safe_cast(self,val,to_type, default=None):
        try:
            return to_type(val)
        except (ValueError, TypeError):
            return default

    def adding_new_patient(self):
        # Adding a new customer

        # Adding the first name
        print("Please provide the following data's: First name, Last name, Age, Phone number, Appointment date")
        is_match = None
        while is_match is None:
            self.FirstName=input("First name:")
            is_match = re.fullmatch(r"^([A-Z][a-z]{0,})?(?(1)([ ][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[ ][A-Z][a-z]{0,}|[ ][A-Z][.]|[.][ ][A-Z][a-z]{0,}|)|NOTVALID)$", self.FirstName)
            if is_match is None:
                print("Please provide the first name in correct format (eg.:'Smith' or 'Smith-Black' or 'Smith Black')")

        # Adding the last name
        is_match = None
        while is_match is None:
            self.LastName=input("Last Name:")
            is_match = re.fullmatch(r"^([A-Z][a-z]{0,})?(?(1)([.][ ][A-Z][a-z]{0,}[.][ ][A-Z][a-z]{0,}|[.][ ][A-Z][a-z]{0,}[.][ ][A-Z][a-z]{0,}[-][A-Z][a-z]{0,}|[.][ ][A-Z][a-z]{0,}[.]|[.][ ][A-Z][a-z]{0,}[-][A-Z][a-z]{0,}|[.][ ][A-Z][a-z]{0,}|[-][A-Z][a-z]{0,})|[A-Z][a-z]{0,})$", self.LastName)
            if is_match is None:
                print("Please provide the first name in correct format (eg.:'John' or 'J.' or '<NAME>')")

        # Adding the Date of birth
        is_match = None
        while is_match is None:
            self.Dob = input("Date of Birth (correct format: 1900-01-01):")
            is_match = re.fullmatch(r"^[1-2][0-9]{3}[-][0-1][0-9]{1}[-][0-9]{2}$", self.Dob)
            try:
                dob_date = datetime.strptime(self.Dob, '%Y-%m-%d')
            except ValueError:
                print("Please provide a valid date between 01-01 and 12-31.")
                continue
            if dob_date < datetime(year=1900, month=1, day=1) or dob_date >= datetime.now():
                is_match = None
                print("Please provide the date at least today")
            if is_match is None:
                print("Please provide a correct date format (1900-01-01).")

        # Adding the mother maiden name
        is_match = None
        while is_match is None:
            self.MotherMaidenName = input("Mother Maiden name (correct format: Sue Doe or Sue Doe-Black or Sue Doe Black or Sue D. Black.):")
            is_match = re.fullmatch(r"^([A-Z][a-z]{0,})?(?(1)([ ][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[-][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[ ][A-Z][a-z]{0,}|[ ][A-Z][.][ ][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[ ][A-Z][.])|NOTVALID)$", self.MotherMaidenName)
            if is_match is None:
                print("Please provide the mother maiden name in a correct form eg.: <NAME> or <NAME>-Black or <NAME> or <NAME>")

        # Adding the phone number
        is_match = None
        while is_match is None:
            self.Phone_number = input("Phone number(correct format: +36-00-000-0000):")
            is_match = re.fullmatch(r"^[+][3][6][-][0-9]{2}[-][0-9]{3}[-][0-9]{4}$", self.Phone_number)
            if is_match is None:
                print("Please provide a correct phone number format (+36-00-000-0000).")

        # Adding the appointment date and time
        is_match = None
        while is_match is None:
            self.AppointmentDate = input("Appointment Date (correct format: 1900-01-01):")
            is_match = re.fullmatch(r"^[2][0-9]{3}[-][0-1][0-9]{1}[-][0-9]{2}$", self.AppointmentDate)
            try:
                self.AppointmentDate = datetime.strptime(self.AppointmentDate, '%Y-%m-%d')
            except ValueError:
                print("Please provide a valid date between 01-01 and 12-31.")
                continue
            if self.AppointmentDate < datetime.now() - timedelta(days=1):
                is_match = None
                print("Please provide the date at least today")
            if is_match is None:
                print("Please provide a correct date format (1900-01-01).")

            self.AppointmentTime = input("Appointment time (correct format: 00:00):")
            is_match = re.fullmatch(r"^[0-9]{2}[:][0-9]{2}$", self.AppointmentTime)
            start_time = time(hour=8, minute=0)
            end_time = time(hour=16, minute=0)
            try:
                self.AppointmentTime = datetime.strptime(self.AppointmentTime, '%H:%M').time()
                self.AppointmentDate = datetime.combine(self.AppointmentDate, self.AppointmentTime)
            except ValueError:
                print("Please provide a valid time between 08:00 and 16:00")
                is_match = None
                continue
            if self.AppointmentTime < start_time or self.AppointmentTime > end_time:
                is_match = None
                print("Please provide a valid time between 08:00 and 16:00")
            if is_match is None:
                print("Please provide a correct time format (08:00).")

    def change_first_name(self):
        # Changing the first name
        print("Please provide first name.")
        is_match = None
        while is_match is None:
            self.FirstName = input("First name:")
            is_match = re.fullmatch(r"^([A-Z][a-z]{0,})?(?(1)([ ][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[ ][A-Z][a-z]{0,}|[ ][A-Z][.]|[.][ ][A-Z][a-z]{0,}|)|NOTVALID)$", self.FirstName)
            if is_match is None:
                print("Please provide the first name in correct format (eg.:'Smith' or 'Smith-Black' or 'Smith Black')")

        return self.FirstName

    def change_last_name(self):
        # Changing the last name
        print("Please provide last name.")
        is_match = None
        while is_match is None:
            self.LastName = input("Last Name:")
            is_match = re.fullmatch(r"^([A-Z][a-z]{0,})?(?(1)([.][ ][A-Z][a-z]{0,}[.][ ][A-Z][a-z]{0,}|[.][ ][A-Z][a-z]{0,}[.][ ][A-Z][a-z]{0,}[-][A-Z][a-z]{0,}|[.][ ][A-Z][a-z]{0,}[.]|[.][ ][A-Z][a-z]{0,}[-][A-Z][a-z]{0,}|[.][ ][A-Z][a-z]{0,}|[-][A-Z][a-z]{0,})|[A-Z][a-z]{0,})$", self.LastName)
            if is_match is None:
                print("Please provide the first name in correct format (eg.:'John' or 'J.' or '<NAME>')")

        return self.LastName

    def change_dob(self):
        # Changing the Date of birth
        print("Provide the date of birth.")
        is_match = None
        while is_match is None:
            self.Dob = input("Date of Birth (correct format: 1900-01-01):")
            is_match = re.fullmatch(r"^[1-2][0-9]{3}[-][0-1][0-9]{1}[-][0-9]{2}$", self.Dob)
            try:
                dob_date = datetime.strptime(self.Dob, '%Y-%m-%d')
            except ValueError:
                print("Please provide a valid date between 01-01 and 12-31.")
                continue
            if dob_date < datetime(year=1900,month=1,day=1) or dob_date >= datetime.now():
                is_match = None
                print("Please provide the date at least today")
            if is_match is None:
                print("Please provide a correct date format (1900-01-01).")

        return self.Dob

    def change_mother_maiden_name(self):
        # Changing mother maiden name.
        print("Provide mother maiden name.")
        is_match = None
        while is_match is None:
            self.MotherMaidenName = input("Mother Maiden name (correct format: Sue Doe or Sue Doe-Black or Sue Doe Black or Sue D. Black.):")
            is_match = re.fullmatch(r"^([A-Z][a-z]{0,})?(?(1)([ ][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[-][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[ ][A-Z][a-z]{0,}|[ ][A-Z][.][ ][A-Z][a-z]{0,}|[ ][A-Z][a-z]{0,}[ ][A-Z][.])|NOTVALID)$", self.MotherMaidenName)
            if is_match is None:
                print("Please provide the mother maiden name in a correct form eg.: <NAME> or <NAME>-Black or <NAME> or <NAME>")

        return self.MotherMaidenName

    def change_phonenumber(self):
        # Changing phone number.
        print("Provide phone number.")
        is_match = None
        while is_match is None:
            self.Phone_number = input("Phone number(correct format: +36-00-000-0000):")
            is_match = re.fullmatch(r"^[+][3][6][-][0-9]{2}[-][0-9]{3}[-][0-9]{4}$", self.Phone_number)
            if is_match is None:
                print("Please provide a correct phone number format (+36-00-000-0000).")

        return self.Phone_number

    def change_appointment_date(self):
        # Change appointment date and time
        is_match = None
        while is_match is None:
            self.AppointmentDate = input("Appointment Date (correct format: 1900-01-01):")
            is_match = re.fullmatch(r"^[2][0-9]{3}[-][0-1][0-9]{1}[-][0-9]{2}$", self.AppointmentDate)
            try:
                self.AppointmentDate = datetime.strptime(self.AppointmentDate, '%Y-%m-%d')
            except ValueError:
                print("Please provide a valid date between 01-01 and 12-31.")
                continue
            if self.AppointmentDate < datetime.now() - timedelta(days=1):
                is_match = None
                print("Please provide the date at least today")
            if is_match is None:
                print("Please provide a correct date format (1900-01-01).")

            self.AppointmentTime = input("Appointment time (correct format: 00:00):")
            is_match = re.fullmatch(r"^[0-9]{2}[:][0-9]{2}$", self.AppointmentTime)
            start_time = time(hour=8, minute=0)
            end_time = time(hour=16, minute=0)
            try:
                self.AppointmentTime = datetime.strptime(self.AppointmentTime, '%H:%M').time()
                self.AppointmentDate = datetime.combine(self.AppointmentDate, self.AppointmentTime)
            except ValueError:
                print("Please provide a valid time between 08:00 and 16:00")
                is_match = None
                continue
            if self.AppointmentTime < start_time or self.AppointmentTime > end_time:
                is_match = None
                print("Please provide a valid time between 08:00 and 16:00")
            if is_match is None:
                print("Please provide a correct time format (08:00).")

        return self.AppointmentDate
<file_sep>/PatientModify.py
from SearchCustomer import *
from UserInput import *
from DatabaseConnection import *


class PatientModding:
    """Modifying a Patient include add, modify appoint date, delete appointment"""

    def __init__(self):
        self.firstName = None
        self.lastName = None
        self.dateOfBirth = None
        self.phoneNumber = None
        self.motherMaidenName = None
        self.appointmentDate = None
        self.pastAppointments = None
        self.pastIsAppear = None

    # Adding data to the class
    def upload_all_data(self,first_name, last_name, date_of_birth, mother_maiden_name, phone_number, appointment_date, past_is_appear):
        self.firstName = first_name
        self.lastName = last_name
        self.dateOfBirth = date_of_birth
        self.motherMaidenName = mother_maiden_name
        self.phoneNumber = phone_number
        self.appointmentDate = appointment_date
        self.pastAppointments = appointment_date
        self.pastIsAppear = past_is_appear

    def adding_customer(self):
        # Upload a customer to the tables

        # Connect to the database
        cnxn, cursor = ConnectingToDatabase.connect_database(self)

        # Select the last PK ID from Patient table and +1 to it.
        id_last_number_query_patient = "SELECT TOP 1 ID FROM Patient ORDER BY ID Desc;"
        cursor.execute(id_last_number_query_patient)
        row = cursor.fetchone()
        id_number_patient = row[0]+1

        # Select the last PK ID from PastAppointments table and +1 to is
        id_last_number_query_patient = "SELECT TOP 1 ID FROM PastAppointments ORDER BY ID Desc;"
        cursor.execute(id_last_number_query_patient)
        row = cursor.fetchone()
        id_number_pastappointments = row[0]+1

        # Input the customer data and validate that the patient is not in the table
        search_customer_duplicate_checker = SearchingCustomer()
        is_customer_in_table = search_customer_duplicate_checker.search_customer_duplicate_checker()

        # Adding user data to this class variables
        self.upload_all_data(search_customer_duplicate_checker.firstName,
                             search_customer_duplicate_checker.lastName,
                             search_customer_duplicate_checker.dateOfBirth,
                             search_customer_duplicate_checker.motherMaidenName,
                             search_customer_duplicate_checker.phoneNumber,
                             search_customer_duplicate_checker.appointmentDate,
                             "No")

        # If the customer not find in the table inserting to the patient table
        if is_customer_in_table is None:
            # Insert Patient data's into the Patient table
            query_insert = "INSERT INTO Patient(ID, FirstName, LastName, DateOfBirth, MotherMaidenName, PhoneNumber, AppointmentDate) VALUES(?,?,?,?,?,?,?);"
            cursor.execute(query_insert, id_number_patient, self.firstName, self.lastName, self.dateOfBirth, self.motherMaidenName, self.phoneNumber, self.appointmentDate)
            cnxn.commit()

            # Select PK ID Where the firstname and lastname which is passed as variable
            id_current_query = "SELECT ID FROM Patient WHERE FirstName=? and LastName=?;"
            cursor.execute(id_current_query, self.firstName, self.lastName)
            row = cursor.fetchone()
            id_current_query = row[0]

            # Insert the past appointments to the PastAppointments table set the Isappear column default to No.
            query_insert = "INSERT INTO PastAppointments(ID, PatientID, PastAppTime, IsAppear) VALUES(?,?,?,?);"
            cursor.execute(query_insert, id_number_pastappointments, id_current_query, self.pastAppointments, self.pastIsAppear)
            cnxn.commit()

        # If the customer is in the table a message shown that the patient is registered
        else:
            print("Patient is already registered.")

    def modifying_first_name(self):
        # Change the first name and update in the table
        search = SearchingCustomer()
        customer = search.search_customer()
        if customer is not None:
            change_first_name = UserInput()
            change_name = change_first_name.change_first_name()
            cnxn, cursor = ConnectingToDatabase.connect_database(self)
            query_mod_first_name = "UPDATE Patient SET FirstName=? WHERE ID=?;"
            cursor.execute(query_mod_first_name,change_name,customer)
            cnxn.commit()

    def modifying_last_name(self):
        # Change the last name and update in the table
        search = SearchingCustomer()
        customer = search.search_customer()
        if customer is not None:
            change_last_name = UserInput()
            change_name = change_last_name.change_last_name()
            cnxn, cursor = ConnectingToDatabase.connect_database(self)
            query_mod_last_name = "UPDATE Patient SET LastName=? WHERE ID=?;"
            cursor.execute(query_mod_last_name,change_name, customer)
            cnxn.commit()

    def modifying_phone_number(self):
        # Change the phone number and update in the table
        search = SearchingCustomer()
        customer = search.search_customer()
        if customer is not None:
            change_phone_number = UserInput()
            change_pnumber = change_phone_number.change_phonenumber()
            cnxn, cursor = ConnectingToDatabase.connect_database(self)
            query_mod_phone_number = "UPDATE Patient SET PhoneNumber=? WHERE ID=?;"
            cursor.execute(query_mod_phone_number, change_pnumber, customer)
            cnxn.commit()

    def modifying_dob(self):
        # Change the date of birth and update in the table
        search = SearchingCustomer()
        customer = search.search_customer()
        if customer is not None:
            change_date_of_birth = UserInput()
            change_dob = change_date_of_birth.change_dob()
            cnxn, cursor = ConnectingToDatabase.connect_database(self)
            query_mod_dob = "UPDATE Patient SET DateOfBirth=? WHERE ID=?;"
            cursor.execute(query_mod_dob, change_dob, customer)
            cnxn.commit()

    def modifying_mother_maiden_name(self):
        # Change mother maiden name and update in the table
        search = SearchingCustomer()
        customer = search.search_customer()
        if customer is not None:
            change_mother_maiden_name = UserInput()
            change_mothername = change_mother_maiden_name.change_mother_maiden_name()
            cnxn, cursor = ConnectingToDatabase.connect_database(self)
            query_mod_mother_maiden_name = "UPDATE Patient SET MotherMaidenName=? WHERE ID=?;"
            cursor.execute(query_mod_mother_maiden_name, change_mothername, customer)
            cnxn.commit()

    def modifying_appointment_date(self):
        # Change appointment date and update in the table
        search = SearchingCustomer()
        customer = search.search_customer()
        if customer is not None:
            change_appointment_date = UserInput()
            change_appointmentdate = change_appointment_date.change_appointment_date()
            cnxn, cursor = ConnectingToDatabase.connect_database(self)
            query_mod_appointment_date = "UPDATE Patient SET AppointmentDate=? WHERE ID=?;"
            cursor.execute(query_mod_appointment_date, change_appointmentdate, customer)
            cnxn.commit()
<file_sep>/DatabaseConnection.py
import pyodbc


class ConnectingToDatabase:
    # Connecting to a database

    def connect_database(self):
        # Connect to the database
        cnxn = pyodbc.connect("Driver={SQL Server Native Client 11.0};"
                              "Server=.\SQLEXPRESS;"
                              "Database=PatientRegistry;"
                              "Trusted_Connection=yes;")

        cursor = cnxn.cursor()
        return cnxn, cursor
<file_sep>/SearchCustomer.py
from DatabaseConnection import *
from UserInput import *


class SearchingCustomer:

    def __init__(self):
        self.firstName = None
        self.lastName = None
        self.dateOfBirth = None
        self.motherMaidenName = None
        self.phoneNumber = None
        self.appointmentDate = None
        self.pastAppDate = None

    def upload_for_searching(self, first_name, last_name, date_of_birth, mother_maiden_name, phone_number, appointment_date):
        self.firstName = first_name
        self.lastName = last_name
        self.dateOfBirth = date_of_birth
        self.motherMaidenName = mother_maiden_name
        self.phoneNumber = phone_number
        self.appointmentDate = appointment_date
        self.pastAppDate = appointment_date

    def search_customer(self):
        # Searching customer by first name + last name + mother maiden name + dob return PK ID
        # Connect to the database
        cnxn, cursor = ConnectingToDatabase.connect_database(self)

        # Searching the patient giving back patient not found if there are no records in the table
        userin = UserInput()
        userin.change_first_name()
        userin.change_last_name()
        userin.change_dob()
        userin.change_mother_maiden_name()
        self.upload_for_searching(userin.FirstName,
                                  userin.LastName,
                                  userin.Dob,
                                  userin.MotherMaidenName)

        # Querying the result in the patient table
        query_search = "SELECT ID FROM Patient WHERE FirstName=? and LastName=? and DateOfBirth=? and MotherMaidenName=?;"
        cursor.execute(query_search, self.firstName, self.lastName, self.dateOfBirth, self.motherMaidenName)
        row = cursor.fetchone()
        try:
            id_current_query = row[0]
            return id_current_query
        except:
            return None

    def search_customer_duplicate_checker(self):
        # Check the new customer if it's already in the table, preventing from upload

        # Connect to the database
        cnxn, cursor = ConnectingToDatabase.connect_database(self)

        userin = UserInput()
        userin.adding_new_patient()
        self.upload_for_searching(userin.FirstName,
                                  userin.LastName,
                                  userin.Dob,
                                  userin.MotherMaidenName,
                                  userin.Phone_number,
                                  userin.AppointmentDate,
                                  )
        # Querying the result in the patient table
        query_search = "SELECT ID FROM Patient WHERE FirstName=? and LastName=? and DateOfBirth=? and MotherMaidenName=?;"
        cursor.execute(query_search, self.firstName, self.lastName, self.dateOfBirth, self.motherMaidenName)
        row = cursor.fetchone()
        try:
            id_current_query = row[0]
            return id_current_query
        except:
            return None
<file_sep>/main.py
from PatientModify import *

#adding a customer from userinputs input
adding_new_customer = PatientModding()

adding_new_customer.adding_customer()
<file_sep>/Readme.md
Python 3 project for a Patient registry software
###
For new features please read [New features list](https://github.com/RobertPecz/PatientRegistry/projects/1?add_cards_query=is%3Aopen). If you choose to make a new feature, open an issue for it.
