51
INTRODUCTION TO RELATIONAL DATABASE AND SQL CARER DATABASE SCHEDULING SYSTEM FINAL PROJECT DOCUMENT Submitted by: Ademola Kazeem Student No: 15200214 Due: 29 th April, 2016

Carer Database Scheduling System.pdf

Embed Size (px)

Citation preview

Page 1: Carer Database Scheduling System.pdf

INTRODUCTION TO RELATIONAL

DATABASE AND SQL

CARER DATABASE SCHEDULING SYSTEM

FINAL PROJECT DOCUMENT

Submitted by: Ademola Kazeem

Student No: 15200214

Due: 29th April, 2016

Page 2: Carer Database Scheduling System.pdf

PART ONE

Page 3: Carer Database Scheduling System.pdf

Project Idea

Carer Database Scheduling System is a project that allows Carer to specify their availability

for job scheduling. Each carer is assigned to clients based on the carers' availability by an

manager who is the manager of a Homecare Company. The carers can also schedule their

holidays and manager can either grant or deny the holiday for any holiday requests by any

carer. The manager can assign cover for a carer that is on holiday.

Business Rules

Carer is an employee of the company that takes care of the company’s Clients.

Each Carer has manager and 1 manager can manage more than one Carers.

The Carer specifies his/her availability in the system, which in our case is a many-to-

many relationship, so it was divided into 2 called Carer_Availability.

The Manager assigns Carer to different Clients by setting up a roster (called Visit in the

diagram)

A Carer can book many holidays in a year, based on the acceptance or rejection of the

Manager and number of holiday days the Carer is allowed by the Company.

The manager can either grant or deny holiday request by the Carer.

Once a Carer is on holiday, there is need for cover.

A Cover is also a Carer, except that he/she would be covering for someone on holiday.

A manager assigns visits, and a Carer can visit many Clients while 1 Clients can be

visited by many Carer.

A Carer can visit many times within a period.

A period is a range of days that a Carer is scheduled to visit some specific Clients, the

range of time could be 3 weeks range.

Clients have comments, apart from their names, address etc.

These Comments may include medication, personal care, Grooming/Dressing, Client

safety, house work, and other information needed by the Carer to take care of the

Client.

Entities in the Database 1. Manager(managerId, username, firstname, lastname, DateOfBirth, email, dateCreated,

dateUpdated) 2. Address(postcodes, street, city, county, country) 3. Carer(carerId, username, firstname, lastname, sex, phone, ppsNumber, adminNote,

userStatus, DateOfBirth, email, dateCreated, dateUpdated)

4. Company_Car(reg_number, model, assigned_to, assigned_date)

5. Client(clientId, firstname, lastname, sex, phone, DateOfBirth, commentId) 6. Comments(commentId, dressing, communication, housework, medication, safety,

nutrition) 7. Availability (availabilityId, dayOfTheWeek, time) 8. Period(periodId, fromdate, todate, fromtime, totime, duration) 9. Holiday(carerId, managerId, date, numberOfDays, numberOfDaysAllowed,

numberOfDaysTaken, status)

Page 4: Carer Database Scheduling System.pdf

10. Visit (visitId, carerId, clientId, periodId, managerId) 11. Cover(carerId, coverCarerId, reason, visitId) 12. Carer_Availability (carerId, availabilityId) 13. Company_Car(reg_number, model, assigned_to_carerid, assigneddate) 14. Company_car_audit(reg_number, model, assigned_to_carerid, assigneddate,

recordeddate, operation)

Functional Dependencies 1. Manager(managerId, username, firstname, lastname, DateOfBirth, securityLevel, email,

dateCreated, dateUpdated) 2. Carer(carerId, username, firstname, lastname, sex, address, county, phone,

ppsNumber, adminNote, userStatus, DateOfBirth, email, dateCreated, dateUpdated)

1 to Many Relationship

1 Manager Grants Many Holidays

1 Manager assigns many visits

1 Carer has many holidays

1 Period involves many visits

1 cover can make many visits

Many to Many Relationship

Many carers has many availabilities (Carer_availabilities)

Many carers visit many Clients

1 to 1 Relationship

1 carer may be assigned 1 Company_Car

1 Client has 1 Comment

Page 5: Carer Database Scheduling System.pdf
Page 6: Carer Database Scheduling System.pdf

PART TWO

Note: The whole project is exported using expdp and it is attached as part of the document,

more information is in the log file.

Page 7: Carer Database Scheduling System.pdf

Database Setup

Proof of 3rd Normal Form

One of the example is demonstrated below:

Page 8: Carer Database Scheduling System.pdf

Here, the 3rd normal form is demonstrated in the two tables above, with the use POSTCODES

as the foreign key in client table as well as carer table.

The POSTCODES column was made NOT NULL because we believe that all carer should have

address and all clients should have address that the carer will visit.

All other tables follow 3rd normal form too.

For instance, the table availability and table carer have many to many relationship that do not

split, so we have another table called carer_availability, that host the relationship between

the two tables, as shown in the ERDiagram above.

The tables are included in the sql document attached with this document.

Click on the logo to open the SQL file.

Page 9: Carer Database Scheduling System.pdf

Select * from address;

Select * from company_car

Page 10: Carer Database Scheduling System.pdf

Select * from carer

Select * from client

Page 11: Carer Database Scheduling System.pdf

Comments is a table that contains more information about a client that a carer will go visit.

Select * from comments

Select * from manager

Page 12: Carer Database Scheduling System.pdf

Period is the time by which the carer is being assigned for.

4 INNER JOIN queries with descriptions

INNER JOIN 1 Description: The first INNER JOIN was used in prc_view_all_cr_avail_assigned

procedure with cursor that allows us to view list of all the carers that have chosen availability

before they are being assigned to a client. The code is shown below:

procedure prc_view_all_cr_avail_assigned

is

CURSOR carer_avail_cursor IS

--list all the list of carers that have selected their availabilities for work

SELECT A.FIRSTNAME firstname, A.LASTNAME lastname, C.DAYOFTHEWEEK DAYOFTHEWEEK,

C.FROMTIME FROMTIME, C.TOTIME TOTIME FROM carer A INNER JOIN carer_availability B

ON A.CARERID = B.CARERID INNER JOIN availability C ON B.AVAILABILITYID =

C.AVAILABILITYID ORDER BY A.FIRSTNAME ASC;

selected_carer_avail_row carer_avail_cursor%ROWTYPE;

begin

Page 13: Carer Database Scheduling System.pdf

OPEN carer_avail_cursor;

FETCH carer_avail_cursor INTO selected_carer_avail_row;

DBMS_OUTPUT.PUT_LINE('LIST OF CARERS AND THEIR AVAILABILITY');

DBMS_OUTPUT.PUT_LINE('');

DBMS_OUTPUT.PUT_LINE('FULLNAME' || CHR(9) || CHR(9) || CHR(9) || 'DAY OF THE

WEEK' || CHR(9)|| CHR(9) || 'FROM TIME' || CHR(9) || CHR(9) || 'TO TIME');

WHILE carer_avail_cursor%FOUND LOOP

DBMS_OUTPUT.PUT_LINE(selected_carer_avail_row.firstname || ' ' ||

selected_carer_avail_row.lastname || CHR(9) || CHR(9) || CHR(9) ||

selected_carer_avail_row.dayoftheweek ||

CHR(9) || CHR(9) || CHR(9) || CHR(9) ||CHR(9) ||

selected_carer_avail_row.fromtime || CHR(9) || CHR(9) ||CHR(9) || CHR(9) ||

selected_carer_avail_row.totime);

FETCH carer_avail_cursor INTO selected_carer_avail_row;

END LOOP;

CLOSE carer_avail_cursor;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('No data to display, sorry!');

WHEN others THEN

DBMS_OUTPUT.PUT_LINE('Error!');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'Error Just occur with error code

'||sqlcode, 25);

end;

The screenshot showing the anonymous procedure that run the procedure.

We used the screenshot below to add assign new carer to availability

And the screenshot below shows the list of all the carers who has selected availability

Page 14: Carer Database Scheduling System.pdf

INNER JOIN 2: We want to check the day of the week that a carer is available. i.e. if the weekday (e.g. MONDAY) specified by the input date is one of the days that the carer specified as his/her availability.

procedure prc_schedule_visit(var_carer_id number, client_id number, var_period_id

number,

var_manager_id number, var_date varchar2, var_from_time varchar2, var_to_time

varchar2)

as

add_result number;

var_v_count number;

var_p_count number;

var_count_mgr number;

var_from_date varchar2(50);

var_to_date varchar2(50);

var_to_in timestamp;

var_from_in timestamp;

var_given_day_of_week varchar2(15);

var_av_day_of_week NUMBER;

begin

var_from_date := var_date ||' ' || var_from_time;

var_to_date := var_date ||' ' || var_to_time;

var_from_in:= TO_DATE(var_from_date, 'MM/DD/YYYY HH24:MI');

var_to_in := TO_DATE(var_to_date, 'MM/DD/YYYY HH24:MI');

--check if the carer has been assigned to this client for this period and

this time before

--if yes show response if not, continue to the next line of action.

select count(1) into var_v_count from visit where periodid = var_period_id

and

carerid = var_carer_id and clientid = client_id and TRUNC(VISITFROM) =

TRUNC(TO_DATE(var_date, 'MM/DD/YYYY'))

and pkg_misc_functions.datepart('HH', VISITFROM) =

pkg_misc_functions.datepart('HH', var_from_in)

and pkg_misc_functions.datepart('MI', VISITFROM) =

pkg_misc_functions.datepart('MI', var_from_in)

and pkg_misc_functions.datepart('HH', VISITTO) =

pkg_misc_functions.datepart('HH', var_to_in)

and pkg_misc_functions.datepart('MI', VISITTO) =

pkg_misc_functions.datepart('MI', var_to_in);

Page 15: Carer Database Scheduling System.pdf

if(var_v_count > 0)then

DBMS_OUTPUT.PUT_LINE('Sorry!, the carer has already been setup for this

period, client and time');

else

--var_date := '04/03/2016';

--check if the given date is within the specified period, if yes, then

continue

--else display message to prompt the user to try again with another

parameter.

select count(1) into var_p_count from period p where trunc(p.FROMDATETIME)

<= TO_DATE(var_date,'MM/DD/YYYY') AND

trunc(p.TODATETIME) >= TO_DATE(var_date,'MM/DD/YYYY');

if(var_p_count > 0)then

--check the day of the week (e.g. MONDAY) of the given date and check it

against the carer availability

select pkg_misc_functions.datename('DW', TO_DATE(var_date,'MM/DD/YYYY'))

into var_given_day_of_week from dual;

--We want to check the day of the week that a carer is available. i.e.

if the weekday (e.g. MONDAY)

-- specified by the input date is one of the days that the carer

specified as his/her availability

select count(dayoftheweek) into var_av_day_of_week from availability a

INNER JOIN carer_availability b on a.availabilityid =

b.availabilityid where b.carerid = var_carer_id and

upper(a.dayoftheweek) = trim(var_given_day_of_week) and

TO_DATE(A.FROMTIME, 'HH24:MI') <= TO_DATE(var_from_time,'HH24:MI') AND

TO_DATE(A.TOTIME, 'HH24:MI') >= TO_DATE(var_to_time,'HH24:MI');

DBMS_OUTPUT.PUT_LINE('The count of dayoftheweek in the table is: ' ||

var_av_day_of_week);

if(var_av_day_of_week > 0)then

add_result := PKG_TABLES_CREATION.CDSS_ADD_VISIT(var_carer_id,

client_id, var_period_id, var_manager_id, var_from_in, var_to_in);

if(add_result = 0)then

COMMIT;

DBMS_OUTPUT.PUT_LINE('Carer with carer id: ' || var_carer_id

|| ' has been successfully assigned to a client');

else

DBMS_OUTPUT.PUT_LINE('Error with Error Number: ' || add_result

|| ' has occured. Please consult the admin!');

end if;

else

DBMS_OUTPUT.PUT_LINE('Sorry! the carer is not available for

assignment on this day, please specify another day!');

end if;

else

DBMS_OUTPUT.PUT_LINE('Please specify the appropriate period to assign

visit for this carer,

the date specified does not match the period you want to assign');

end if;

end if;

exception

when others then

--PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode,sqlerrm,33);

DBMS_OUTPUT.PUT_LINE('Sorry! Error has occurred please contact the admin! or try

again later');

Page 16: Carer Database Scheduling System.pdf

DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.format_error_backtrace);

Sample output of the condition

When the condition is fulfilled.

Page 17: Carer Database Scheduling System.pdf

INNER JOIN 3 Description: It allows us to view all carers that are assigned to what clients by

what managers in what range of period and what range of time for visiting.

procedure prc_view_all_visit

is

CURSOR visit_all_cursor IS

--list all the list of carer, manager that assigned the carer, the clients they are

assigned to

--, etc at one glance.

SELECT C.FIRSTNAME || ' ' || C.LASTNAME CARER_NAME, CL.FIRSTNAME || ' ' ||

CL.LASTNAME CLIENT_NAME,

M.FIRSTNAME || ' ' || M.LASTNAME MANAGER_NAME, V.VISITFROM VISITING_FROM, V.VISITTO

VISITING_TO,

P.FROMDATETIME PERIOD_FROM, P.TODATETIME PERIOD_TO FROM CARER C INNER JOIN VISIT V

ON V.CARERID=C.CARERID INNER JOIN CLIENT CL ON V.CLIENTID = CL.CLIENTID

INNER JOIN PERIOD P ON V.PERIODID = P.PERIODID INNER JOIN MANAGER M ON

V.MANAGERID=M.MANAGERID;

selected_visit_row visit_all_cursor%ROWTYPE;

begin

OPEN visit_all_cursor;

FETCH visit_all_cursor INTO selected_visit_row;

DBMS_OUTPUT.PUT_LINE('LIST OF ALL ROSTERS');

DBMS_OUTPUT.PUT_LINE('');

DBMS_OUTPUT.PUT_LINE('CARERNAME' || CHR(9) || CHR(9) || CHR(9) ||

'CLIENTNAME' || CHR(9) || CHR(9) || CHR(9) || 'MANAGERNAME' || CHR(9) || CHR(9) ||

CHR(9) || 'VISITING_FROM' || CHR(9) || CHR(9) || 'VISITING_TO'

|| CHR(9) || CHR(9) || CHR(9) || CHR(9) || 'PERIOD_FROM' || CHR(9) ||

CHR(9) || CHR(9) || 'PERIOD_TO');

WHILE visit_all_cursor%FOUND LOOP

DBMS_OUTPUT.PUT_LINE(selected_visit_row.CARER_NAME || CHR(9) ||

CHR(9) || CHR(9) || selected_visit_row.CLIENT_NAME || CHR(9) || CHR(9) || CHR(9) ||

selected_visit_row.MANAGER_NAME ||

CHR(9) || CHR(9) || CHR(9) || CHR(9) ||CHR(9) ||

selected_visit_row.VISITING_FROM || CHR(9) || CHR(9) ||CHR(9) || CHR(9) ||

selected_visit_row.VISITING_TO

|| CHR(9) || CHR(9) || CHR(9) || CHR(9) ||CHR(9) ||

selected_visit_row.PERIOD_FROM || CHR(9) || CHR(9) ||CHR(9) || CHR(9) ||

selected_visit_row.PERIOD_TO);

Page 18: Carer Database Scheduling System.pdf

FETCH visit_all_cursor INTO selected_visit_row;

END LOOP;

CLOSE visit_all_cursor;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('No data to display, sorry!');

WHEN others THEN

DBMS_OUTPUT.PUT_LINE('Error has occured please contact the admin!');

end;

After executing the procedure above, we have the list

INNER JOIN 4 and description: This shows individual carer’s roster for a period of time. So a

carer can just supply the carer number and the period number to get the roster.

Page 19: Carer Database Scheduling System.pdf

6 OUTER JOIN (2 x left, 2 x full, 2 x right) queries with descriptions

FULL JOIN 1 and description: Show full list of cars both assigned and unassigned.

procedure prc_view_car_carer

is

CURSOR view_cursor IS

--list all the list of both carer and the car assigned and the car not assigned

SELECT CC.REG_NUMBER regno, CC.MODEL model, CC.ASSIGNED_DATE ass_date,

C.FIRSTNAME || ' ' || C.LASTNAME CARER_NAME FROM COMPANY_CAR CC FULL OUTER

JOIN CARER C ON

CC.ASSIGNED_TO_CARERID=C.CARERID;

selected_view_row view_cursor%ROWTYPE;

begin

OPEN view_cursor;

FETCH view_cursor INTO selected_view_row;

DBMS_OUTPUT.PUT_LINE('LIST OF ALL CARS AND CARERS');

DBMS_OUTPUT.PUT_LINE('');

DBMS_OUTPUT.PUT_LINE('REGISTRATION_NUMBER' || CHR(9) || CHR(9) || CHR(9) ||

'MODEL' || CHR(9) || CHR(9) || CHR(9) || 'ASSIGNED_DATE' || CHR(9) || CHR(9) ||

CHR(9) || 'CARER_NAME');

WHILE view_cursor%FOUND LOOP

DBMS_OUTPUT.PUT_LINE(selected_view_row.regno || CHR(9) || CHR(9) ||

CHR(9) || selected_view_row.model || CHR(9) || CHR(9) || CHR(9) ||

selected_view_row.ass_date ||

CHR(9) || CHR(9) || CHR(9) || CHR(9) ||CHR(9) ||

selected_view_row.carer_name);

FETCH view_cursor INTO selected_view_row;

END LOOP;

CLOSE view_cursor;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('No data to display, sorry!');

WHEN others THEN

DBMS_OUTPUT.PUT_LINE('Error has occured please contact the admin!');

end;

Page 20: Carer Database Scheduling System.pdf

SELECT CC.REG_NUMBER regno, CC.MODEL model, CC.ASSIGNED_DATE ass_date,

C.FIRSTNAME || ' ' || C.LASTNAME CARER_NAME FROM COMPANY_CAR CC FULL OUTER

JOIN CARER C ON

CC.ASSIGNED_TO_CARERID=C.CARERID;

Using the procedure to execute

begin

pkg_scheduling_assignments.prc_view_car_carer;

end;/

Page 21: Carer Database Scheduling System.pdf

FULL JOIN 2 and description: Show full list of all carers and the corresponding managers.

SELECT C.FIRSTNAME ||' ' || C.LASTNAME CARER_NAME, C.ADMINNOTE, M.FIRSTNAME ||' ' ||

M.LASTNAME MANAGER_NAME FROM CARER C FULL OUTER JOIN MANAGER M ON C.MANAGERID =

M.MANAGERID;

LEFT JOIN 1: and description: We want to list all the clients and some of their corresponding

comment information

select C.FIRSTNAME || ' ' || c.LASTNAME CLIENT_NAME, CC.DRESSING, CC.COMMUNICATION,

CC.HOUSEWORK, CC.MEDICATION, CC.SAFETY, CC.NUTRITION from client c LEFT OUTER

JOIN COMMENTS CC ON

C.COMMENTID=CC.COMMENTID;

Page 22: Carer Database Scheduling System.pdf

LEFT JOIN 2: We want to know the list of holidays dates from and to, that were booked by

what carer so that we have in the database in order to make business decisions on approving

or rejecting them.

SELECT H.HOLIDAYFROMDATE, H.HOLIDAYTODATE, H.NUMBEROFDAYS, H.STATUS, C.FIRSTNAME,

C.LASTNAME FROM HOLIDAY H LEFT OUTER JOIN CARER C ON H.CARERID=C.CARERID;

RIGHT JOIN 1: Here, we are interested in holidays date that all managers are involved in for

business decision

SELECT M.FIRSTNAME, M.LASTNAME, H.HOLIDAYFROMDATE, H.HOLIDAYTODATE FROM MANAGER M

RIGHT OUTER JOIN HOLIDAY H ON H.MANAGERID = M.MANAGERID

Page 23: Carer Database Scheduling System.pdf

RIGHT JOIN 2: We are interested in getting the information about all carers who have applied

for holiday and their holiday approved or rejected, or who have not applied at all in order to

make business decision.

select H.HOLIDAYFROMDATE, H.HOLIDAYTODATE, H.NUMBEROFDAYS, H.STATUS, C.FIRSTNAME,

C.LASTNAME FROM holiday h RIGHT OUTER JOIN CARER C ON H.CARERID = C.CARERID;

1 CUBE query (with at least 2 columns

CUBE was used to count the number of holiday days each carer has booked

SELECT C.CARERID, H.HOLIDAYFROMDATE,

SUM(H.NUMBEROFDAYS) FROM HOLIDAY H INNER JOIN CARER C ON C.CARERID = H.CARERID

GROUP BY CUBE(C.CARERID, H.HOLIDAYFROMDATE );

Page 24: Carer Database Scheduling System.pdf

5 examples of sub-queries

Sub-query 1: We want to get the number of days the carers hava taken in the booking year before he/she is allowed to go to a new holiday. If the number of days for the year is greater than the number allowed for that carer, we would report error. select sum(numberofdays) into var_num_of_days from

holiday where carerid = selected_grant_row.carerid AND

PKG_MISC_FUNCTIONS.datepart('YY', HOLIDAYFROMDATE)=

(SELECT PKG_MISC_FUNCTIONS.datepart('YY', HOLIDAYFROMDATE) FROM

HOLIDAY WHERE

STATUS='BOOKED' AND CARERID = selected_grant_row.carerid);

DBMS_OUTPUT.PUT_LINE(' Number of days: ' || var_num_of_days);

select numberofdaysallowed into var_allowed from carer where

carerid = selected_grant_row.carerid;

Here is the full code where the subquery was implemented.

procedure prc_grant_holiday(var_manager_id number)

is

CURSOR grant_cursor IS

SELECT * FROM holiday WHERE status = 'BOOKED' and managerid = var_manager_id;

selected_grant_row grant_cursor%ROWTYPE;

var_allowed number;

var_num_of_days number;

update_h_result number;

update_ccr_result number;

var_status varchar2(15);

var_count_ass_cr_car number;

var_car_reg varchar2(40);

var_mgr_count number;

Page 25: Carer Database Scheduling System.pdf

begin

select count(1) into var_mgr_count from manager where managerid =

to_number(var_manager_id);

if(var_mgr_count > 0)then

begin

OPEN grant_cursor;

FETCH grant_cursor INTO selected_grant_row;

WHILE grant_cursor%FOUND LOOP

--We want to get the number of days the carers hava taken in the -

--booking year before he/she is allowed to go to a new holiday

select sum(numberofdays) into var_num_of_days from

holiday where carerid = selected_grant_row.carerid AND

PKG_MISC_FUNCTIONS.datepart('YY', HOLIDAYFROMDATE)=

(SELECT PKG_MISC_FUNCTIONS.datepart('YY', HOLIDAYFROMDATE) FROM

HOLIDAY WHERE

STATUS='BOOKED' AND CARERID = selected_grant_row.carerid);

DBMS_OUTPUT.PUT_LINE(' Number of days: ' || var_num_of_days);

select numberofdaysallowed into var_allowed from carer where

carerid = selected_grant_row.carerid;

DBMS_OUTPUT.PUT_LINE('Days allowed: ' || var_allowed);

if(var_num_of_days > var_allowed) then

DBMS_OUTPUT.PUT_LINE('Sorry! carer with Id: '||

selected_grant_row.carerid

|| ' has either finished holiday for the year or picked too much

new holiday. Please review and rebook, thank you!');

else

SAVEPOINT UPDATE_AND_UNASSIGN;

var_status := 'APPROVED';

DBMS_OUTPUT.PUT_LINE('value to send to update holiday: ' ||

var_status || ', carer id: ' || selected_grant_row.carerid

|| ', manager id: ' || var_manager_id);

update_h_result :=

pkg_tables_update.cdss_update_holiday(selected_grant_row.carerid, var_manager_id,

var_status);

if(update_h_result = 0) then

select count(1) into var_count_ass_cr_car from company_car

where assigned_to_carerid = selected_grant_row.carerid;

if(var_count_ass_cr_car > 0)then

select reg_number into var_car_reg from company_car

where assigned_to_carerid = selected_grant_row.carerid;

update_ccr_result :=

pkg_tables_update.cdss_update_car(var_car_reg);

if(update_ccr_result = 0)then

DBMS_OUTPUT.PUT_LINE('The holiday of Carer of

Carer Id: ' || selected_grant_row.carerid || ' has been granted, but the car has

been deallocated');

COMMIT;

else

DBMS_OUTPUT.PUT_LINE('Sorry! we cannot

deallocate the car assigned to this carer with id: '|| selected_grant_row.carerid ||

'at the moment, and all the transactions are now rolled back for the carer.

Pls contact the administrator or try again

later.');

ROLLBACK TO UPDATE_AND_UNASSIGN;

end if;

else

DBMS_OUTPUT.PUT_LINE('The holiday of Carer of Carer

Id: ' || selected_grant_row.carerid || ' has been granted, and no car to

deallocate');

COMMIT;

Page 26: Carer Database Scheduling System.pdf

end if;

else

DBMS_OUTPUT.PUT_LINE('Sorry! we cannot update the holiday

information for carer with id: '|| selected_grant_row.carerid || 'at the moment, and

all the transactions are now rolled back for the carer.

Pls contact the administrator or try again

later.');

ROLLBACK TO UPDATE_AND_UNASSIGN;

end if;

end if;

FETCH grant_cursor INTO selected_grant_row;

END LOOP;

CLOSE grant_cursor;

end;

else

DBMS_OUTPUT.PUT_LINE('The manager specified does not exist. Sorry!');

end if;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('No data for the manager to process. Sorry!');

end;

Sub-query 2: We are checking for carers who have applied for holiday more than once in a

given year, and we gave 2016 as an example.

--check for carers who have applied for holiday more than once in a given year in

this case, 2016

select C.FIRSTNAME, C.LASTNAME from carer c where c.carerid in

(select carerid from holiday WHERE pkg_misc_functions.datepart('YY',

HOLIDAYFROMDATE) = '2016' having count(numberofdays) > 1 Group by carerid);

Page 27: Carer Database Scheduling System.pdf

Sub-query 3: This query with subqueries check if a carer who want to cover is also on holiday

before being assigned to cover another carer.

--check if the carer is also on holiday

select count(1) into var_on_hol from holiday h where h.carerid =

var_cover_id and

h.HOLIDAYFROMDATE <= (select trunc(VISITFROM) from visit where visitid =

var_visit_id)

and H.HOLIDAYTODATE >= (select TRUNC(VISITTO) from visit where visited =

var_visit_id);

DBMS_OUTPUT.PUT_LINE('Check if cover is on holiday too, using variable

val_on_hol to count: ' || var_on_hol);

if(var_cover_id = var_carer_id)then

DBMS_OUTPUT.PUT_LINE('Sorry, A carer cannot cover for

himself/herself!');

elsif(var_on_hol > 0) then

DBMS_OUTPUT.PUT_LINE('Sorry, the cover is on holiday too at the time');

-- check if the cover carer is also on visit at the time

select count(1) into var_on_visit from visit where carerid =

var_cover_id and

VISITFROM <= (select VISITFROM from visit where visitid =var_visit_id)

and VISITTO >= (select VISITTO from visit where visitid =var_visit_id);

DBMS_OUTPUT.PUT_LINE('Check if cover is on visit at the time too using

var_on_visit to count: ' || var_on_visit);

if(var_on_visit > 0)then

DBMS_OUTPUT.PUT_LINE('Sorry, the cover is also on duty at the time!');

Page 28: Carer Database Scheduling System.pdf

Sub-query 4: This query with subqueries check if a carer who want to cover has a visit at the

time too, since a carer cannot be at more than one places at a time, it is meaningless to let

them be able to assign any carer just any how.

Sub-query 5: We want to know the list of carers that have choosen their availability so that

we can assign them to clients. Only carers with availability Id would be assigned.

--all the Carer that have set up their availability

select firstname, lastname, dateofbirth from carer where carerid in

(select distinct carerid from carer_availability)

Page 29: Carer Database Scheduling System.pdf

5 PL/SQL procedures as part of one package. One procedure must demonstrate each of the following:

The procedures showing here are in one package called pkg_scheduling_assignments

Procedure 1: The use of a cursor, save points and rollback: This procedure is one of the many procedures developed for this application and it duely makes use of cursor, savepoints and rollback. In order to grant holiday to a carer, we would first check if such carer has a car given to him/her to go to the clients, and that he/she is eligible for holiday based on some controls including whether he has expended his holiday for the year he is trying to book holiday for or not. If all conditions are met, we would proceed to approving holiday. Then the car is deallocated from such carer until he/she is back so that others can make use of the car to visit clients. So the transaction that saves the approval will be rolled back in case of error or something terrible happened during the approval. This means that both the update for the holiday and deallocation of the car would have to be successful. If update holiday has error, it is rolled back. We are using cursor to loop through each carer that has status ‘BOOKED’ and belonging to one manager, so that the manager only need to hit one button to approve or reject holiday booking by each carer under them.

procedure prc_grant_holiday(var_manager_id number)

is

CURSOR grant_cursor IS

SELECT * FROM holiday WHERE status = 'BOOKED' and managerid = var_manager_id;

selected_grant_row grant_cursor%ROWTYPE;

var_allowed number;

var_num_of_days number;

update_h_result number;

update_ccr_result number;

var_status varchar2(50);

var_count_ass_cr_car number;

var_car_reg varchar2(40);

var_mgr_count number;

begin

select count(1) into var_mgr_count from manager where managerid = var_manager_id;

if(var_mgr_count > 0)then

begin

OPEN grant_cursor;

FETCH grant_cursor INTO selected_grant_row;

WHILE grant_cursor%FOUND LOOP

--We want to get the number of days the carers hava taken in the

booking year

--before he/she is allowed to go to a new holiday

DBMS_OUTPUT.PUT_LINE(' Inside loop carer ' ||

selected_grant_row.carerid );

select sum(numberofdays) into var_num_of_days from

holiday where carerid = selected_grant_row.carerid AND

PKG_MISC_FUNCTIONS.datepart('YY', HOLIDAYFROMDATE)=

(SELECT PKG_MISC_FUNCTIONS.datepart('YY', HOLIDAYFROMDATE) FROM

HOLIDAY WHERE

Page 30: Carer Database Scheduling System.pdf

STATUS='BOOKED' AND CARERID = selected_grant_row.carerid);

DBMS_OUTPUT.PUT_LINE(' Number of days: ' || var_num_of_days);

select numberofdaysallowed into var_allowed from carer where

carerid = selected_grant_row.carerid;

DBMS_OUTPUT.PUT_LINE('Days allowed: ' || var_allowed);

if(var_num_of_days > var_allowed) then

var_status := 'REJECTED, TOO MANY DAYS';

update_h_result :=

pkg_tables_update.cdss_update_holiday(selected_grant_row.carerid, var_manager_id,

var_status);

if(update_h_result = 0)then

commit;

DBMS_OUTPUT.PUT_LINE('Sorry! the holiday has been rejected,

please update');

else

DBMS_OUTPUT.PUT_LINE('Error updating the rejection');

end if;

DBMS_OUTPUT.PUT_LINE('Sorry! carer with Id: '||

selected_grant_row.carerid

|| ' has either finished holiday for the year or picked too much

new holiday. Please review and rebook, thank you!');

else

SAVEPOINT UPDATE_AND_UNASSIGN;

var_status := 'APPROVED';

DBMS_OUTPUT.PUT_LINE('value to send to update holiday: ' ||

var_status || ', carer id: ' || selected_grant_row.carerid

|| ', manager id: ' || var_manager_id);

update_h_result :=

pkg_tables_update.cdss_update_holiday(selected_grant_row.carerid, var_manager_id,

var_status);

if(update_h_result = 0) then

select count(1) into var_count_ass_cr_car from company_car

where assigned_to_carerid = selected_grant_row.carerid;

if(var_count_ass_cr_car > 0)then

select reg_number into var_car_reg from company_car

where assigned_to_carerid = selected_grant_row.carerid;

update_ccr_result :=

pkg_tables_update.cdss_update_car(var_car_reg);

if(update_ccr_result = 0)then

COMMIT;

DBMS_OUTPUT.PUT_LINE('The holiday of Carer of

Carer Id: ' || selected_grant_row.carerid || ' has been granted, but the car has

been deallocated');

else

ROLLBACK TO UPDATE_AND_UNASSIGN;

DBMS_OUTPUT.PUT_LINE('Sorry! we cannot

deallocate the car assigned to this carer with id: '|| selected_grant_row.carerid ||

'at the moment, and all the transactions are now rolled back for the carer.

Pls contact the administrator or try again

later.');

end if;

else

COMMIT;

DBMS_OUTPUT.PUT_LINE('The holiday of Carer of Carer

Id: ' || selected_grant_row.carerid || ' has been granted, and no car to

deallocate');

end if;

Page 31: Carer Database Scheduling System.pdf

else

ROLLBACK TO UPDATE_AND_UNASSIGN;

DBMS_OUTPUT.PUT_LINE('Sorry! we cannot update the holiday

information for carer with id: '|| selected_grant_row.carerid || 'at the moment, and

all the transactions are now rolled back for the carer.

Pls contact the administrator or try again

later.');

end if;

end if;

FETCH grant_cursor INTO selected_grant_row;

END LOOP;

CLOSE grant_cursor;

end;

else

DBMS_OUTPUT.PUT_LINE('The manager specified does not exist. Sorry!');

end if;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('No data for the manager to process. Sorry!');

end;

We used grant holiday procedure below to grant all carers who are a being managed by a

manager 1000 holidays and unassign cars from them in order to assign it to another person for

work purpose.

begin

pkg_scheduling_assignments.prc_grant_holiday(1000);

end;

Page 32: Carer Database Scheduling System.pdf

Procedure 2: This procedure is used to assign a cover to a carer, the cover is also a carer but can only cover for another if he/she is not on holiday and not having a client to attend to at the same time of the cover.

procedure prc_assign_cover(var_manager_id number)

as

var_cover_id number;

var_carer_id number;

var_on_hol number;

var_on_visit number;

var_result number;

var_reason varchar2(70);

var_visit_id number;

begin

var_cover_id := 1024;

var_carer_id := 1004;

var_reason := 'The carer is on Holiday';

var_visit_id := 18;

--check if the carer is also on holiday

select count(1) into var_on_hol from holiday h where h.carerid =

var_cover_id and

h.HOLIDAYFROMDATE <= (select trunc(VISITFROM) from visit where visitid =

var_visit_id)

and H.HOLIDAYTODATE >= (select TRUNC(VISITTO) from visit where

visitid=var_visit_id);

DBMS_OUTPUT.PUT_LINE('Check if cover is on holiday too, using variable

val_on_hol to count: ' || var_on_hol);

if(var_cover_id = var_carer_id)then

DBMS_OUTPUT.PUT_LINE('Sorry, A carer cannot cover for

himself/herself!');

elsif(var_on_hol > 0) then

DBMS_OUTPUT.PUT_LINE('Sorry, the cover is on holiday too at the time');

else

-- check if the cover carer is also on visit at the time

select count(1) into var_on_visit from visit where carerid =

var_cover_id and

VISITFROM <= (select VISITFROM from visit where visitid =var_visit_id)

and VISITTO >= (select VISITTO from visit where visitid =var_visit_id);

DBMS_OUTPUT.PUT_LINE('Check if cover is on visit at the time too using

var_on_visit to count: ' || var_on_visit);

if(var_on_visit > 0)then

DBMS_OUTPUT.PUT_LINE('Sorry, the cover is also on duty at the

time!');

else

var_result := PKG_TABLES_CREATION.CDSS_ADD_COVER(var_carer_id,

var_cover_id, var_reason, var_visit_id);

if(var_result = 0)then

DBMS_OUTPUT.PUT_LINE('Congratulations! Cover for carer with id:

' || var_carer_id

|| ' has been successfully found. Carer with Carer id: ' ||

var_cover_id || ' will cover');

Page 33: Carer Database Scheduling System.pdf

COMMIT;

else

DBMS_OUTPUT.PUT_LINE('Oops! we cannot save cover information at

the moment. Please try again later!');

end if;

end if;

end if;

end;

Procedure 3: This procedure is used to assign a carer to a availability. The carers can choose different days of the week that they are going to be available for work.

Example:

begin

PKG_SCHEDULING_ASSIGNMENTS.PRC_ASSIGN_CARER_TO_AVAIL(1026, 27, 1033);

end;/

procedure prc_assign_carer_to_avail(var_carer_id number, var_availability_id number,

var_manager_id number)

as

result number;

var_count_c_a number;

var_count_mgr number;

begin

select count(1) into var_count_c_a from carer_availability where carerid =

var_carer_id and availabilityid = var_availability_id;

select count(1) into var_count_mgr from manager where managerid =

var_manager_id;

if(var_count_mgr > 0)then

begin

if(var_count_c_a > 0)then

DBMS_OUTPUT.PUT_LINE('Sorry! This Carer has been assigned to this

availability before

Please specify another carer or another availability. Thank you!');

else

begin

--we return 0 everytime the insertion is successful

result :=

pkg_tables_creation.cdss_add_carer_availability(var_carer_id, var_availability_id);

Page 34: Carer Database Scheduling System.pdf

if(result = 0) then

COMMIT;

DBMS_OUTPUT.PUT_LINE('Carer availability has been successfully

inserted: ');

else

DBMS_OUTPUT.PUT_LINE('Sorry! the carer cannot be assigned at the

moment, we have error: '

|| result || ' please contact administrator');

end if;

end;

end if;

end;

else

DBMS_OUTPUT.PUT_LINE('Sorry! this manager id ' || var_manager_id ||

' does not exist, only existing manager can insert data');

end if;

end;

if the manager id does not exist

If the carer has already been assigned

When the data is correct

Page 35: Carer Database Scheduling System.pdf

Procedure 4: The procedure is used to assign carer to client with the help of the carer_availability selected by the carer above and at a particular period. This is assigned by a manager assigned to the carer. Example of calling of the procedure:

declare

add_result number;

var_v_count number;

var_p_count number;

var_count_mgr number;

var_manager_id number;

var_from_date varchar2(50);

var_to_date varchar2(50);

var_to_in timestamp;

var_from_in timestamp;

var_given_day_of_week varchar2(15);

var_av_day_of_week NUMBER;

var_date varchar2(30);

var_from_time varchar2(30);

var_to_time varchar2(30);

var_carer_id number;

client_id number;

var_period_id number;

begin

var_carer_id:= 1003;

var_manager_id := 1002;

var_date := '4/4/2016';

var_from_time := '10:00';

var_to_time := '12:00';

client_id := 300;

var_period_id := 2;

pkg_scheduling_assignments.prc_schedule_visit(var_carer_id, client_id,

var_period_id,

var_manager_id, var_date, var_from_time, var_to_time);

end;

The procedure creation procedure prc_schedule_visit(var_carer_id number, client_id number, var_period_id

number,

var_manager_id number, var_date varchar2, var_from_time varchar2, var_to_time

varchar2)

as

add_result number;

var_v_count number;

var_p_count number;

var_count_mgr number;

var_v_count_cl number;

var_v_count_cr number;

var_from_date varchar2(50);

var_to_date varchar2(50);

var_to_in timestamp;

var_from_in timestamp;

Page 36: Carer Database Scheduling System.pdf

var_given_day_of_week varchar2(15);

var_av_day_of_week NUMBER;

begin

var_from_date := var_date ||' ' || var_from_time;

var_to_date := var_date ||' ' || var_to_time;

var_from_in:= TO_DATE(var_from_date, 'MM/DD/YYYY HH24:MI');

var_to_in := TO_DATE(var_to_date, 'MM/DD/YYYY HH24:MI');

--check if the carer has been assigned to this client for this period and

this time before

--if yes show response if not, continue to the next line of action.

select count(1) into var_v_count from visit where periodid = var_period_id

and

carerid = var_carer_id and clientid = client_id and TRUNC(VISITFROM) =

TRUNC(TO_DATE(var_date, 'MM/DD/YYYY'))

and pkg_misc_functions.datepart('HH', VISITFROM) =

pkg_misc_functions.datepart('HH', var_from_in)

and pkg_misc_functions.datepart('MI', VISITFROM) =

pkg_misc_functions.datepart('MI', var_from_in)

and pkg_misc_functions.datepart('HH', VISITTO) =

pkg_misc_functions.datepart('HH', var_to_in)

and pkg_misc_functions.datepart('MI', VISITTO) =

pkg_misc_functions.datepart('MI', var_to_in);

--check if the carer has been assigned to another client at the time, so he

does not get assigned

-- to 2 or more clients at a time

select count(1) into var_v_count_cl from visit where periodid = var_period_id

and

carerid = var_carer_id and TRUNC(VISITFROM) = TRUNC(TO_DATE(var_date,

'MM/DD/YYYY'))

and pkg_misc_functions.datepart('HH', VISITFROM) =

pkg_misc_functions.datepart('HH', var_from_in)

and pkg_misc_functions.datepart('MI', VISITFROM) =

pkg_misc_functions.datepart('MI', var_from_in)

and pkg_misc_functions.datepart('HH', VISITTO) =

pkg_misc_functions.datepart('HH', var_to_in)

and pkg_misc_functions.datepart('MI', VISITTO) =

pkg_misc_functions.datepart('MI', var_to_in);

--check if the time has been booked for that client with another carer

select count(1) into var_v_count_cr from visit where periodid = var_period_id

and

clientid = client_id and TRUNC(VISITFROM) = TRUNC(TO_DATE(var_date,

'MM/DD/YYYY'))

and pkg_misc_functions.datepart('HH', VISITFROM) =

pkg_misc_functions.datepart('HH', var_from_in)

and pkg_misc_functions.datepart('MI', VISITFROM) =

pkg_misc_functions.datepart('MI', var_from_in)

and pkg_misc_functions.datepart('HH', VISITTO) =

pkg_misc_functions.datepart('HH', var_to_in)

and pkg_misc_functions.datepart('MI', VISITTO) =

pkg_misc_functions.datepart('MI', var_to_in);

if(var_v_count > 0)then

--If carer already exist for the same client

DBMS_OUTPUT.PUT_LINE('Sorry!, the carer has already been setup for this

period, client and time');

elsif(var_v_count_cl > 0) then

--if carer has been scheduled with another client

Page 37: Carer Database Scheduling System.pdf

DBMS_OUTPUT.PUT_LINE('Sorry!, the carer has already been setup for this

period, to another client at the same time');

elsif(var_v_count_cr > 0) then

--if carer has been scheduled with another client

DBMS_OUTPUT.PUT_LINE('Sorry!, the client has already been setup for this

period, to another carer at the same time');

else

--var_date := '04/03/2016';

--check if the given date is within the specified period, if yes, then

continue

--else display message to prompt the user to try again with another

parameter.

select count(1) into var_p_count from period p where trunc(p.FROMDATETIME)

<= TO_DATE(var_date,'MM/DD/YYYY') AND

trunc(p.TODATETIME) >= TO_DATE(var_date,'MM/DD/YYYY');

if(var_p_count > 0)then

--check the day of the week (e.g. MONDAY) of the given date and check it

against the carer availability

select pkg_misc_functions.datename('DW', TO_DATE(var_date,'MM/DD/YYYY'))

into var_given_day_of_week from dual;

--We want to check the day of the week that a carer is available. i.e.

if the weekday (e.g. MONDAY)

-- specified by the input date is one of the days that the carer

specified as his/her availability

select count(dayoftheweek) into var_av_day_of_week from availability a

INNER JOIN carer_availability b on a.availabilityid =

b.availabilityid where b.carerid = var_carer_id and

upper(a.dayoftheweek) = trim(var_given_day_of_week) and

TO_DATE(A.FROMTIME, 'HH24:MI') <= TO_DATE(var_from_time,'HH24:MI') AND

TO_DATE(A.TOTIME, 'HH24:MI') >= TO_DATE(var_to_time,'HH24:MI');

DBMS_OUTPUT.PUT_LINE('The count of dayoftheweek in the table is: ' ||

var_av_day_of_week);

if(var_av_day_of_week > 0)then

add_result := PKG_TABLES_CREATION.CDSS_ADD_VISIT(var_carer_id,

client_id, var_period_id, var_manager_id, var_from_in, var_to_in);

if(add_result = 0)then

COMMIT;

DBMS_OUTPUT.PUT_LINE('Carer with carer id: ' || var_carer_id

|| ' has been successfully assigned to a client');

else

DBMS_OUTPUT.PUT_LINE('Error with Error Number: ' || add_result

|| ' has occured. Please consult the admin!');

end if;

else

DBMS_OUTPUT.PUT_LINE('Sorry! the carer is not available for

assignment on this day, please specify another day!');

end if;

else

DBMS_OUTPUT.PUT_LINE('Please specify the appropriate period to assign

visit for this carer,

the date specified does not match the period you want to assign');

end if;

end if;

exception

when others then

Page 38: Carer Database Scheduling System.pdf

--PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode,sqlerrm,33);

DBMS_OUTPUT.PUT_LINE('Sorry! Error has occurred please contact the admin! or try

again later');

DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.format_error_backtrace);

end;

When the data is already existing in the database

When the carer has not selected the availability

Page 39: Carer Database Scheduling System.pdf

When it is successful.

Procedure 5: The procedure shows the list of rosters of one carer based on a range of period. So the carer can specify the period id and his/her carer id in order to show it. Example of calling of the procedure:

begin

pkg_scheduling_assignments.prc_view_all_visit(1003, 2);

end;/

procedure prc_view_all_visit(var_carer_id number, var_period_id number)

is

CURSOR visit_all_cursor IS

--list all the list of carer, manager that assigned the carer, the clients they are

assigned to

--, etc at one glance.

SELECT C.FIRSTNAME || ' ' || C.LASTNAME CARER_NAME, CL.FIRSTNAME || ' ' ||

CL.LASTNAME CLIENT_NAME,

M.FIRSTNAME || ' ' || M.LASTNAME MANAGER_NAME, V.VISITFROM VISITING_FROM, V.VISITTO

VISITING_TO,

P.FROMDATETIME PERIOD_FROM, P.TODATETIME PERIOD_TO FROM CARER C INNER JOIN VISIT V

ON V.CARERID=C.CARERID INNER JOIN CLIENT CL ON V.CLIENTID = CL.CLIENTID

INNER JOIN PERIOD P ON V.PERIODID = P.PERIODID INNER JOIN MANAGER M ON

V.MANAGERID=M.MANAGERID

AND C.CARERID=var_carer_id and P.PERIODID=var_period_id;

selected_visit_row visit_all_cursor%ROWTYPE;

begin

OPEN visit_all_cursor;

FETCH visit_all_cursor INTO selected_visit_row;

DBMS_OUTPUT.PUT_LINE('LIST OF CARER '|| var_carer_id || ' ROSTER');

DBMS_OUTPUT.PUT_LINE('');

DBMS_OUTPUT.PUT_LINE('CARERNAME' || CHR(9) || CHR(9) || CHR(9) ||

'CLIENTNAME' || CHR(9) || CHR(9) || CHR(9) || 'MANAGERNAME' || CHR(9) || CHR(9) ||

CHR(9) || 'VISITING_FROM' || CHR(9) || CHR(9) || 'VISITING_TO'

Page 40: Carer Database Scheduling System.pdf

|| CHR(9) || CHR(9) || CHR(9) || CHR(9) || 'PERIOD_FROM' || CHR(9) ||

CHR(9) || CHR(9) || 'PERIOD_TO');

WHILE visit_all_cursor%FOUND LOOP

DBMS_OUTPUT.PUT_LINE(selected_visit_row.CARER_NAME || CHR(9) ||

CHR(9) || CHR(9) || selected_visit_row.CLIENT_NAME || CHR(9) || CHR(9) || CHR(9) ||

selected_visit_row.MANAGER_NAME ||

CHR(9) || CHR(9) || CHR(9) || CHR(9) ||CHR(9) ||

selected_visit_row.VISITING_FROM || CHR(9) || CHR(9) ||CHR(9) || CHR(9) ||

selected_visit_row.VISITING_TO

|| CHR(9) || CHR(9) || CHR(9) || CHR(9) ||CHR(9) ||

selected_visit_row.PERIOD_FROM || CHR(9) || CHR(9) ||CHR(9) || CHR(9) ||

selected_visit_row.PERIOD_TO);

FETCH visit_all_cursor INTO selected_visit_row;

END LOOP;

CLOSE visit_all_cursor;

EXCEPTION

WHEN NO_DATA_FOUND THEN

DBMS_OUTPUT.PUT_LINE('No data to display, sorry!');

WHEN others THEN

DBMS_OUTPUT.PUT_LINE('Error has occured please contact the admin!');

end;

There are other procedures in the other packages and in the package made use of in this

section.

Page 41: Carer Database Scheduling System.pdf

2 PL/SQL functions

There are lots of functions made use of in this program, all the insertions are performed with

the use of functions. Then we have a miscellaneous function that is always in handy in the

application to get the day of the week, hours, minutes, seconds, days. Others also get

differences between 2 dates which might be hours difference, days difference, week

differences etc. I will just pick 2 of the functions to explain here.

Function 1.

During holiday booking, an anonymous plsql was written where a function cdss_add_holiday

belonging to pkg_tables_creation was called in order to book holiday by carers.

This allows carers to book holiday. Error is displayed if the user has already booked a holiday

that has not been approved or rejected.

Example:

declare

var_care_id number;

var_manager_id number;

var_status varchar2(30);

var_managerid number;

var_holiday_from_date date;

var_holiday_to_date DATE;

insert_result number;

v_count number;

begin

var_care_id := 1025;

var_manager_id := 1033;

var_status := 'BOOKED';

var_holiday_from_date := TO_DATE('4/5/2016', 'MM/DD/YYYY');

var_holiday_to_date := TO_DATE('4/14/2016', 'MM/DD/YYYY');

select count(1) into v_count from holiday where CARERID=var_care_id and

STATUS='BOOKED';

if(v_count > 0)then

DBMS_OUTPUT.PUT_LINE('Sorry, you still have a booking that has not been approved

yet');

Else

--function that calls the book holiday

insert_result := PKG_TABLES_CREATION.cdss_add_holiday(var_care_id,

var_manager_id, var_holiday_from_date, var_holiday_to_date, var_status);

if(insert_result = 0)then

COMMIT;

DBMS_OUTPUT.PUT_LINE('Holiday booking was successful the manager will access

it soon');

else

DBMS_OUTPUT.PUT_LINE('Error has occured during booking');

end if;

end if;

exception

when others then

DBMS_OUTPUT.PUT_LINE('Error has occured ');

DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.format_error_backtrace);

end;/

Page 42: Carer Database Scheduling System.pdf

Here is the function

FUNCTION cdss_add_holiday(var_carerid number, var_managerid number,

var_holiday_from_date DATE, var_holiday_to_date DATE, var_status

varchar2 ) return number

as

var_duration number;

no_rows exception;

v_l_retval number;

begin

begin

var_duration := PKG_MISC_FUNCTIONS.datediff('DD',

var_holiday_from_date, var_holiday_to_date);

INSERT INTO holiday

(

CARERID,

MANAGERID,

HOLIDAYFROMDATE,

NUMBEROFDAYS,

STATUS,

HOLIDAYTODATE

)

values (

var_carerid,

var_managerid,

var_holiday_from_date,

var_duration,

var_status,

var_holiday_to_date

);

if sql%rowcount != 1 then

raise no_rows;

end if;

exception

when no_rows then

DBMS_OUTPUT.PUT_LINE('No rows inserted for cdss_add_holiday');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'No rows inserted for

cdss_add_holiday', 22);

return 5694;

when others then

DBMS_OUTPUT.PUT_LINE('Insert failed for cdss_add_holiday');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'Insert failed for

cdss_add_holiday', 25);

return sqlcode;

end;

return 0;

exception

when others then

DBMS_OUTPUT.PUT_LINE('Execution of cdss_add_holiday failed');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'Execution of

cdss_add_holiday failed', 104);

return 95;

end;

Page 43: Carer Database Scheduling System.pdf

When the holiday is successfully booked

When the carer has booked before and the manager has not reply (either approve or reject)

Function 2.

The datediff function is situated in pkg_misc_functions package it is used in the program

to get the duration between two dates which may be year, weeks, days, hours, minutes

or seconds difference. It was used inside the

Page 44: Carer Database Scheduling System.pdf

function datediff(fmt VARCHAR2, dat1 DATE, dat2 DATE) return INTEGER as

rint INTEGER;

begin

if (fmt = 'DD') then

rint := trunc(dat2) - trunc(dat1);

end if;

if (fmt = 'MM') then

rint := MONTHS_BETWEEN(last_day(dat2), last_day(dat1));

end if;

if (fmt = 'YY') then

rint := datepart(yy, dat2) - datepart(yy, dat1);

end if;

if (fmt = 'HH') then

rint := ((trunc(dat2) - trunc(dat1)) * 24) +

(datepart(hh, dat2) - datepart(hh, dat1));

end if;

if (fmt = 'MI') then

rint := ((datediff(hh, dat1, dat2)) * 60) +

(datepart(mi, dat2) - datepart(mi, dat1));

end if;

if (fmt = 'SS') then

rint := ((datediff(mi, dat1, dat2)) * 60) +

(datepart(ss, dat2) - datepart(ss, dat1));

end if;

if(fmt = 'WK')then

select trunc((dat2-dat1)/7) into rint from dual;

end if;

return rint;

end;

Where it was used

FUNCTION cdss_add_holiday(var_carerid number, var_managerid number,

var_holiday_from_date DATE, var_holiday_to_date DATE, var_status

varchar2 ) return number

as

var_duration number;

no_rows exception;

v_l_retval number;

begin

begin

--get differences based on number of days

var_duration := PKG_MISC_FUNCTIONS.datediff('DD',

var_holiday_from_date, var_holiday_to_date);

INSERT INTO holiday

(

CARERID,

MANAGERID,

HOLIDAYFROMDATE,

NUMBEROFDAYS,

STATUS,

HOLIDAYTODATE

)

values (

var_carerid,

var_managerid,

var_holiday_from_date,

Page 45: Carer Database Scheduling System.pdf

var_duration,

var_status,

var_holiday_to_date

);

if sql%rowcount != 1 then

raise no_rows;

end if;

exception

when no_rows then

DBMS_OUTPUT.PUT_LINE('No rows inserted for cdss_add_holiday');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'No rows inserted for

cdss_add_holiday', 22);

return 5694;

when others then

DBMS_OUTPUT.PUT_LINE('Insert failed for cdss_add_holiday');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'Insert failed for

cdss_add_holiday', 25);

return sqlcode;

end;

return 0;

exception

when others then

DBMS_OUTPUT.PUT_LINE('Execution of cdss_add_holiday failed');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'Execution of

cdss_add_holiday failed', 104);

return 95;

end;

It was also used in function cdss_add_period in order to find the differences in weeks between

periods.

FUNCTION cdss_add_period(var_from_date_time date,

var_to_date_time date) return number

as

var_duration number;

no_rows exception;

v_l_retval number;

begin

-- The period is a range of time that carers get assigned to clients newly.

Mostly, carers

--get assigned in 3 weeks

--PKG_MISC_FUNCTIONS.datediff is getting the duration of the period which

maybe 2 weeks or 3 weeks,

-- So the var_duration here return weeks, so if you have 1 it means 1 week,

and if 2 it means 2 weeks

begin

--get difference based on weeks

var_duration := PKG_MISC_FUNCTIONS.datediff('WK',

var_from_date_time, var_to_date_time);

DBMS_OUTPUT.PUT_LINE('The number of weeks between ' || var_from_date_time || ' and

' ||

var_to_date_time || ' is ' || var_duration);

if(var_duration < 1)then

return -1;

elsif(var_duration > 1) then

Page 46: Carer Database Scheduling System.pdf

INSERT INTO PERIOD

(

FROMDATETIME,

TODATETIME,

DURATION

)

values (

var_from_date_time,

var_to_date_time,

var_duration

);

end if;

if sql%rowcount != 1 then

raise no_rows;

end if;

exception

when no_rows then

DBMS_OUTPUT.PUT_LINE('No rows inserted for cdss_add_period');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'No rows inserted for

cdss_add_period', 22);

return 5694;

when others then

DBMS_OUTPUT.PUT_LINE('Insert failed for cdss_add_period');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'Insert failed for

cdss_add_period', 25);

return sqlcode;

end;

return 0;

exception

when others then

DBMS_OUTPUT.PUT_LINE('Execution of cdss_add_period failed');

PKG_MISC_FUNCTIONS.ORA_RAISERROR(sqlcode, 'Execution of

cdss_add_period failed', 104);

return 95;

end;

Another function is datename that was used in the application to get the name of the week

function datename(fmt IN VARCHAR2, miscdate IN DATE) return VARCHAR2 as

rexp VARCHAR2(15);

begin

if (fmt = 'DD') then

rexp := to_char(miscdate, 'DD');

end if;

if (fmt = 'MM') then

rexp := to_char(miscdate, 'Month');

end if;

if (fmt = 'YY') then

rexp := to_char(miscdate, 'YYYY');

end if;

if (fmt = 'QQ') then

rexp := to_char(miscdate, 'Q');

Page 47: Carer Database Scheduling System.pdf

end if;

if (fmt = 'WK') then

rexp := to_char(miscdate, 'WW');

end if;

if (fmt = 'DY') then

rexp := to_char(miscdate, 'DDD');

end if;

if (fmt = 'DW') then

rexp := to_char(miscdate, 'DAY');

end if;

if (fmt = 'Dw') then

rexp := to_char(miscdate, 'Day');

end if;

if (fmt = 'dw') then

rexp := to_char(miscdate, 'day');

end if;

if (fmt = 'HH') then

rexp := to_char(miscdate, 'HH24');

end if;

if (fmt = 'MI') then

rexp := to_char(miscdate, 'MI');

end if;

if (fmt = 'SS') then

rexp := to_char(miscdate, 'SS');

end if;

return rexp;

end;

var_duration := PKG_MISC_FUNCTIONS.datediff('WK',

var_from_date_time, var_to_date_time);

DBMS_OUTPUT.PUT_LINE('The number of weeks between ' || var_from_date_time || ' and

' ||

var_to_date_time || ' is ' || var_duration);

The specified above generates the screenshot below:

Page 48: Carer Database Scheduling System.pdf

3 Triggers (at least 1 before, and at least 1 after)

Trigger 1

The trigger was created for all the auto increment ids in order to combine with the created

sequence to be triggered before each insertion.

CREATE SEQUENCE MGR_CARER_SEQ

START WITH 1000

INCREMENT BY 1 NOMAXVALUE;

--TRIGGERS

CREATE OR REPLACE TRIGGER MGR_INSERTION_TRIGGER

BEFORE INSERT ON MANAGER FOR EACH ROW

BEGIN

SELECT MGR_CARER_SEQ.NEXTVAL INTO :NEW.MANAGERID FROM DUAL;

END;

/

Trigger 2

This trigger shows whenever a carer tries to select more than 20 days of holiday at once.

CREATE OR REPLACE TRIGGER HOL_GT_20

BEFORE INSERT OR UPDATE OF NUMBEROFDAYS ON HOLIDAY

FOR EACH ROW

WHEN (New.NUMBEROFDAYS > 20)

BEGIN

DBMS_OUTPUT.PUT_LINE('The carer with carer id: ' || :NEW.carerid || ' cannot have

more than 20 days holiday at once');

DBMS_OUTPUT.PUT_LINE('The Updated or Inserted number of days is: ' ||

:NEW.NUMBEROFDAYS);

END;

/

Page 49: Carer Database Scheduling System.pdf

Trigger 3: This is an after trigger that triggers whenever there is an insert, update or delete

into company_car table, this is a company’s asset and it needs to be monitored to know know

whenever someone makes a change to it. In the trigger, we captured the user that performed

the act too.

CREATE OR REPLACE TRIGGER COMPANY_CAR_TRIGGER

AFTER INSERT OR DELETE OR UPDATE ON COMPANY_CAR

FOR EACH ROW

DECLARE

v_username varchar2(50);

BEGIN

SELECT user INTO v_username FROM dual;

IF INSERTING THEN

INSERT INTO COMPANY_CAR_AUDIT ( REG_NUMBER, MODEL, ASSIGNED_TO_CARERID,

ASSIGNED_DATE, operation, WHO)

VALUES (:NEW.REG_NUMBER,:NEW.MODEL, :NEW.ASSIGNED_TO_CARERID ,

:NEW.ASSIGNED_DATE, 'Insert ', v_username);

ELSIF DELETING THEN

INSERT INTO COMPANY_CAR_AUDIT ( REG_NUMBER, MODEL, ASSIGNED_TO_CARERID,

ASSIGNED_DATE, operation, WHO)

VALUES (:NEW.REG_NUMBER,:NEW.MODEL, :NEW.ASSIGNED_TO_CARERID ,

:NEW.ASSIGNED_DATE, 'Delete ', v_username);

ELSIF UPDATING THEN

INSERT INTO COMPANY_CAR_AUDIT ( REG_NUMBER, MODEL, ASSIGNED_TO_CARERID,

ASSIGNED_DATE, operation, WHO)

VALUES (:NEW.REG_NUMBER,:NEW.MODEL, :NEW.ASSIGNED_TO_CARERID ,

:NEW.ASSIGNED_DATE, 'Update ', v_username);

END IF;

END;

/

Page 50: Carer Database Scheduling System.pdf

Here is the script that will insert into the table

declare

var_result number;

begin

var_result := pkg_tables_creation.cdss_add_company_car('8993 CC 90', 'Toyota

Avensis 2015', null);

if(var_result=0)then

COMMIT;

DBMS_OUTPUT.PUT_LINE('Company car Successfully saved!');

else

DBMS_OUTPUT.PUT_LINE('We are having challenges saving the car at the moment!');

end if;

end;/

After the execution of pkg_tables_createion.cdss_add_company_car, the following was created automatically by the trigger.

Page 51: Carer Database Scheduling System.pdf

Identification of weaknesses or potential improvements to the

database

The database application program is very robust and easy to use. The package names,

procedures and functions are well defined and are descriptive of what names they are

doing. The CDSS is the acronym for the project, which means Carer Database Scheduling

System.

I started the managerid and carerid from 1000 and interwoven into one another depending

on which id is being created next. This means they use the same trigger to generate id

since they are both employees of a company. This makes it easier to follow. Visit table has

visitid because we are still making use of the id somewhere else within the application

But because of the short period of time, the program however is not short of some

weaknesses including the use of numbers as parameters which might be hard for some

people to remember, Eventhough username in the table for carer and manager are unique

and can be used to search for any for any information just like the carerid and managerid,

I decided to use numbers to uniquely identify the column. The problem with this is that

each carer and manager has to remember their ids and manager has to also remember some

ids in order to get job done within the applicaton.

In the future, the application could be using username instead of ids which is easier to

remember by the carer.

Also, in the future, salary structure could be added to the functionality and feedback after

the visiting has been performed should be part of the application.