SET scan off
CREATE OR REPLACE PACKAGE CESTimEn
AS
-- FILE NAME..: cestimen.sql
-- RELEASE....: 7.3
-- OBJECT NAME: CESTIMEN
-- PRODUCT....: GENWEB
-- RELEASED...: 9/25/07
-- USAGE......: CES BANNER Web Time Entry Approvals Package Specification
-- AUTHOR.....: Stephen Rea; Maristream, Inc.
-- Declare the procedures called within the Web environment: the procedure
-- that creates the time entry approval screen (P_DispTEView) and the procedure
-- that is called when the submit (Submit Approvals/Returns) button is pressed
-- (P_ProcTEUpdate). These procedures must be declared to Web Tailor (click
-- on Create button in Customize a Web Menu or Procedure). The supporting
-- procedures don't need to be declared here.
-- Updates:
-- 3/15/04 - Original version.
-- 4/19/04 - Include employees with no hours reported (no perhour record).
-- Also, exclude BI's who have reported zero hours.
-- 5/7/04 - Added optional PIN verification for approver (see request_pin).
-- 5/19/04 - Select only the allowed org code job records for superusers.
-- 6/26/07 - Include Report Leave actions (L), along with Report Time
-- actions (T).
-- 7/16/07 - Call SCT's pekteap.p_approve_time procedure to also update
-- the leave balances (which weren't updated here) for the Payroll Leave
-- Reporting changes for SM employees.
-- 7/19/07 - Add a Return checkbox to return the timesheet for correction.
-- 9/25/07 - Combine htp.p javascript lines into a single htp.p call for
-- each javascript function (tip from Mark Styles of McGill University).
empty_array owa_util.ident_arr;
PROCEDURE P_DispTEView;
PROCEDURE P_ProcTEUpdate(
seqnos_approve owa_util.ident_arr default empty_array,
seqnos_return owa_util.ident_arr default empty_array,
PinNo char
);
END CESTimEn;
/
SHOW errors
SET scan on
SET scan off
CREATE OR REPLACE PACKAGE BODY CESTimEn
AS
-- FILE NAME..: cestime1.sql
-- RELEASE....: 7.3
-- OBJECT NAME: CESTIMEN
-- PRODUCT....: GENWEB
-- RELEASED...: 9/25/07
-- USAGE......: CES BANNER Web Time Entry Approvals Package Body
-- AUTHOR.....: Stephen Rea; Maristream, Inc.
-- Declare variables for the package's release version, the message
-- text string and severity level (1 = Stop, 2 = Warning, 3 = OK),
-- and the current user's pidm.
curr_release VARCHAR2(10) := '7.3';
msg_text VARCHAR2(1000) := NULL;
msg_level NUMBER := 3;
pidm NUMBER;
request_pin BOOLEAN := FALSE; -- Set this to FALSE to never request approver's
-- PIN, even if ptrinst_web_certification_ind is Y.
-- Declare cursors used in the package. For CESTIMEN, this includes the time
-- entry records (time sheets) to be approved for the given approver's pidm.
CURSOR approve_cur(pidm NUMBER)
IS
SELECT spriden_first_name first_name,spriden_last_name last_name,
spriden_pidm,perjobs_year year,perjobs_pict_code pict,
perjobs_payno payno,perjobs_seqno seqno,nvl(ptrearn_code,' ') code,
nvl(ptrearn_long_desc,'(No Hours)') category,
nvl(sum(perhour_hrs),0.00) hours,gobeacc_username approver,
perrout_appr_pidm apidm
FROM perjobs,perhour,perrout,spriden,gobeacc,ptrearn
WHERE perjobs_action_ind in ('T','L')
AND perjobs_status_ind = 'P'
AND perhour_jobs_seqno(+) = perjobs_seqno
AND perrout_jobs_seqno = perjobs_seqno
AND spriden_pidm = perjobs_pidm
AND spriden_change_ind is null
AND gobeacc_pidm = perrout_appr_pidm
AND ptrearn_code(+) = perhour_earn_code
AND (perrout_appr_pidm = pidm
OR EXISTS (SELECT 'x' FROM gobeacc,ptruser
WHERE gobeacc_pidm = pidm
AND ptruser_code = gobeacc_username
AND ptruser_te_appr_superuser = 'Y'
AND (EXISTS (SELECT 'x' FROM psrorgn
WHERE psrorgn_user_code = gobeacc_username
AND perjobs_orgn_code_ts between psrorgn_orgn_low
AND psrorgn_orgn_high)
OR NOT EXISTS (SELECT 'x' FROM psrorgn
WHERE psrorgn_user_code = gobeacc_username)))
OR EXISTS (SELECT 'x' from gobeacc g1,ntrtprx,gobeacc g2
WHERE g1.gobeacc_pidm = pidm
AND g1.gobeacc_username = ntrtprx_proxy_user_id
AND g2.gobeacc_username = ntrtprx_user_id
AND g2.gobeacc_pidm = perrout_appr_pidm))
GROUP BY
perjobs_seqno,perjobs_year,perjobs_pict_code,perjobs_payno,
ptrearn_code,ptrearn_long_desc,spriden_last_name,spriden_first_name,
spriden_pidm,gobeacc_username,perrout_appr_pidm
HAVING
not (nvl(sum(perhour_hrs),0.00) = 0 and perjobs_pict_code = 'BI')
ORDER BY
gobeacc_username,perjobs_year,perjobs_pict_code,perjobs_payno,
spriden_last_name,spriden_first_name,spriden_pidm,ptrearn_long_desc;
--------------------------------------------------------------------------
-- Procedure P_DispTEView (Display Time Entry Approvals View) builds the HTML to
-- display the time entry records and allow changes to the status indicators.
-- It includes creating one or more lines for each person's time entry with:
-- The text for each person's earn code hours.
-- A check box allowing the user to mark the status as approved.
-- Along with the following buttons:
-- A Check All button to set all of the seqno check boxes.
-- An Uncheck All button to clear all of the seqno check boxes.
-- A Switch All button (commented out) to flip the values of all of the
-- seqno check boxes.
-- A Submit Approvals/Returns button (which calls P_ProcTEUpdate to post the
-- changes), along with an optional PIN field for verification.
-- A Reset button (commented out) to change the fields on the screen back
-- to their original (unchecked) values (assuming the submit button hasn't
-- been pressed).
PROCEDURE P_DispTEView
IS
first_name spriden.spriden_first_name%TYPE;
last_name spriden.spriden_last_name%TYPE;
epidm spriden.spriden_pidm%TYPE;
year perjobs.perjobs_year%TYPE;
pict perjobs.perjobs_pict_code%TYPE;
payno perjobs.perjobs_payno%TYPE;
seqno perjobs.perjobs_seqno%TYPE;
code ptrearn.ptrearn_code%TYPE;
category ptrearn.ptrearn_long_desc%TYPE;
hours perhour.perhour_hrs%TYPE;
approver gobeacc.gobeacc_username%TYPE;
apidm perrout.perrout_appr_pidm%TYPE;
spriden_name varchar2(30);
approve_line VARCHAR2(80);
approve_found BOOLEAN := TRUE;
prev_seqno perjobs.perjobs_seqno%TYPE := 0;
cnt number;
reqpin char;
BEGIN
-- Get the current user ID's pidm (for whoever is logged in for this Web
-- session).
IF NOT twbkwbis.F_ValidUser(pidm)
THEN
RETURN;
END IF;
-- Check to see if there are any time entry records to approve for this pidm.
OPEN approve_cur(pidm);
FETCH approve_cur INTO first_name,last_name,epidm,year,pict,payno,seqno,
code,category,hours,approver,apidm;
IF approve_cur%NOTFOUND
THEN
approve_found := FALSE;
END IF;
CLOSE approve_cur;
-- See if the approver's PIN should be requested for verification of approvals.
IF request_pin
THEN
SELECT ptrinst_web_certification_ind INTO reqpin FROM ptrinst;
request_pin := reqpin = 'Y';
END IF;
-- Open the form, possibly just showing any outstanding error message(s) in it
-- if present (shouldn't be). Also, define the Check All, Uncheck All, and
-- Switch All functions to check and/or uncheck all of the seqno check boxes.
twbkwbis.P_OpenDoc('cestimen.P_DispTEView');
HTP.meta (
'Content-Script-Type',
'Default_Script_Language',
'text/javascript'
);
twbkjscr.p_jscriptopen;
htp.p('function approveAll(cnt) {
for (var j = 0; j < cnt; j++) {
if (cnt == 1) box = eval("document.timenform.seqnos_approve");
else box = eval("document.timenform.seqnos_approve(" + j + ")");
if (box.checked == false) box.checked = true;
if (cnt == 1) box = eval("document.timenform.seqnos_return");
else box = eval("document.timenform.seqnos_return(" + j + ")");
if (box.checked == true) box.checked = false;
}
}');
twbkjscr.p_jscriptclose;
twbkjscr.p_jscriptopen;
htp.p('function unapproveAll(cnt) {
for (var j = 0; j < cnt; j++) {
if (cnt == 1) box = eval("document.timenform.seqnos_approve");
else box = eval("document.timenform.seqnos_approve(" + j + ")");
if (box.checked == true) box.checked = false;
}
}');
twbkjscr.p_jscriptclose;
twbkjscr.p_jscriptopen;
htp.p('function switchAll(cnt) {
for (var j = 0; j < cnt; j++) {
if (cnt == 1) box = eval("document.timenform.seqnos_approve");
else box = eval("document.timenform.seqnos_approve(" + j + ")");
box.checked = !box.checked;
if (cnt == 1) box = eval("document.timenform.seqnos_return");
else box = eval("document.timenform.seqnos_return(" + j + ")");
box.checked = !box.checked;
}
}');
twbkjscr.p_jscriptclose;
twbkjscr.p_jscriptopen;
htp.p('function returnAll(cnt) {
for (var j = 0; j < cnt; j++) {
if (cnt == 1) box = eval("document.timenform.seqnos_return");
else box = eval("document.timenform.seqnos_return(" + j + ")");
if (box.checked == false) box.checked = true;
if (cnt == 1) box = eval("document.timenform.seqnos_approve");
else box = eval("document.timenform.seqnos_approve(" + j + ")");
if (box.checked == true) box.checked = false;
}
}');
twbkjscr.p_jscriptclose;
twbkjscr.p_jscriptopen;
htp.p('function unreturnAll(cnt) {
for (var j = 0; j < cnt; j++) {
if (cnt == 1) box = eval("document.timenform.seqnos_return");
else box = eval("document.timenform.seqnos_return(" + j + ")");
if (box.checked == true) box.checked = false;
}
}');
twbkjscr.p_jscriptclose;
twbkjscr.p_jscriptopen;
htp.p('function clearApprove(i) {
box = eval("document.timenform.seqnos_approve(" + i + ")");
if (box.checked == true) box.checked = false;
}');
twbkjscr.p_jscriptclose;
twbkjscr.p_jscriptopen;
htp.p('function clearReturn(i) {
box = eval("document.timenform.seqnos_return(" + i + ")");
if (box.checked == true) box.checked = false;
}');
twbkjscr.p_jscriptclose;
IF msg_text IS NOT NULL -- for any pending messages, just in case.
THEN
twbkfrmt.P_PrintMessage(msg_text,TO_CHAR(msg_level));
msg_text := NULL;
END IF;
-- Start building the form.
twbkwbis.P_DispInfo('cestimen.P_DispTEView','DEFAULT');
HTP.FormOpen('cestimen.P_ProcTEUpdate','post',cattributes=>'name=timenform'); -- this happens when submit button pressed
twbkfrmt.P_TableOpen('DATAENTRY',
cattributes=>'Summary="This table allows approval of time sheets."');
-- Create each time entry approval field.
cnt := 0;
IF approve_found
THEN
twbkfrmt.P_TableRowOpen;
twbkfrmt.P_TableDataLabel('Employee Name');
twbkfrmt.P_TableDataLabel('Year');
twbkfrmt.P_TableDataLabel('Pict');
twbkfrmt.P_TableDataLabel('PayNo');
-- twbkfrmt.P_TableDataLabel('SeqNo');
-- twbkfrmt.P_TableDataLabel('Code');
twbkfrmt.P_TableDataLabel('Category');
twbkfrmt.P_TableDataLabel('Hours');
twbkfrmt.P_TableDataLabel('Approver');
twbkfrmt.P_TableDataLabel('Approve It');
twbkfrmt.P_TableDataLabel('Return It');
twbkfrmt.P_TableRowClose;
FOR approve_rec IN approve_cur(pidm)
LOOP
twbkfrmt.P_TableRowOpen;
IF approve_rec.seqno != prev_seqno
THEN
twbkfrmt.P_TableDataLabel(approve_rec.first_name || ' ' || approve_rec.last_name);
twbkfrmt.P_TableDataLabel(approve_rec.year,calign=>'right');
twbkfrmt.P_TableDataLabel(approve_rec.pict);
twbkfrmt.P_TableDataLabel(approve_rec.payno,calign=>'right');
-- twbkfrmt.P_TableDataLabel(approve_rec.seqno,calign=>'right');
-- twbkfrmt.P_TableDataLabel(approve_rec.code,calign=>'right');
twbkfrmt.P_TableDataLabel(approve_rec.category);
twbkfrmt.P_TableDataLabel(to_char(approve_rec.hours,'990.99'),calign=>'right');
twbkfrmt.P_TableDataLabel(approve_rec.approver);
twbkfrmt.P_TableData(htf.FormCheckBox('seqnos_approve',
to_char(approve_rec.seqno) || '_' || to_char(approve_rec.apidm),cattributes=>'onclick="clearReturn(' || cnt || ')"'),
calign=>'center');
-- cattributes=>'ID="' || 'approve_' || approve_rec.seqno || '_' ||
-- approve_rec.code || '"'));
twbkfrmt.P_TableData(htf.FormCheckBox('seqnos_return',
to_char(approve_rec.seqno) || '_' || to_char(approve_rec.apidm),cattributes=>'onclick="clearApprove(' || cnt || ')"'),
calign=>'center');
-- cattributes=>'ID="' || 'return_' || approve_rec.seqno || '_' ||
-- approve_rec.code || '"'));
cnt := cnt + 1;
ELSE
twbkfrmt.P_TableDataLabel('',ccolspan=>'4');
-- twbkfrmt.P_TableDataLabel(approve_rec.code,calign=>'right');
twbkfrmt.P_TableDataLabel(approve_rec.category);
twbkfrmt.P_TableDataLabel(to_char(approve_rec.hours,'990.99'),calign=>'right');
twbkfrmt.P_TableDataLabel('');
END IF;
twbkfrmt.P_TableRowClose;
prev_seqno := approve_rec.seqno;
END LOOP;
ELSE
twbkfrmt.P_PrintMessage('There are no time sheets for you to approve.','2');
END IF;
-- Finish specifying the data entry fields with a call to twbkfrmt.P_TableClose
-- to match the starting twbkfrmt.P_TableOpen.
twbkfrmt.P_TableClose;
HTP.Para;
-- Add the buttons. The HTP.FormSubmit button (labeled 'Submit Approvals/
-- Returns') will call the "post" procedure (cestimen.P_ProcTEUpdate) specified
-- in the HTP.FormOpen call above. The HTP.FormReset button (labeled 'Reset')
-- will change the fields on the screen back to their original (unchecked)
-- values. The other buttons control the seqno check boxes. An optional PIN
-- verification for approval is also here.
IF approve_found
THEN
htp.p('');
htp.p('');
htp.p('');
htp.p('');
-- htp.p('');
htp.p(' ');
IF request_pin
THEN
htp.p('PIN for Approver:');
htp.p('');
ELSE
htp.p('');
htp.p(' ');
END IF;
HTP.FormSubmit(cvalue=>'Submit Approvals/Returns');
-- HTP.FormReset(cvalue=>'Reset');
END IF;
-- Finish building the form by closing the form and document. The value
-- passed to twbkwbis.P_CloseDoc is usually the current release version
-- of this form, and is placed at the bottom of the form.
HTP.FormClose;
twbkwbis.P_CloseDoc(curr_release);
END;
--------------------------------------------------------------------------
-- Procedure P_DispTEUpdate (Display Time Entry Update) returns to the
-- parent screen (probably the Personal Information screen) and displays a
-- message at the top of it indicating success or failure of the time entry
-- updates. (Note that this routine is called by P_ProcTEUpdate, which
-- is only called when the submit button is pressed, indicating an attempt
-- was made to approve the time entries.) Passing 'Y' to this routine
-- indicates a successful update; otherwise, unsuccessful.
PROCEDURE P_DispTEUpdate(disp_msg VARCHAR2)
IS
BEGIN
-- Determine which menu to call, stored in TWGBWMNU_BACK_URL.
OPEN twbklibs.getmenuc('cestimen.P_DispTEView');
FETCH twbklibs.getmenuc INTO twbklibs.twgbwmnu_rec;
IF twbklibs.getmenuc%NOTFOUND
THEN
CLOSE twbklibs.getmenuc;
RAISE twbklibs.getmenuerror;
END IF;
CLOSE twbklibs.getmenuc;
-- Indicate a successful update.
IF disp_msg = 'Y'
THEN
msg_text := 'Your time sheet approvals have been saved.';
msg_level := 3;
-- Indicate a problem with the update. If the message text string is not
-- empty, a problem was encountered when attempting to save the time entry
-- approvals; otherwise, there were no changes made for the time entry
-- approvals (even though the user clicked on the submit button).
ELSE
IF LENGTH(msg_text) > 0
THEN
msg_text := msg_text || ' ';
msg_text := msg_text || 'Your time sheet approvals were not saved.';
msg_level := 1;
ELSE
msg_text := 'There was nothing to approve for your time sheets.';
msg_level := 2;
END IF;
END IF;
-- Return to the parent screen, displaying the resulting message text string
-- and severity level icon.
twbkwbis.P_GenMenu(SUBSTR(twbklibs.twgbwmnu_rec.twgbwmnu_back_url,
INSTR(twbklibs.twgbwmnu_rec.twgbwmnu_back_url,'/',-1)+1),
msg_text,message_type=>TO_CHAR(msg_level));
-- This shouldn't happen!
EXCEPTION
WHEN twbklibs.getmenuerror
THEN
twbkfrmt.P_PrintMessage('Configuration Error -' ||
' Menu cestimen.P_DispTEView not found.','1');
END;
--------------------------------------------------------------------------
-- Procedure P_ProcTEUpdate (Process Time Entry Approvals) updates the
-- time entry status indicators, if valid, and is called when the submit
-- button is pressed. Note that only the seqnos which are checked are
-- included in the seqnos_approve array passed by the HTML, not the ones
-- which the approver unchecked. (Same with seqnos_return.)
PROCEDURE P_ProcTEUpdate(
seqnos_approve owa_util.ident_arr default empty_array,
seqnos_return owa_util.ident_arr default empty_array,
PinNo char
)
IS
seqno perjobs.perjobs_seqno%TYPE;
apidm perrout.perrout_appr_pidm%TYPE;
superuser char;
proxy char;
userpin varchar2(6);
msg_rec nokmsgs.msg_rectype;
BEGIN
-- Get the current user ID's pidm.
IF NOT twbkwbis.F_ValidUser(pidm)
THEN
RETURN;
END IF;
IF request_pin
THEN
SELECT gobtpac_pin INTO userpin FROM gobtpac
WHERE gobtpac_pidm = pidm;
IF PinNo is null or PinNo != userpin
THEN
userpin := '';
msg_text := 'The PIN you entered is incorrect.';
P_DispTEUpdate('N');
RETURN;
END IF;
userpin := '';
END IF;
-- Note: The job's org doesn't need to be checked here for superuser,
-- since, if superuser was used to select the job in the first place
-- to be displayed, then the org will have already matched for the
-- job's seqno at that time.
SELECT DECODE(COUNT(*),0,'N','Y') INTO superuser FROM gobeacc,ptruser
WHERE gobeacc_pidm = pidm
AND ptruser_code = gobeacc_username
AND ptruser_te_appr_superuser = 'Y';
-- Loop through the job seqnos to be approved, and approve each one.
IF seqnos_approve.EXISTS(1)
THEN
FOR i in seqnos_approve.FIRST .. seqnos_approve.LAST
LOOP
seqno := SUBSTR(seqnos_approve(i),1,INSTR(seqnos_approve(i),'_')-1);
apidm := SUBSTR(seqnos_approve(i),INSTR(seqnos_approve(i),'_')+1);
SELECT DECODE(COUNT(*),0,'N','Y') INTO proxy
FROM perrout,gobeacc g1,ntrtprx,gobeacc g2
WHERE perrout_queue_status_ind = 'P'
AND perrout_jobs_seqno = seqno
AND g1.gobeacc_pidm = pidm
AND g1.gobeacc_username = ntrtprx_proxy_user_id
AND g2.gobeacc_username = ntrtprx_user_id
AND g2.gobeacc_pidm = perrout_appr_pidm;
IF proxy = 'Y'
THEN
pekteap.p_approve_time(seqno,'A',pidm,apidm,'W',msg_rec);
ELSIF superuser = 'Y'
THEN
pekteap.p_approve_time(seqno,'S',pidm,null,'W',msg_rec);
ELSE
pekteap.p_approve_time(seqno,'A',pidm,null,'W',msg_rec);
END IF;
IF nokmsgs.f_error_found(msg_rec)
THEN
msg_text := 'Error on job ' || seqno || ': ' || msg_rec.msg_text;
P_DispTEUpdate('N');
RETURN;
END IF;
END LOOP;
END IF;
-- Loop through the job seqnos to be returned, and return each one.
IF seqnos_return.EXISTS(1)
THEN
FOR i in seqnos_return.FIRST .. seqnos_return.LAST
LOOP
seqno := SUBSTR(seqnos_return(i),1,INSTR(seqnos_return(i),'_')-1);
apidm := SUBSTR(seqnos_return(i),INSTR(seqnos_return(i),'_')+1);
SELECT DECODE(COUNT(*),0,'N','Y') INTO proxy
FROM perrout,gobeacc g1,ntrtprx,gobeacc g2
WHERE perrout_queue_status_ind = 'P'
AND perrout_jobs_seqno = seqno
AND g1.gobeacc_pidm = pidm
AND g1.gobeacc_username = ntrtprx_proxy_user_id
AND g2.gobeacc_username = ntrtprx_user_id
AND g2.gobeacc_pidm = perrout_appr_pidm;
IF proxy = 'Y'
THEN
pekteap.p_return_time(seqno,'A',pidm,apidm,'W',msg_rec);
ELSIF superuser = 'Y'
THEN
pekteap.p_return_time(seqno,'S',pidm,null,'W',msg_rec);
ELSE
pekteap.p_return_time(seqno,'A',pidm,null,'W',msg_rec);
END IF;
IF nokmsgs.f_error_found(msg_rec)
THEN
msg_text := 'Error on job ' || seqno || ': ' || msg_rec.msg_text;
P_DispTEUpdate('N');
RETURN;
END IF;
END LOOP;
END IF;
-- Return to the parent screen, indicating that the update was successful..
IF seqnos_approve.EXISTS(1) or seqnos_return.EXISTS(1)
THEN
P_DispTEUpdate('Y');
-- Otherwise, return to the parent screen, indicating nothing was changed.
ELSE
P_DispTEUpdate('N');
END IF;
END;
END CESTimEn;
/
SHOW errors
SET scan on