create or replace procedure pro_employee_card(
in_start_time Date, --統計開始時間
in_end_time Date, --統計結束時間
in_corp_id char(6) --公司id
) as
cur_employee_id char(10),
cur_employee_name varchar2(20),
cur_class_id char(6),
cur_class_num Number(10),
cur_senior_flag char(1),
cur_holiday_flag char(1),
cur_overtime_flag char(1)
cur_card_start Date,
cur_card_end Date,
c_class_name varchar2(40),
c_cycle_flag char(1),
n_cycle_time Number(6,2),
c_start_flag char(1),
c_end_flag char(1),n_over_time Number(6,2), --記錄總加班時間
n_holi_time Number(6,2), --記錄總請假時間
n_after_time Number(6,2), --記錄總曠工時間--定義遊標cur_employee尋找公司的員工記錄
declare Cursor cur_employee is
select employee_id,employee_name,class_id
from employee_code
where corp_id = in_corp_id;declare Cursor cur_card is
select class_num,senior_flag,holiday_flag,overtime_flag,card_start,card_end
from employee_card
where corp_id = in_corp_id
and employee_id = cur_employee_id
and class_id = cur_class_id;/**********
定義遊標,找出所對應的員工的請假記錄
在公司不要求上下班打卡或上下班隻打一次卡的情況下,算出各類請假的總時間,以方便計算薪資時使用
**********/
delcare Cursor cur_fur is
select furlough_sn,sum(furlough_end - furlough_start) * 24
from employee_furlough
where corp_id = in_corp_id
and furlough_start > in_bgin_date
and furlough_start <= in_end_date
and furlough_end >= in_begin_date
and furlough_end <= in_end_date
and employee_id = var_employee_id
Group by furlough_sn;/*******
定義遊標,找出所對應員工的加班記錄,
在公司不要求上下班打卡或上下班隻打一次卡的情況下,算出各類加班的總時間,以方便計算薪資時使用
************/
declare Cursor cur_over is
select overtime_sn,sum(overtime_end - overtime_start) * 24
from employee_overtime
where corp_id = in_corp_id
and employee_id = var_employee_id
and overtime_start > in_bgin_date
and overtime_start <= in_end_date
and overtime_end >= in_begin_date
and overtime_end <= in_end_date
Group by overtime_sn;
begin
open cur_employee; --打開遊標,讀取員工的資料
loop
fetch cur_employee into cur_employee_id,cur_employee_name,cur_class_id;
exit when cur_employee%notfound;

select class_name, --讀取此員工的班表資料
cycle_flag,
cycle_time,
cycle_num,
start_flag,
end_flag
into :c_class_name,
:c_cycle_flag,
:n_cycle_time,
:c_start_flag,
:c_end_flag
from class_master
where corp_id = in_corp_id
and class_id = cur_class_id
and class_start >= in_start_time
and class_start >= in_end_time
and class_end <= in_start_time
and class_end <= in_end_time;);


if (c_start_flag = "N" and c_end_flag = "N" )
or (c_start_flag = "Y" and c_end_flag = "N" )
or (c_start_flag = "N" and c_end_flag = "Y" ) then
/*************************
在員工上下班都不需要打卡或上下班隻需打一次卡的情況下,員工的加班信息和
請假信息都根據加班單和請假單計算
*************************/
/**********
處理員工上下班都不用打卡的記錄
員工上下班都不打卡,系統沒有記錄或不需要讀取員工的打卡記錄
系統系統處理員工加班和請假的資料就好了
**********/
open cur_fur;
loop
fetch cur_fur into var_furlough_sn,var_furlough_time;
exit when cur_fur%notfound;
/****此間計算請假期間薪資的發放的明細********/
/**根據薪資發放比率計算薪資*/
select furlough_rate,furlough_type
into :var_furlough_rate,:var_furlough_type
from work_furlough
where corp_id = in_corp_id
and furlough_sn = var_furlough_sn;
end loop
close cur_fur;

open cur_over;
loop
fetch cur_over into var_overtime_sn,var_overtime_time;
exit then cur_over%notfound;
/****此間計算加班和加班薪資發放的明細*********/
/****根據薪資發放比率計算薪資*/
select over_rate,over_type
into :var_overtime_rate,:var_overtime_type
from work_overtime
where corp_id = in_corp_id
and overtime_sn = var_overtime_sn;
end loop;
close cur_over;
end if;
if (c_start_flag = "Y" and c_end_flag = "N")
or (c_start_flag = "N" and c_end_flag = "Y")
or (c_start_flag = "Y" and c_end_flag = "Y")  then
/*************************
在員工上下班都需要打卡或上下班隻需打一次卡的情況下,
都需要讀取員工的打卡記錄以判斷員工的曠工等情況
*************************/
open cur_card;--打開遊標,讀取相應員工的打卡記錄
loop
fetch cur_card into cur_class_num,cur_senior_flag,cur_holiday_flag,cur_card_start,cur_card_end;
exit when cur_card%notfound;
--讀取相應的班表記錄
select work_flag,
work_start,
work_end,
holiday_flag,
overtime_flag,
senior_flag
into :c_work_flag,
:d_work_start,
:d_work_end,
:c_holiday_flag,
:c_overtime_flag,
:c_senior_flag
from class_detail
where corp_id = in_corp_id
and class_id = cur_class_id 
and class_index = cur_class_num;

if c_start_flag = "Y" and c_end_flag = "N" then --上班需要打卡,下班不需要打卡
if (cur_card_start >= d_work_start) or c_senior_flag = 1 then --上班打卡時間早於上班時間,屬於正常上班
n_count = n_count + 1;--正常上班次數加1
elsif  --上班打卡時間晚於上班時間,計算曠工時間

select (cur_card_start - d_work_start)*24
into temp_num --此次曠工時間,精確到小時
from dual;
n_after_time = n_after_time + temp_num; --記錄到總曠工時間中
end if;
end if;

if c_end_flag = "Y" and c_start_flag = "N" then --下班需要打卡,上班不需要打卡
if (cur_card_end =< d_work_end) or c_senior_flag = 2  then --下班打卡時間晚於下班時間,屬於正常上班
n_count = n_count + 1;--正常上班次數加1
else --下班打卡時間早於下班時間,計算曠工時間
select (d_work_start - cur_card_end)*24
into temp_num --此次曠工時間,精確到小時
from dual;
n_after_time = n_after_time + temp_num; --記錄到總曠工時間中
end if;
end if;

if c_start_flag = "Y" and c_end_flag = "Y" then --上下班都需要打卡

if cur_card_start >= d_work_start and cur_card_end <= d_work_end then --正常上班
n_count = n_count + 1;--正常上班次數加1
if c_overtime_flag = "Y" then --有加班
select (d_work_start - cur_card_start) * 24 + (cur_card_end - d_work_start) * 24
into :temp_over_num --此次上班加班時間
from dual;
n_over_time = n_over_time + temp_over_num;
/**************
加班根據加班的時間和填寫的加班單信息,找出加班的類型,
將相應的時間記錄到相應的加班類型上去,以方便計算薪資
**************/
end if;
else --不正常上班
if cur_card_start < d_work_start then--上班時間晚於班表時間
select (cur_card_start - d_work_start)*24
into temp_num --此次曠工時間,精確到小時
from dual;
if c_holiday_flag = "Y" then --有加班單
n_holi_time = n_holi_time + temp_num;--記錄到總請假時間中
else
n_after_time = n_after_time + temp_num; --記錄到總曠工時間中
end if;
end if;
if cur_card_end > d_work_end then --下班時間早於班表時間
select (d_work_start - cur_card_end)*24
into temp_num --此次曠工時間,精確到小時
from dual;
if c_holiday_flag = "Y" then --有加班單
n_holi_time = n_holi_time + temp_num;--記錄到總請假時間中
else
n_after_time = n_after_time + temp_num; --記錄到總曠工時間中
end if;
end if;
/**************
請假根據請假的時間和填寫的請假單,找出請假的類型,
將相應的時間記錄到相應的請假類型上去,以方便計算薪資
**************/
end if;
end loop;
close cur_employee;
end if;
end loop;
close cur_employee;
end;