1 package body pay_nz_holidays_2003 as
2 -- $Header: pynzhl2003.pkb 120.2.12010000.3 2008/09/12 12:20:38 lnagaraj ship $
3 --
4 -- Copyright (C) 1999 Oracle Corporation
5 -- All Rights Reserved
6 --
7 -- Change List
8 -- ===========
9 --
10 -- Date Author Reference Description
11 -- -----------+-----------+---------+--------------------------------------------
12 -- 03 FEB 2003 sclarke 3417767 Adjustments now taken off entitlement before accrual
13 -- 19 NOV 2003 sclarke 3064179 Created
14 -- 04 DEC 2003 sclarke Updates after testing
15 -- 30 DEC 2003 sclarke Changed parameters to annual_leave_calc_1
16 -- 08 JAN 2004 sclarke Removed tables of records
17 -- 28 JAN 2004 sclarke 3392071 changed get_accrual_entitlement logic regarding
18 -- adjustment elements
19 -- 11 FEB 2004 sclarke 3435633 get_working_days_balance cursor changed
20 -- so that the max ass action fetches
21 -- the currently processing action
22 -- 12 FEB 2004 sclarke 3435633 Need to handle when viewing accruals
23 -- for actual time worked and there are no runs
24 -- in period. Better error handling required.
25 -- 12 Mar 2004 sclarke 3547116 Recurring absences
26 -- 02 APR 2004 sclarke 3541500 Anniversary Date is not moved the initial 7 days
27 -- 15 APR 2004 sclarke 3541500 Do not accrue leave on the initial 7 days
28 -- 11 MAY 2004 puchil 3592923 Performance fix for cursor csr_ass_action.
29 -- 3620398 1) Changed function get_working_days_balance
30 -- 2) Added return statement to function get_previous_rate
31 -- 13 MAY 2004 statkar 3620398 Reverted back the changes to
32 -- csr_ass_action done in the previous version
33 -- 21 MAY 2004 sclarke 3632528 added extra action_status to get_working_days_balance
34 -- 11 JUN 2004 puchil 3654766 Changed the cursor csr_get_rate to return the value
35 -- based on the assignment_action_id.
36 -- 07 JUL 2004 puchil 3654766 Changed the cursor csr_get_rate to consider
37 -- leaves spanning multiple pay periods.
38 -- 23 JUL 2004 bramajey 3608752 Added functions is_parental_leave_taken,get_entitled_amount
39 -- ,get_recur_abs_prev_period and get_leave_taken
40 -- 17 AUG 2004 bramajey 3608752 Modified cursor csr_parental_leave_taken
41 -- and csr_get_count_leave.
42 -- 05 AUG 2005 rpalli 4536217 As part of bug 4536217(performance issue):
43 -- Added overloaded function determine_work_week.
44 -- Added is_leap_year function.
45 -- Removed eligible_for_accrual function.
46 -- Modified calculate_daily_accrual function.
47 -- Modified daily_accrual_loop function.
48 -- 02 SEP 2005 snekkala 4259438 Modified cursor csr_hire_date as Part of Performance
49 -- Modified csr_ass_action in get_working_days_balance
50 -- for performance
51 -- 21 JUL 2008 vamittal 7254820 Modified function annual_leave_rate_calc_2 and get_annual_leave_percentage.
52 -- 30-Jul-2008 avenkatk 7260523 Modified function annual_leave_rate_calc_1 - condition for months_between
53 -- ------------------------------------------------------------------------------
54 --
55 g_package constant varchar2(60) := 'pay_nz_holidays_2003.';
56 g_debug boolean;
57 g_legislation_code constant varchar2(3) := 'NZ';
58 g_unpaid_absence_category constant varchar2(4) := 'NZUL';
59 --
60 -- An absence is taken given a start and end date with the two days the given
61 -- dates fall on being included in the absence taken. Unpaid absences greater
62 -- than 1 week move the anniversary date. To determine the 1 weeks duration
63 -- we are subtracting the start_date from the end_date of the absence and moving
64 -- the anniversary when the difference is > than 6 days (Note, not 7 days).
65 --
66 g_unpaid_absence_days constant number := 6;
67 --
68 type t_person_rec2 is record
69 (person_id number
70 ,calculation_date date
71 ,anniversary_start_date date
72 ,anniversary_end_date date
73 ,years_of_service number
74 );
75 type t_person_tab2 is table of t_person_rec2 index by binary_integer;
76
77 p_anniversary_table2 t_person_tab2;
78 --
79 -- Cursor to retrieve days where the assignment
80 -- is not active
81 --
82 cursor csr_inactive_days
83 (p_assignment_id number
84 ,p_period_sd date
85 ,p_period_ed date
86 ) is
87 -- need to add 1 as to include the finale day
88 -- e.g. 01-JAN-2000 minus 01-JAN-2000 is actually 1 day but the arithmetic returns 0
89 select sum(asg.effective_end_date - asg.effective_start_date + 1) days_inactive
90 from per_assignments_f asg
91 , per_assignment_status_types ast
92 where asg.assignment_id = p_assignment_id
93 and ((asg.effective_start_date between p_period_sd and p_period_ed
94 or asg.effective_end_date between p_period_sd and p_period_ed)
95 or (p_period_sd between asg.effective_start_date and asg.effective_end_date))
96 and asg.assignment_status_type_id = ast.assignment_status_type_id
97 and ast.per_system_status <> 'ACTIVE_ASSIGN';
98 --
99 cursor csr_person_id
100 (p_assignment_id number
101 ,p_calculation_date date
102 ) is
103 select person_id
104 from per_assignments_f
105 where assignment_id = p_assignment_id
106 and p_calculation_date between effective_start_date and effective_end_date;
107 --
108 -- Cursor to retrieve the input value of
109 -- element entry for LEAVE_INFORMATION -> STANDARD WORK WEEK
110 --
111 cursor csr_work_week
112 (p_assignment_id number
113 ,p_effective_date date
114 ) is
115 select nvl(to_number(val.screen_entry_value),0)
116 from pay_element_entries_f ent
117 , pay_element_types_f el
118 , pay_input_values_f piv
119 , pay_element_entry_values_f val
120 , pay_element_links_f link
121 where ent.assignment_id = p_assignment_id
122 and ent.element_entry_id = val.element_entry_id
123 and p_effective_date between ent.effective_start_date and ent.effective_end_date
124 and ent.element_link_id = link.element_link_id
125 and link.element_type_id = el.element_type_id
126 and el.element_name = 'Leave Information'
127 and el.legislation_code = g_legislation_code
128 and p_effective_date between el.effective_start_date and el.effective_end_date
129 and el.element_type_id = piv.element_type_id
130 and piv.name = 'Standard Work Week'
131 and p_effective_date between piv.effective_start_date and piv.effective_end_date
132 and val.input_value_id = piv.input_value_id
133 and p_effective_date between val.effective_start_date and val.effective_end_date;
134 --
135 -- Cursor to retrieve the input value of
136 -- element entry for Leave Information -> USE ASSIGNMENT WORK HOURS
137 --
138 cursor csr_use_asg_hours
139 (p_assignment_id number
140 ,p_effective_date date
141 ) is
142 select nvl(val.screen_entry_value,'Y')
143 from pay_element_entries_f ent
144 , pay_element_types_f el
145 , pay_input_values_f piv
146 , pay_element_entry_values_f val
147 , pay_element_links_f link
148 where ent.assignment_id = p_assignment_id
149 and ent.element_entry_id = val.element_entry_id
150 and p_effective_date between ent.effective_start_date and ent.effective_end_date
151 and ent.element_link_id = link.element_link_id
152 and link.element_type_id = el.element_type_id
153 and el.element_name = 'Leave Information'
154 and el.legislation_code = g_legislation_code
155 and p_effective_date between el.effective_start_date and el.effective_end_date
156 and el.element_type_id = piv.element_type_id
157 and piv.name = 'Use Assignment Working Hours'
158 and p_effective_date between piv.effective_start_date and piv.effective_end_date
159 and val.input_value_id = piv.input_value_id
160 and p_effective_date between val.effective_start_date and val.effective_end_date;
161
162 --
163 -- Comparison on dates uses the > 6
164 -- as an alternative to => 7
165 --
166 cursor csr_get_unpaid_absences
167 (p_person_id per_all_people_f.person_id%type
168 ,p_start_date date
169 ,p_end_date date
170 ) is
171 select ab.absence_attendance_id
172 , ab.person_id
173 , ab.absence_days
174 , ab.absence_hours
175 , abt.hours_or_days
176 , ab.date_start
177 , ab.date_end
178 , ((ab.date_end - ab.date_start) - g_unpaid_absence_days) add_days
179 -- however, do not move the initial qualifying period
180 from per_absence_attendances ab
181 , per_absence_attendance_types abt
182 where ab.absence_attendance_type_id = abt.absence_attendance_type_id
183 and ab.person_id = p_person_id
184 and abt.absence_category = g_unpaid_absence_category
185 and ab.date_start between p_start_date and p_end_date
186 and ((ab.date_end - ab.date_start) > g_unpaid_absence_days);
187 --
188 -----------------------------
189 -- GET_ACCRUAL_PLAN_UOM
190 -----------------------------
191 function get_accrual_plan_uom
192 (p_accrual_plan_id number
193 ) return varchar2 is
194 --
195 l_uom varchar2(60);
196 --
197 cursor csr_get_uom
198 (p_accrual_plan_id number
199 ) is
200 select accrual_units_of_measure
201 from pay_accrual_plans
202 where accrual_plan_id = p_accrual_plan_id;
203 --
204 begin
205 open csr_get_uom(p_accrual_plan_id);
206 fetch csr_get_uom into l_uom;
207 close csr_get_uom;
208 --
209 return l_uom;
210 end get_accrual_plan_uom;
211
212 ---------------------------
213 -- GET_WORKING_DAYS_BALANCE
214 ---------------------------
215 --
216 function get_working_days_balance
217 (p_assignment_id in number
218 ,p_effective_date in date
219 ) return number is
220
221 l_balance_name constant varchar2(100) := 'Days or Hours Worked';
222 l_dimension_name constant varchar2(100) := '_ASG_PTD';
223 l_value number;
224 l_defined_balance_id number;
225 l_procedure constant varchar2(100) := g_package||'get_working_days_balance';
226
227 cursor csr_def_bal
228 (p_balance_name varchar2
229 ,p_dimension_name varchar2
230 )is
231 select defined_balance_id
232 from pay_defined_balances pdb
233 , pay_balance_types pbt
234 , pay_balance_dimensions dim
235 where pdb.balance_type_id = pbt.balance_type_id
236 and pdb.balance_dimension_id = dim.balance_dimension_id
237 and pbt.balance_name = p_balance_name
238 and dim.dimension_name = p_dimension_name
239 and dim.legislation_code = g_legislation_code
240 and pbt.legislation_code = g_legislation_code;
241
242 /* Bug 4259438 : Modified cursor as part of performance */
243 CURSOR csr_ass_action
244 (p_assignment_id NUMBER
245 ,p_effective_date DATE
246 ) IS
247 SELECT MAX(paa.assignment_action_id)
248 FROM pay_assignment_actions paa
249 , per_assignments_f paf
250 , pay_payrolls_f ppf
251 , pay_payroll_actions ppa
252 , per_time_periods ptp
253 WHERE paf.assignment_id = p_assignment_id
254 AND ppa.action_type in ('R','Q')
255 AND p_effective_date BETWEEN paf.effective_start_date
256 AND paf.effective_end_date
257 AND ppa.payroll_action_id = paa.payroll_action_id
258 AND ppf.payroll_id = paf.payroll_id
259 AND ppa.time_period_id = ptp.time_period_id
260 AND ppf.payroll_id = ppa.payroll_id
261 AND ppa.effective_date BETWEEN ptp.start_date
262 AND ptp.end_date
263 AND p_effective_date BETWEEN ptp.start_date
264 AND ptp.end_date
265 AND ppf.payroll_id = ppa.payroll_id
266 AND ppf.payroll_id = ptp.payroll_id
267 AND paf.assignment_id = paa.assignment_id
268 AND paa.action_status IN ('C','P','U')
269 AND ppa.action_status IN ('C','P','U')
270 GROUP BY paa.assignment_action_id
271 HAVING paa.assignment_action_id = MAX(paa.assignment_action_id);
272
273 --
274 l_assignment_action_id number;
275 begin
276 --
277 g_debug := hr_utility.debug_enabled;
278 --
279 if g_debug then
280 hr_utility.set_location(l_procedure, 0);
281 end if;
282 --
283 open csr_ass_action(p_assignment_id, p_effective_date);
284 fetch csr_ass_action into l_assignment_action_id;
285 close csr_ass_action;
286 --
287 if g_debug then
288 hr_utility.set_location(l_procedure, 10);
289 hr_utility.trace('l_assignment_action_id = *'||to_char(nvl(l_assignment_action_id,99))||'*');
290 end if;
291 --
292 if l_assignment_action_id is null then
293 hr_utility.set_message(801,'HR_NZ_WORKING_HRS_MISSING');
294 hr_utility.raise_error;
295 end if;
296 --
297 open csr_def_bal(l_balance_name, l_dimension_name);
298 fetch csr_def_bal into l_defined_balance_id;
299 if csr_def_bal%notfound then
300 if g_debug then
301 hr_utility.set_location(l_procedure, 7);
302 end if;
303 --
304 l_value := 0;
305 else
306 --
307 l_value := pay_balance_pkg.get_value
308 (p_defined_balance_id =>l_defined_balance_id
309 ,p_assignment_action_id => l_assignment_action_id
310 );
311 end if;
312 close csr_def_bal;
313 --
314 --
315 ----
316 --l_value := pay_balance_pkg.get_value
317 --(p_defined_balance_id => l_defined_balance_id
318 --,p_assignment_id => p_assignment_id
319 --,p_virtual_date => p_effective_date
320 --);
321 --
322 if g_debug then
323 hr_utility.set_location(l_procedure,999);
324 end if;
325 --
326 return l_value;
327 end get_working_days_balance;
328 ---------------------------
329 -- GET_BALANCE
330 ---------------------------
331 --
332 function get_balance
333 (p_assignment_id in number
334 ,p_effective_date in date
335 ,p_balance_name varchar2
336 ,p_dimension_name varchar2
337 ) return number is
338
339 l_value number;
340 l_defined_balance_id number;
341 l_procedure constant varchar2(100) := g_package||'get_balance';
342
343 cursor csr_def_bal
344 (p_balance_name varchar2
345 ,p_dimension_name varchar2
346 )is
347 select defined_balance_id
348 from pay_defined_balances pdb
349 , pay_balance_types pbt
350 , pay_balance_dimensions dim
351 where pdb.balance_type_id = pbt.balance_type_id
352 and pdb.balance_dimension_id = dim.balance_dimension_id
353 and pbt.balance_name = p_balance_name
354 and dim.dimension_name = p_dimension_name
355 and dim.legislation_code = g_legislation_code
356 and pbt.legislation_code = g_legislation_code;
360 fetch csr_def_bal into l_defined_balance_id;
357 begin
358 --
359 open csr_def_bal(p_balance_name, p_dimension_name);
361 close csr_def_bal;
362 --
363 l_value := nvl(pay_balance_pkg.get_value
364 (p_defined_balance_id => l_defined_balance_id
365 ,p_assignment_id => p_assignment_id
366 ,p_virtual_date => p_effective_date
367 ),0);
368 --
369 return l_value;
370 end get_balance;
371 --
372 --------------------
373 -- GET_STANDARD_WORK_WEEK
374 --------------------
375 --
376 function get_standard_work_week
377 (p_assignment_id in number
378 ,p_effective_date in date
379 ) return number is
380 l_procedure constant varchar2(100) := g_package||'get_standard_week';
381 l_standard_days_per_week number;
382 begin
383 --
384 open csr_work_week(p_assignment_id, p_effective_date);
385 fetch csr_work_week
386 into l_standard_days_per_week;
387 if csr_work_week%notfound then
388 l_standard_days_per_week := 0;
389 end if;
390 close csr_work_week;
391 --
392 return l_standard_days_per_week;
393 end get_standard_work_week;
394 --
395 -------------------
396 -- MOVE_ANNIVERSARY
397 -------------------
398 --
399 function move_anniversary
400 (p_person_id number
401 ,p_calculation_date date
402 ,p_start_date in out nocopy date
403 ,p_end_date in out nocopy date
404 ) return date is
405 --
406 g_absences_found boolean;
407 l_tmp_anniversary_end_date date;
408 l_procedure constant varchar2(60) := g_package||'move anniversary';
409 l_date_moved boolean;
410 --
411 begin
412 --
413 g_debug := hr_utility.debug_enabled;
414 --
415 l_tmp_anniversary_end_date := p_end_date;
416 if g_debug then
417 hr_utility.set_location(l_procedure, 0);
418 end if;
419 --
420 if g_debug then
421 hr_utility.set_location('Entering '||l_procedure,1);
422 hr_utility.set_location('p_start_date '||to_char(p_start_date,'DD-MON-YYYY'),1);
423 hr_utility.set_location('p_end_date '||to_char(p_end_date,'DD-MON-YYYY'),1);
424 end if;
425 --
426 -- Check for more absence unless we have gone beyond the calculation date
427 while not l_tmp_anniversary_end_date > p_end_date
428 loop
429 if g_debug then
430 hr_utility.set_location(l_procedure,2);
431 end if;
432 -- initialise variable to false before we actually check absences
433 g_absences_found := false;
434 --
435 -- now check for absences
436 for abs_rec in csr_get_unpaid_absences(p_person_id, p_start_date, p_end_date)
437 loop
438 -- add the number of days the absence was taken over
439 g_absences_found := true;
440 l_tmp_anniversary_end_date := l_tmp_anniversary_end_date + abs_rec.add_days;
441 end loop;
442
446 if g_debug then
443 if g_absences_found then
444 l_tmp_anniversary_end_date := move_anniversary(p_person_id, p_calculation_date, p_end_date, l_tmp_anniversary_end_date);
445 else
447 hr_utility.set_location('no absences',1);
448 end if;
449 --
450 -- exit when absence not found
451 exit;
452 end if;
453 end loop;
454 --
455 if g_debug then
456 hr_utility.set_location(l_procedure,999);
457 end if;
458 --
459 return l_tmp_anniversary_end_date;
460 end move_anniversary;
461 --
462 ---------------------------
463 -- INITIALISE_ANNIVERSARIES
464 ---------------------------
465 -- Sets the first anniversary start date for an employee
466 -- If p_service_date is not entered then the first anniversary start date
467 -- will be set to the hire date of the employee...
468 -- p_service_date is provided so continuous_service_date can be considered
469 -- it is expected that this parameter has already been validated.
470 --
471 procedure initialise_dates
472 (p_assignment_id in number
473 ,p_service_start_date in out nocopy date
474 ,p_anniversary_start_date out nocopy date
475 ) is
476 l_procedure constant varchar2(60) := g_package||'initialise_anniversaries';
477 l_anniversary_start_date date;
478 --
479 -- Bug 4259438 : Modified the Select clause of the cursor as part of Performance
480 --
481 CURSOR csr_hire_date
482 IS
483 SELECT date_start
484 FROM per_periods_of_service pps
485 , per_assignments_f paf
486 WHERE pps.period_of_service_id = paf.period_of_service_id
487 AND pps.person_id = paf.person_id
488 AND paf.assignment_id = p_assignment_id;
489 --
490 -- End Bug 4259438
491 --
492 begin
493 g_debug := hr_utility.debug_enabled;
494 if g_debug then
495 hr_utility.set_location(l_procedure, 0);
496 hr_utility.trace('..p_assignment_id = '||to_char(nvl(p_assignment_id,0)));
497 hr_utility.trace('..p_service_start_date = '||to_char(p_service_start_date,'DD/MM/RRRR'));
498 end if;
499 --
500 -- If the service start date is entered
501 -- then we assume validation of dates has
502 -- already been done.
503 --
504 if p_service_start_date is null then
505 --
506 -- get hire_date and termination_date for future use
507 open csr_hire_date;
508 fetch csr_hire_date into l_anniversary_start_date;
509 close csr_hire_date;
510 --
511 p_service_start_date := l_anniversary_start_date;
512 else
513 l_anniversary_start_date := p_service_start_date;
514 end if;
515 --
516 p_anniversary_start_date := l_anniversary_start_date;
517 --
518 if g_debug then
519 hr_utility.trace('..l_anniversary_start_date = '||to_char(l_anniversary_start_date,'DD/MM/RRRR'));
520 hr_utility.set_location(l_procedure, 999);
521 end if;
522 end initialise_dates;
523 --
524 --------------------------
525 -- CACE_ANNIVERSARY_DETAILS
526 --------------------------
527 --
528 -- This function fetches anniversary dates
529 -- for the lifetime of the employee up to the calculation date
530 -- Since this function is for the accrual formula it is assumed
531 -- the data passed in has already been validated so we do no
532 -- validate again.
533 --
534 function cache_anniversary_details
535 (p_payroll_id in number
536 ,p_assignment_id in number
540 ,p_anniversary_start_date out nocopy date
537 ,p_accrual_plan_id in number
538 ,p_calculation_date in date
539 ,p_service_start_date in date
541 ,p_anniversary_end_date out nocopy date
542 ,p_years_of_service out nocopy number
543 ) return number is
544 l_procedure constant varchar2(60) := g_package||'cache_anniversary_details';
545 l_person_counter integer;
546 l_counter integer;
547 l_anniversary_start_date date;
548 l_anniversary_end_date date;
549 l_years_of_service number;
550 l_person_id number;
551 l_date_start date;
552 l_cached boolean;
553 l_anniversary_not_found boolean;
554 l_actual_termination_date date;
555 l_calculation_date date;
556 l_service_start_date date;
557 begin
558 l_person_counter := 1;
559 l_counter := 1;
560 l_years_of_service := 0;
561 g_debug := hr_utility.debug_enabled;
562 if g_debug then
563 hr_utility.set_location(l_procedure, 0);
564 end if;
565 --
566 open csr_person_id(p_assignment_id, p_calculation_date);
567 fetch csr_person_id into l_person_id;
568 close csr_person_id;
569 --
570 if g_debug then
571 hr_utility.trace('l_person_id.=.'||to_char(l_person_id));
572 end if;
573 --
574 -- Has the information been cached?
575 -- Note: Anniversaries apply to the person... not each assignment
576 --
577 if (p_anniversary_table2.count > 0) then
578 for x in 1..p_anniversary_table2.count loop
579 if (p_anniversary_table2(x).person_id = l_person_id)
580 and
581 (p_anniversary_table2(x).calculation_date = p_calculation_date) then
582 l_cached := true;
583 else
584 l_cached := false;
585 end if;
586 end loop;
587 else
588 l_cached := false;
589 end if;
590 --
591 if not l_cached then
592 --
593 -- Anniversaries have not yet been cached
594 --
595 if g_debug then
596 hr_utility.set_location(l_procedure, 30);
597 end if;
598 --
599 -- Initialise the first anniversary
600 -- and start from there.
601 --
602 initialise_dates
603 (p_assignment_id => p_assignment_id
604 ,p_service_start_date => l_service_start_date
605 ,p_anniversary_start_date => l_anniversary_start_date
606 );
607 l_anniversary_end_date := l_anniversary_start_date;
608 --
609 if g_debug then
610 hr_utility.set_location(l_procedure, 40);
611 hr_utility.trace('l_anniversary_start_date..=.'||to_char(l_anniversary_start_date));
612 hr_utility.trace('p_calculation_date........=.'||to_char(p_calculation_date));
613 end if;
614 --
615 -- Initialise Person Table
616 --
617 if p_anniversary_table2.exists(1) then
618 --
619 -- Some records exist... we have already confirmed
620 -- that one does not exist for this person above
621 -- so set the person counter index after the last
622 --
623 l_person_counter := p_anniversary_table2.last + 1;
624 --
625 if g_debug then
626 hr_utility.set_location(l_procedure, 45);
627 end if;
628 end if;
629 --
630 --
631 -- Start at l_anniversary_start and loop thru until the next anniversary is after calculation date
632 --
633 while (not l_anniversary_start_date > p_calculation_date) and (l_anniversary_end_date <= p_calculation_date)
634 loop
635 --
636 -- Initialise Anniversary Table
637 --
638 -- Note, the anniversary dates cannot be on the same day
639 -- Assuming no time off without pay, the anniversary end date
640 -- will actually be 12mths - 1 day from the anniversary start date
641 --
642 p_anniversary_table2(l_person_counter).person_id := l_person_id;
643 p_anniversary_table2(l_person_counter).calculation_date := p_calculation_date;
644 --
645 if l_service_start_date = l_anniversary_end_date then
646 p_anniversary_table2(l_person_counter).anniversary_start_date := l_anniversary_end_date;
647 p_anniversary_table2(l_person_counter).anniversary_end_date := add_months(l_anniversary_end_date,12) - 1;
648 else
649 p_anniversary_table2(l_person_counter).anniversary_start_date := l_anniversary_end_date + 1;
650 p_anniversary_table2(l_person_counter).anniversary_end_date := add_months(l_anniversary_end_date,12);
651 end if;
652 p_anniversary_table2(l_person_counter).years_of_service := l_years_of_service;
653 --
654 p_anniversary_table2(l_person_counter).anniversary_end_date :=
655 move_anniversary
656 (l_person_id
657 , p_calculation_date
658 , p_anniversary_table2(l_person_counter).anniversary_start_date
659 , p_anniversary_table2(l_person_counter).anniversary_end_date
660 );
661 if g_debug then
662 hr_utility.set_location(l_procedure, 50);
666 hr_utility.trace('years_of_service........=.'||to_char(p_anniversary_table2(l_person_counter).years_of_service));
663 hr_utility.trace('........................');
664 hr_utility.trace('anniversary_start_date..=.'||to_char(p_anniversary_table2(l_person_counter).anniversary_start_date));
665 hr_utility.trace('anniversary_end_date....=.'||to_char(p_anniversary_table2(l_person_counter).anniversary_end_date));
667 hr_utility.trace('........................');
668 end if;
669 --
670 -- Has the next anniversary been moved after the calculation date
671 if l_anniversary_end_date > p_calculation_date then
672 if g_debug then
673 hr_utility.set_location(l_procedure, 60);
674 end if;
675 exit;
676 end if;
677 l_anniversary_start_date := p_anniversary_table2(l_person_counter).anniversary_start_date;
678 l_anniversary_end_date := p_anniversary_table2(l_person_counter).anniversary_end_date;
679 --
680 -- Years of service cannot equal to l_counter
681 -- because it can be zero, whereas the index for a plsql table
682 -- starts at 1
683 --
684 l_years_of_service := l_years_of_service + 1;
685 --
686 -- Increment table counter and initialise next anniversaries
687 --
688 l_counter := l_counter + 1;
689 l_person_counter := l_person_counter + 1;
690 --
691 if g_debug then
692 hr_utility.set_location(l_procedure, 70);
693 end if;
694 --
695 end loop;
696 p_anniversary_start_date := l_anniversary_start_date;
697 p_anniversary_end_date := l_anniversary_end_date;
698 --
699 -- Years of service is zero until 1 complete year of employment is reached
700 -- This being the case then because the table counter is initialised at 1
701 -- we need to subtract 1 from the count to get the correct result...
702 -- unless of course the counter is less than 1 (which can happen when the
703 -- calculation date is on the service_start_date
704 --
705 if l_counter > 0 then
706 p_years_of_service := l_counter - 1;
707 else
708 p_years_of_service := 0;
709 end if;
710 --
711 l_cached := true;
712 end if;
713 --
714 if l_cached then
715 for x in 1..p_anniversary_table2.count loop
716 if (p_anniversary_table2(x).person_id = l_person_id)
717 then
718 --
719 -- Information has been cached
720 -- so we retrieve it from the cache
721 --
722 if g_debug then
723 hr_utility.set_location(l_procedure||' CACHE', 10);
724 end if;
725 --
726 -- looking for where the calculation_date is between ann_start and ann_end
727 -- for the given person
728 --
729 if ((p_calculation_date > p_anniversary_table2(x).anniversary_start_date)
730 or(p_calculation_date = p_anniversary_table2(x).anniversary_start_date))
731 and
732 ((p_calculation_date < p_anniversary_table2(x).anniversary_end_date)
733 or (p_calculation_date = p_anniversary_table2(x).anniversary_end_date))
734 then
735 if g_debug then
736 hr_utility.set_location(l_procedure||' CACHE', 20);
737 end if;
738 p_anniversary_start_date := p_anniversary_table2(x).anniversary_start_date;
739 p_anniversary_end_date := p_anniversary_table2(x).anniversary_end_date;
740 p_years_of_service := p_anniversary_table2(x).years_of_service;
741 if g_debug then
742 hr_utility.set_location('p_anniversary_start_date = '||to_char(p_anniversary_start_date,'DD-MON-YYYY'), 20);
743 hr_utility.set_location('p_anniversary_end_date.. = '||to_char(p_anniversary_end_date,'DD-MON-YYYY'), 20);
744 hr_utility.set_location('p_years_of_service...... = '||to_char(p_years_of_service), 20);
745 end if;
746 --
747 -- Exit loop so that the counter is not incremented
748 --
749 exit;
750 end if; -- p_calculation_date
751 end if;
752 end loop;
753 --
754 end if;
755 --
756 if g_debug then
757 hr_utility.set_location(l_procedure,999);
758 end if;
759 --
760 return 0;
761 --
762 end cache_anniversary_details;
763 --
764 --------------------------
765 -- CALCULATE_DAILY_ACCRUAL
766 --------------------------
767 --
768 function calculate_daily_accrual
769 (p_person_id in number
770 ,p_accrual_plan_id in number
771 ,p_start_date in date
772 ,p_end_date in date
773 ,p_annual_accrual in number
774 ,p_work_week in number
775 )
776 return number is
777 --
778 l_days number;
779 l_daily_accrual number;
780 l_days_inactive number;
781 l_days_total number;
782 l_days_unpaid number;
783 l_procedure constant varchar2(60) := g_package||'calculate_daily_accrual';
784 --
785 begin
786 g_debug := hr_utility.debug_enabled;
787 if g_debug then
791 end if;
788 hr_utility.set_location(l_procedure, 0);
789 hr_utility.trace('p_start_date = '||to_char(p_start_date,'DD-MON-YYYY'));
790 hr_utility.trace('p_end_date...= '||to_char(p_end_date,'DD-MON-YYYY'));
792 --
793 -- 1.
794 -- Get the number of days between start and end
795 -- we include the end day which is why we add 1
796 l_days := (p_end_date + 1) - p_start_date;
797 --
798 --
799 -- 2.
800 -- Get the number of days of unpaid absence where the total each seperate absence was > 1 week
801 -- between these 2 dates
802 l_days_unpaid := 0;
803 --
804 for abs_rec in csr_get_unpaid_absences(p_person_id, p_start_date, p_end_date)
805 loop
806 l_days_unpaid := l_days_unpaid + abs_rec.add_days;
807 end loop;
808 --
809 -- total = 1-2
810 l_days_total := l_days - l_days_unpaid;
811 --
812 -- The Annual Accrual is held in 'work weeks' therefore
813 -- we need the multiplication by work week
814 l_daily_accrual := (p_annual_accrual * p_work_week)/l_days_total;
815
816 if g_debug then
817 hr_utility.trace('l_days...........= '||to_char(l_days));
818 hr_utility.trace('l_days_unpaid....= '||to_char(l_days_unpaid));
819 hr_utility.trace('l_days_total.....= '||to_char(l_days_total));
820 hr_utility.trace('l_daily_accrual..= '||to_char(l_daily_accrual));
821 end if;
822 --
823 if g_debug then
824 hr_utility.set_location(l_procedure, 999);
825 end if;
826 --
827 return l_daily_accrual;
828 --
829 end calculate_daily_accrual;
830 --
831 ----------------------
832 -- DETERMINE_WORK_WEEK
833 ----------------------
834 --
835 function determine_work_week
836 (p_assignment_id in number
837 ,p_current_day in date
838 ,p_uom in varchar2
839 ,p_annual_accrual in number
840 ,p_chg_asg_hours IN boolean
841 ,p_asg_hours IN number
842 ,p_freq IN varchar2
843 ) return number is
844 l_procedure constant varchar2(60) := g_package||'determine_work_week';
845 l_work_week number;
846 l_work_frequency varchar2(30);
847 l_use_asg_hours varchar2(3);
848 l_weeks_in_period number;
849 l_days_in_period number;
850 l_working_time number;
851 --
852 cursor csr_asg_hours(p_effective_date date) is
853 select normal_hours
854 , frequency
855 from per_assignments_f
856 where assignment_id = p_assignment_id
857 and p_effective_date between effective_start_date and effective_end_date;
858 --
859 cursor csr_get_days_in_period is
860 select ptp.end_date - ptp.start_date days_in_period
861 from per_time_periods ptp
862 , per_assignments_f paf
863 where paf.assignment_id = p_assignment_id
864 and p_current_day between paf.effective_start_date and paf.effective_end_date
865 and paf.payroll_id = ptp.payroll_id
866 and p_current_day between ptp.start_date and ptp.end_date;
867 --
868 begin
869 l_use_asg_hours := 'N';
870 g_debug := hr_utility.debug_enabled;
871 if g_debug then
872 hr_utility.set_location(l_procedure, 0);
873 hr_utility.trace('p_assignment_id = '||to_char(p_assignment_id));
874 hr_utility.trace('p_current_day.. = '||to_char(p_current_day,'DD-MON-YYYY'));
875 end if;
876 --
877 -- Check how to calculate accrual
878 --
879 open csr_use_asg_hours(p_assignment_id, p_current_day);
880 fetch csr_use_asg_hours into l_use_asg_hours;
881 close csr_use_asg_hours;
882 --
883 if g_debug then
884 hr_utility.trace('l_use_asg_hours = '||l_use_asg_hours);
885 end if;
886
887 if l_use_asg_hours = 'Y' then
888 --
889 -- Get work week from ASG_HOURS on this current day
890 -- because ASG_HOURS can be datetracked we need to check it
891 -- each day
892 --
893 IF p_chg_asg_hours THEN
894 l_work_week:=p_asg_hours;
895 l_work_frequency:=p_freq;
896 ELSE
897 open csr_asg_hours(p_current_day);
898 fetch csr_asg_hours into l_work_week, l_work_frequency;
899 if csr_asg_hours%notfound then
900 hr_utility.set_message(801,'HR_NZ_WORKING_HRS_MISSING');
901 hr_utility.raise_error;
902 end if;
903 close csr_asg_hours;
904 END IF;
905 --
906 -- ASG_FREQ must be Week
907 --
908 if l_work_frequency <> 'W' then
909 hr_utility.set_message(801,'HR_NZ_BAD_WORKING_FREQ');
910 hr_utility.raise_error;
911 end if;
912 --
913 -- Validate date to use work week from ASG_HOURS
914 -- Note: this can only be used to accrue in HOURS
915 -- so we also check the UOM of the accrual plan
916 -- matches this.
917 --
918 if ((l_work_week is not null) or (l_work_week = 0)) then
919 if g_debug then
920 hr_utility.set_location(l_procedure,20);
921 hr_utility.trace('l_work_week comes from ASG_HOURS');
922 hr_utility.trace('l_work_week = '||to_char(l_work_week));
923 hr_utility.trace('p_uom.......= '||p_uom);
924 end if;
928 hr_utility.raise_error;
925 --
926 else
927 hr_utility.set_message(801,'HR_NZ_WORKING_HRS_MISSING');
929 end if;
930 --
931 else
932 --
933 --------------------------------------------
934 -- Work week is not determined from ASG_HOURS
935 --------------------------------------------
936 --
937 if g_debug then
938 hr_utility.set_location(l_procedure,35);
939 end if;
940 --
941 l_work_week := get_standard_work_week(p_assignment_id => p_assignment_id, p_effective_date => p_current_day);
942 --
943 -- If the 'Standard Work Week' is not available
944 -- then we use the balance DAYS_OR_HOURS_WORKED
945 --
946 if (l_work_week is null) or (l_work_week = 0) then
947 --
948 open csr_get_days_in_period;
949 fetch csr_get_days_in_period into l_days_in_period;
950 close csr_get_days_in_period;
951 --
952 l_weeks_in_period := l_days_in_period / 7;
953
954 l_working_time := get_working_days_balance
955 (p_assignment_id => p_assignment_id
956 ,p_effective_date => p_current_day
957 );
958
959 l_work_week := l_working_time / l_weeks_in_period;
960
961 if g_debug then
962 hr_utility.set_location(l_procedure,40);
963 hr_utility.trace('..l_work_week comes from DAYS_OR_HOURS_WORKED');
964 hr_utility.trace('..l_work_week = '||to_char(l_work_week));
965 hr_utility.trace('..l_working_time = '||to_char(l_working_time));
966 hr_utility.trace('..l_weeks_in_period = '||to_char(l_weeks_in_period));
967 hr_utility.trace('..p_annual_accrual = '||to_char(p_annual_accrual));
968 hr_utility.trace('..l_days_in_period = '||to_char(l_days_in_period));
969 end if;
970
971 end if;
972 --
973 end if;
974 --
975 --
976 if g_debug then
977 hr_utility.set_location(l_procedure, 999);
978 end if;
979 --
980 return l_work_week;
981 end determine_work_week;
982 ---------------------------------------------------------------------
983 -- is_leap_year function --
984 -- function called in daily_accrual_loop function --
985 -- This function finds whether 29-feb of leap year present between --
986 -- the dates given --
987 ---------------------------------------------------------------------
988 function is_leap_year
989 (p_start_date in date
990 ,p_end_date in date)
991 return number
992 is
993
994 l_date date;
995 l_year_date date;
996 l_curr_year varchar2(4);
997 l_mon number;
998
999 begin
1000
1001 l_mon :=to_char(p_start_date,'MM');
1002
1003 IF l_mon<=2 THEN
1004 l_curr_year := to_char(p_start_date,'YYYY');
1005 l_year_date := p_start_date;
1006 ELSE
1007 l_curr_year := to_char(p_end_date,'YYYY');
1008 l_year_date := p_end_date;
1009 END IF;
1010
1011 if ((to_number(l_curr_year)/4 = trunc( to_number(l_curr_year)/4))
1012 and not((to_number(l_curr_year)/100 = trunc(to_number(l_curr_year)/100))))
1013 or (to_number(l_curr_year)/400 = trunc(to_number(l_curr_year)/400) )
1014 then
1015 l_date := to_date('29-02'||to_char(l_year_date,'YYYY'),'DD-MM-YYYY');
1016 if l_date between p_start_date and p_end_date then
1017 return 1;
1018 else
1019 return 0;
1020 end if;
1021 else
1022 return 0;
1023 end if;
1024
1025 end is_leap_year;
1026 --
1027 --------------------------
1028 -- DETERMINE_WORK_WEEK_OLD
1029 --------------------------
1030 --
1031 function determine_work_week
1032 (p_assignment_id in number
1033 ,p_current_day in date
1034 ,p_uom in varchar2
1035 ,p_annual_accrual in number
1036 ) return number is
1037 l_procedure constant varchar2(60) := g_package||'determine_work_week';
1038 l_work_week number;
1039 l_work_frequency varchar2(30);
1040 l_use_asg_hours varchar2(3);
1041 l_weeks_in_period number;
1042 l_days_in_period number;
1043 l_working_time number;
1044 --
1045 cursor csr_asg_hours(p_effective_date date) is
1046 select normal_hours
1047 , frequency
1048 from per_assignments_f
1049 where assignment_id = p_assignment_id
1050 and p_effective_date between effective_start_date and effective_end_date;
1051 --
1052 cursor csr_get_days_in_period is
1053 select ptp.end_date - ptp.start_date days_in_period
1054 from per_time_periods ptp
1055 , per_assignments_f paf
1056 where paf.assignment_id = p_assignment_id
1057 and p_current_day between paf.effective_start_date and paf.effective_end_date
1058 and paf.payroll_id = ptp.payroll_id
1059 and p_current_day between ptp.start_date and ptp.end_date;
1060 --
1061 begin
1062 l_use_asg_hours := 'N';
1063 g_debug := hr_utility.debug_enabled;
1064 if g_debug then
1068 end if;
1065 hr_utility.set_location(l_procedure, 0);
1066 hr_utility.trace('p_assignment_id = '||to_char(p_assignment_id));
1067 hr_utility.trace('p_current_day.. = '||to_char(p_current_day,'DD-MON-YYYY'));
1069 --
1070 -- Check how to calculate accrual
1071 --
1072 open csr_use_asg_hours(p_assignment_id, p_current_day);
1073 fetch csr_use_asg_hours into l_use_asg_hours;
1074 close csr_use_asg_hours;
1075 --
1076 if g_debug then
1077 hr_utility.trace('l_use_asg_hours = '||l_use_asg_hours);
1078 end if;
1079
1080 if l_use_asg_hours = 'Y' then
1081 --
1082 -- Get work week from ASG_HOURS on this current day
1083 -- because ASG_HOURS can be datetracked we need to check it
1084 -- each day
1085 --
1086 open csr_asg_hours(p_current_day);
1087 fetch csr_asg_hours into l_work_week, l_work_frequency;
1088 if csr_asg_hours%notfound then
1089 hr_utility.set_message(801,'HR_NZ_WORKING_HRS_MISSING');
1090 hr_utility.raise_error;
1091 end if;
1092 close csr_asg_hours;
1093 --
1094 -- ASG_FREQ must be Week
1095 --
1096 if l_work_frequency <> 'W' then
1097 hr_utility.set_message(801,'HR_NZ_BAD_WORKING_FREQ');
1098 hr_utility.raise_error;
1099 end if;
1100 --
1101 -- Validate date to use work week from ASG_HOURS
1102 -- Note: this can only be used to accrue in HOURS
1103 -- so we also check the UOM of the accrual plan
1104 -- matches this.
1105 --
1106 if ((l_work_week is not null) or (l_work_week = 0)) then
1107 if g_debug then
1108 hr_utility.set_location(l_procedure,20);
1109 hr_utility.trace('l_work_week comes from ASG_HOURS');
1110 hr_utility.trace('l_work_week = '||to_char(l_work_week));
1111 hr_utility.trace('p_uom.......= '||p_uom);
1112 end if;
1113 --
1114 else
1115 hr_utility.set_message(801,'HR_NZ_WORKING_HRS_MISSING');
1116 hr_utility.raise_error;
1117 end if;
1118 --
1119 else
1120 --
1121 --------------------------------------------
1122 -- Work week is not determined from ASG_HOURS
1123 --------------------------------------------
1124 --
1125 if g_debug then
1126 hr_utility.set_location(l_procedure,35);
1127 end if;
1128 --
1129 l_work_week := get_standard_work_week(p_assignment_id => p_assignment_id, p_effective_date => p_current_day);
1130 --
1131 -- If the 'Standard Work Week' is not available
1132 -- then we use the balance DAYS_OR_HOURS_WORKED
1133 --
1134 if (l_work_week is null) or (l_work_week = 0) then
1135 --
1136 open csr_get_days_in_period;
1137 fetch csr_get_days_in_period into l_days_in_period;
1138 close csr_get_days_in_period;
1139 --
1140 l_weeks_in_period := l_days_in_period / 7;
1141
1142 l_working_time := get_working_days_balance
1143 (p_assignment_id => p_assignment_id
1144 ,p_effective_date => p_current_day
1145 );
1146
1147 l_work_week := l_working_time / l_weeks_in_period;
1148
1149 if g_debug then
1150 hr_utility.set_location(l_procedure,40);
1151 hr_utility.trace('..l_work_week comes from DAYS_OR_HOURS_WORKED');
1152 hr_utility.trace('..l_work_week = '||to_char(l_work_week));
1153 hr_utility.trace('..l_working_time = '||to_char(l_working_time));
1154 hr_utility.trace('..l_weeks_in_period = '||to_char(l_weeks_in_period));
1155 hr_utility.trace('..p_annual_accrual = '||to_char(p_annual_accrual));
1156 hr_utility.trace('..l_days_in_period = '||to_char(l_days_in_period));
1157 end if;
1158
1159 end if;
1160 --
1161 end if;
1162 --
1163 --
1164 if g_debug then
1165 hr_utility.set_location(l_procedure, 999);
1166 end if;
1167 --
1168 return l_work_week;
1169 end determine_work_week;
1170 --
1171 ---------------------
1172 -- DAILY_ACCRUAL_LOOP
1173 ---------------------
1174 --
1175 function daily_accrual_loop
1176 (p_payroll_id in number
1177 ,p_assignment_id in number
1178 ,p_accrual_plan_id in number
1179 ,p_service_start_date in date
1180 ,p_start_date in date
1181 ,p_end_date in date
1182 )
1183 return number is
1184 l_procedure constant varchar2(60) := g_package||'daily_accrual_loop';
1185 l_current_day date;
1186 l_anniversary_start_date date;
1187 l_anniversary_end_date date;
1188
1189 l_person_id number;
1190 l_years_of_service number;
1191 l_prev_years_of_service number;
1192 l_tmp_number number;
1193 l_period_accrual number;
1194 l_asg_hours number;
1195 l_annual_accrual number;
1196 l_daily_accrual number;
1197 l_work_week number;
1198 l_temp_week number;
1199 l_temp_accrual number;
1200 l_uom varchar2(2);
1201 l_eligible_inactive boolean;
1205 l_tmp_freq varchar2(1);
1202 l_eligible_abs boolean;
1203 l_chg_asg_hours boolean;
1204 l_tmp_asg_hours number;
1206 l_is_leap_year number;
1207 l_temp_leap_year number;
1208
1209
1210 type t_system_status is table of varchar2(30) index by binary_integer ;
1211 type t_eff_start_date is table of date index by binary_integer ;
1212 type t_eff_end_date is table of date index by binary_integer ;
1213
1214 l_system_status t_system_status;
1215 l_eff_start_date t_eff_start_date;
1216 l_eff_end_date t_eff_end_date;
1217
1218 type t_abs_start_date is table of date index by binary_integer ;
1219 type t_abs_end_date is table of date index by binary_integer ;
1220
1221 l_abs_start_date t_abs_start_date;
1222 l_abs_end_date t_abs_end_date;
1223
1224 type t_normal_hours is table of number index by binary_integer ;
1225 type t_frequency is table of varchar2(1) index by binary_integer ;
1226 type t_wrk_eff_start_date is table of date index by binary_integer ;
1227 type t_wrk_eff_end_date is table of date index by binary_integer ;
1228
1229 l_normal_hours t_normal_hours;
1230 l_frequency t_frequency;
1231 l_wrk_eff_start_date t_wrk_eff_start_date;
1232 l_wrk_eff_end_date t_wrk_eff_end_date;
1233
1234 --
1235 cursor csr_get_accrual_band
1236 (p_number_of_years number
1237 ,p_accrual_plan_id number
1238 ) is
1239 select bnd.annual_rate annual_rate
1240 , acc.accrual_units_of_measure uom
1241 from pay_accrual_bands bnd
1242 , pay_accrual_plans acc
1243 where p_number_of_years >= bnd.lower_limit
1244 and p_number_of_years < bnd.upper_limit
1245 and bnd.accrual_plan_id = p_accrual_plan_id
1246 and bnd.accrual_plan_id = acc.accrual_plan_id;
1247
1248 begin
1249
1250 open csr_person_id(p_assignment_id, p_start_date);
1251 fetch csr_person_id into l_person_id;
1252 close csr_person_id;
1253
1254 select ast.per_system_status,asg.EFFECTIVE_START_DATE,asg.EFFECTIVE_END_DATE
1255 bulk collect into l_system_status, l_eff_start_date, l_eff_end_date
1256 from per_assignments_f asg
1257 ,per_assignment_status_types ast
1258 where asg.assignment_id = p_assignment_id
1259 and asg.assignment_status_type_id = ast.assignment_status_type_id
1260 and ast.per_system_status <> 'ACTIVE_ASSIGN';
1261
1262 select (ab.date_start + g_unpaid_absence_days + 1), ab.date_end
1263 bulk collect into l_abs_start_date, l_abs_end_date
1264 from per_absence_attendances ab
1265 , per_absence_attendance_types abt
1266 where ab.absence_attendance_type_id = abt.absence_attendance_type_id
1267 and ab.person_id = l_person_id
1268 and abt.absence_category = g_unpaid_absence_category
1269 and ((ab.date_end - ab.date_start) > g_unpaid_absence_days);
1270
1271 select normal_hours,frequency,effective_start_date,effective_end_date
1272 bulk collect into l_normal_hours,l_frequency,l_wrk_eff_start_date,l_wrk_eff_end_date
1273 from per_assignments_f
1274 where assignment_id = p_assignment_id;
1275
1276 l_eligible_inactive:= true;
1277 l_eligible_abs:= true;
1278 l_chg_asg_hours:= false;
1279
1280 l_years_of_service := 0;
1281 l_prev_years_of_service := -1;
1282
1283 l_annual_accrual := 0;
1284 l_work_week := 0;
1285 l_period_accrual := 0;
1286 l_is_leap_year:=0;
1287
1288 g_debug := hr_utility.debug_enabled;
1289 if g_debug then
1290 hr_utility.set_location(l_procedure, 0);
1291 hr_utility.set_location('p_payroll_id......= '||to_char(p_payroll_id),1);
1292 hr_utility.set_location('p_assignment_id...= '||to_char(p_assignment_id),1);
1293 hr_utility.set_location('p_accrual_plan_id.= '||to_char(p_accrual_plan_id),1);
1294 hr_utility.set_location('p_start_date......= '||to_char(p_start_date,'DD-MON-YYYY'),1);
1295 hr_utility.set_location('p_end_date........= '||to_char(p_end_date,'DD-MON-YYYY'),1);
1296 end if;
1297 --l_period_accrual := 0;
1298 --
1299 -- Loop thru each day of the period given
1300 -- from first to last day of period
1301 --
1302 l_current_day := p_start_date;
1303 --
1304 loop
1305 exit when l_current_day > p_end_date;
1306 if g_debug then
1307 hr_utility.set_location(l_procedure,5);
1308 hr_utility.trace('l_current_day = '||to_char(l_current_day,'DD-MON-YYYY'));
1309 end if;
1310 --
1311 -- Is this day eligible to accrue Annual Leave
1312 --
1313 --
1314 -- Check if the present day is present in the inactive days periods
1315 if l_system_status.count>0 then
1316 for i in 1..l_system_status.count loop
1317 if l_current_day between l_eff_start_date(i) and l_eff_end_date(i)
1318 then
1319 l_eligible_inactive:= false;
1320 exit;
1321 else
1322 l_eligible_inactive:= true;
1323 end if;
1324 end loop;
1325 end if;
1326
1327 -- Check if the present day is present in the absences
1328 if l_abs_start_date.count>0 then
1332 l_eligible_abs:= false;
1329 for i in 1..l_abs_start_date.count loop
1330 if l_current_day between l_abs_start_date(i) and l_abs_end_date(i)
1331 then
1333 exit;
1334 else
1335 l_eligible_abs:= true;
1336 end if;
1337 end loop;
1338 end if;
1339
1340 -- Check if assignment hours has changed
1341 if l_frequency.count>0 then
1342 for i in 1..l_frequency.count loop
1343 if l_current_day between l_wrk_eff_start_date(i) and l_wrk_eff_end_date(i)
1344 then
1345 l_chg_asg_hours := true;
1346 l_tmp_asg_hours := l_normal_hours(i);
1347 l_tmp_freq := l_frequency(i);
1348 exit;
1349 end if;
1350 end loop;
1351 end if;
1352
1353 if (l_eligible_inactive) and (l_eligible_abs)
1354 then
1355 --
1356 -- Set temporary holder for years of service
1357 -- so that we can check to see if it has changed
1358 -- from day to day... if it has not changed, this
1359 -- means that the accrual band cannot change and
1360 -- this can save us checking the accrual band
1361 -- for every day.
1362 --
1363 if l_prev_years_of_service <> -1 then
1364 l_prev_years_of_service := l_years_of_service;
1365 end if;
1366 --
1367 -- We only need to get the anniversary details
1368 -- once for each anniversary period
1369 -- So we only execute this code if anniversary has
1370 -- not been initialised or if the current processing
1371 -- day has advanced into the next anniversary period
1372 --
1373 if ((l_anniversary_start_date is null) or (l_current_day > l_anniversary_end_date)) then
1374 --
1375 -- Get the anniversary details for this day
1376 --
1377 l_tmp_number := cache_anniversary_details
1378 (p_payroll_id => p_payroll_id
1379 ,p_assignment_id => p_assignment_id
1380 ,p_accrual_plan_id => p_accrual_plan_id
1381 ,p_calculation_date => l_current_day
1382 ,p_service_start_date => p_service_start_date
1383 ,p_anniversary_start_date => l_anniversary_start_date
1384 ,p_anniversary_end_date => l_anniversary_end_date
1385 ,p_years_of_service => l_years_of_service
1386 );
1387 --
1388 if g_debug then
1389 hr_utility.set_location(l_procedure,10);
1390 hr_utility.trace('l_anniversary_start_date = '||to_char(l_anniversary_start_date,'DD-MON-YYYY'));
1391 hr_utility.trace('l_anniversary_end_date...= '||to_char(l_anniversary_end_date,'DD-MON-YYYY'));
1392 end if;
1393 --
1394 end if;
1395 --
1396
1397 l_temp_accrual:=l_annual_accrual;
1398
1399 if l_years_of_service <> l_prev_years_of_service then
1400 --
1401 -- Now get the accrual band for this day
1402 --
1403 if g_debug then
1404 hr_utility.set_location(l_procedure,23);
1405 hr_utility.trace('l_uom...... ='||l_uom);
1406 end if;
1407 --
1408 open csr_get_accrual_band(l_years_of_service, p_accrual_plan_id);
1409 fetch csr_get_accrual_band into l_annual_accrual, l_uom;
1410 close csr_get_accrual_band;
1411 --
1412 end if;
1413 --
1414 -- Get the work week
1415 --
1416 l_temp_week :=l_work_week;
1417
1418 l_work_week := nvl(determine_work_week
1419 (p_assignment_id => p_assignment_id
1420 ,p_current_day => l_current_day
1421 ,p_uom => l_uom
1422 ,p_annual_accrual => l_annual_accrual
1423 ,p_chg_asg_hours => l_chg_asg_hours
1424 ,p_asg_hours => l_tmp_asg_hours
1425 ,p_freq => l_tmp_freq
1426 ),0);
1427 --
1428 if g_debug then
1429 hr_utility.set_location(l_procedure,30);
1430 hr_utility.trace('l_work_week ='||to_char(l_work_week));
1431 end if;
1432 --
1433 l_temp_leap_year:=l_is_leap_year;
1434 l_is_leap_year:=is_leap_year(l_anniversary_start_date,l_anniversary_end_date);
1435
1436 IF (l_temp_week <> l_work_week) OR (l_temp_accrual<>l_annual_accrual)
1437 OR (l_temp_leap_year <> l_is_leap_year)
1438 THEN
1439 l_daily_accrual := nvl(calculate_daily_accrual
1440 (p_person_id => l_person_id
1441 ,p_accrual_plan_id => p_accrual_plan_id
1442 ,p_start_date => l_anniversary_start_date
1443 ,p_end_date => l_anniversary_end_date
1444 ,p_annual_accrual => l_annual_accrual
1445 ,p_work_week => l_work_week
1446 ),0);
1447 END IF;
1448 --
1452 hr_utility.trace('...l_period_accrual = '||to_char(l_period_accrual));
1449 l_period_accrual := l_period_accrual + l_daily_accrual;
1450 if g_debug then
1451 hr_utility.set_location(l_procedure,40);
1453 end if;
1454 end if;
1455 --
1456 l_current_day := l_current_day + 1;
1457 end loop;
1458 --
1459 if g_debug then
1460 hr_utility.set_location(l_procedure, 999);
1461 end if;
1462 --
1463 return nvl(l_period_accrual,0);
1464 --
1465 end daily_accrual_loop;
1466 --
1467 ------------------------------
1468 -- GET_ANNUAL_LEAVE_PERCENTAGE
1469 ------------------------------
1470 --
1471 function get_annual_leave_percentage(p_accrual_plan_id number)
1472 return number is
1473 --
1474 cursor csr_percentage(p_accrual_plan_id number) is
1475 select fnd_number.canonical_to_number(information1)
1476 from pay_accrual_plans pap
1477 where information_category = 'NZ_NZAL'
1478 and pap.accrual_plan_id = p_accrual_plan_id;
1479 --
1480 l_percentage number;
1481 l_procedure constant varchar2(60) := g_package||'get_annual_leave_percentage';
1482 --
1483 begin
1484 g_debug := hr_utility.debug_enabled;
1485 if g_debug then
1486 hr_utility.set_location(l_procedure, 0);
1487 end if;
1488 --
1489 open csr_percentage(p_accrual_plan_id);
1490 fetch csr_percentage into l_percentage;
1491 if csr_percentage%notfound then
1492 l_percentage := 0;
1493 end if;
1494 close csr_percentage;
1495 --
1496 if g_debug then
1497 hr_utility.set_location(l_procedure, 999);
1498 end if;
1499 --
1500 return l_percentage;
1501 --
1502 end get_annual_leave_percentage;
1503 --
1504 --
1505 -- Function used by formula function
1506 -- only required to save on duplication of code
1507 -- due to multiple calls.
1508 --
1509 --
1510 -- Ordinary rate has already been converted to appropriate UOM
1511 --
1512 function annual_leave_rate_calc_1
1513 (p_ordinary_rate in number
1514 ,p_earnings_prev_12mths in number
1515 ,p_earnings_td in number
1516 ,p_time_worked_prev_12mths in number
1517 ,p_time_worked_td in number
1518 ,p_work_week in number
1519 ,p_hire_date in date
1520 ,p_period_start_date in date
1521 ,p_period_end_date in date
1522 )
1523 return number is
1524 l_rate number;
1525 l_procedure constant varchar2(60) := g_package||'annual_leave_rate_calc_1';
1526 l_average_weekly_rate number;
1527 --
1528
1529 begin
1530 g_debug := hr_utility.debug_enabled;
1531 --
1532 if g_debug then
1533 hr_utility.set_location(l_procedure, 0);
1534 hr_utility.trace('...p_ordinary_rate = '||to_char(p_ordinary_rate));
1535 hr_utility.trace('...p_earnings_prev_12mths = '||to_char(p_earnings_prev_12mths));
1536 hr_utility.trace('...p_time_worked_prev_12mths = '||to_char(p_time_worked_prev_12mths));
1537 hr_utility.trace('...p_work_week = '||to_char(p_work_week));
1538 hr_utility.trace('...p_period_start_date = '||to_char(p_period_start_date,'DD/MM/RRRR'));
1539 hr_utility.trace('...p_period_end_date = '||to_char(p_period_end_date,'DD/MM/RRRR'));
1540 hr_utility.trace('...p_hire_date = '||to_char(p_hire_date,'DD/MM/RRRR'));
1541 end if;
1542 --
1543 -- Check to see if the Employees work period is more than 12 months
1544 --
1545 /* Bug 7260523 - Changed dates order for months_between condition */
1546 if months_between(p_period_end_date,p_hire_date) < 12 then
1547 if (p_hire_date = p_period_start_date or p_hire_date > p_period_start_date)
1548 and (p_hire_date = p_period_end_date or p_hire_date < p_period_end_date)
1549 then
1550 if g_debug then
1551 hr_utility.set_location(l_procedure, 20);
1552 end if;
1553 l_rate := greatest(p_ordinary_rate, p_earnings_td/p_time_worked_td);
1554 else
1555 if g_debug then
1556 hr_utility.set_location(l_procedure, 30);
1557 end if;
1558 l_rate := greatest(p_ordinary_rate, p_earnings_prev_12mths/p_time_worked_prev_12mths);
1559 end if;
1560 else
1561 --
1562 -- Calculate the rate per week
1563 --
1564
1565 --
1566 -- Check to ensure we do not get divide by zero error
1567 --
1568 if p_time_worked_prev_12mths = 0 then
1569 l_rate := p_ordinary_rate;
1570 else
1571 l_average_weekly_rate := p_earnings_prev_12mths/52;
1572 l_rate := greatest(p_ordinary_rate, (l_average_weekly_rate / p_work_week));
1573 if g_debug then
1574 hr_utility.set_location(l_procedure, 40);
1575 end if;
1576 end if;
1577 end if;
1578 --
1579 if g_debug then
1580 hr_utility.set_location(l_procedure, 999);
1581 end if;
1582 --
1583 return l_rate;
1584 end annual_leave_rate_calc_1;
1585 --
1586 -- Function used by formula function
1587 -- only required to save on duplication of code
1588 -- due to multiple calls.
1589 --
1590 function annual_leave_rate_calc_2
1594 ) return number is
1591 (p_percentage in number
1592 ,p_gross_earnings in number
1593 ,p_advance_leave_earnings in number
1595 l_rate number;
1596 l_procedure constant varchar2(60) := g_package||'annual_leave_rate_calc_2';
1597 begin
1598 l_rate := p_percentage * p_gross_earnings - p_advance_leave_earnings; /*Bug 7254820 */
1599 return l_rate;
1600 end annual_leave_rate_calc_2;
1601 --
1602 -- PREVIOUS_PERIOD_END_DATE
1603 --
1604 function previous_period_end_date
1605 (p_payroll_id in number
1606 ,p_time_period_id in number
1607 ) return date is
1608 l_date date;
1609 l_number number;
1610 --
1611 cursor csr_get_payment_date is
1612 --select pptp.end_date
1613 select pptp.regular_payment_date
1614 from per_time_periods bptp
1615 , per_time_periods pptp
1616 where bptp.payroll_id = p_payroll_id -- identify driving period
1617 and bptp.time_period_id = p_time_period_id -- identify driving period
1618 and pptp.payroll_id = p_payroll_id -- match payroll
1619 and bptp.start_date = pptp.end_date + 1; -- idenfity previous period
1620 --
1621 begin
1622 open csr_get_payment_date;
1623 fetch csr_get_payment_date into l_date;
1624 close csr_get_payment_date;
1625 --
1626 return l_date;
1627 end previous_period_end_date;
1628 --
1629 --
1630 --------------------------------------------------------------
1631 --
1632 -- get_accrual_entitlement
1633 --
1634 -- This function is required mainly by the NZ local library
1635 -- and will return the net accrual and net entitlement for a
1636 -- given person on a given day.
1637 --
1638 -- These values will be displayed in the forms PAYWSACV and
1639 -- PAYWSEAD.
1640 --
1641 --------------------------------------------------------------
1642 --
1643 FUNCTION get_accrual_entitlement
1644 (p_assignment_id IN NUMBER
1645 ,p_payroll_id IN NUMBER
1646 ,p_business_group_id IN NUMBER
1647 ,p_plan_id IN NUMBER
1648 ,p_calculation_date IN DATE
1649 ,p_net_accrual OUT NOCOPY NUMBER
1650 ,p_net_entitlement OUT NOCOPY NUMBER
1651 ,p_calc_start_date OUT NOCOPY DATE
1652 ,p_last_accrual OUT NOCOPY DATE
1653 ,p_next_period_end OUT NOCOPY DATE
1654 ) RETURN NUMBER IS
1655 -- The stages of the calculation are as follows
1656 --
1657 -- 1. Find the anniversary dates for the given calculation date
1658 -- using the get_carryover_values...this will allow us to
1659 -- obtain entitlement end date
1660 --
1661 -- 2: Find net leave at entitlement end date using the core
1662 -- get_net_accrual Function.
1663 --
1664 -- 3: Find the total net leave up to the calculation date using
1665 -- the core get_net_accrual function.
1666 --
1667 -- 4: Find Leave Accrual Initialise during period
1668 --
1669 -- 5: Find Leave Entitlement Initialise during period
1670 --
1671 -- 6: Net entitlement = step 2 + step 5
1672 --
1673 -- 7: Net accrual = (step 3 + step 5 - step 6)
1674 --
1675 l_procedure constant varchar2(72) := g_package||'.get_accrual_entitlement';
1676 l_adjustment_element varchar2(100);
1677 l_initialise_element varchar2(100);
1678 --
1679 l_anniversary_start_date date;
1680 l_anniversary_end_date date;
1681 l_start_date date;
1682 l_end_date date;
1683 l_accrual_end_date date;
1684 l_entitlement_period_end_date date;
1685 l_accrual_period_start_date date;
1686 l_continuous_service_date date;
1687
1688 --
1689 l_co_formula_id number;
1690 l_max_co number;
1691 l_accrual_adj number;
1692 l_accrual_ent number;
1693 l_entitlement_adj number;
1694 l_net_accrual number;
1695 l_net_entitlement number;
1696 l_accrual number;
1697 l_leave_entitlement number;
1698 l_leave_total number;
1699 l_others_entitlement number;
1700 l_others_accrual number;
1701 l_accrual_absences number;
1702 l_leave_accrual number;
1703 --
1704 l_accrual_period_end_date date;
1705 l_calculation_date date;
1706 --
1707 cursor c_get_co_formula
1708 (p_accrual_plan_id number) is
1709 select co_formula_id
1710 from pay_accrual_plans
1711 where accrual_plan_id = p_accrual_plan_id;
1712 --
1713 BEGIN
1714 --
1715 g_debug := hr_utility.debug_enabled;
1716 if g_debug then
1717 hr_utility.set_location(l_procedure, 0);
1718 hr_utility.trace('p_calculation_date = '||to_char(p_calculation_date,'DD-MON-YYYY'));
1719 end if;
1720 --
1721 l_calculation_date := p_calculation_date;
1722 --
1723 -- Step 1 Find entitlement end date
1724 -- first get the carryover formula then call it
1728 --
1725 -- to get the prev and next anniversary dates.
1726 -- Entitlement end date and accrual end dates are
1727 -- actually the day before the anniversary dates.
1729 open c_get_co_formula (p_plan_id);
1730 fetch c_get_co_formula into l_co_formula_id;
1731 close c_get_co_formula;
1732 --
1733 if g_debug then
1734 hr_utility.set_location(l_procedure, 10);
1735 end if;
1736 --
1737 --------------------------------------------------------
1738 --
1739 -- GET ENTITLEMENT PERIOD DETAILS
1740 --
1741 --------------------------------------------------------
1742 -- The carryover formula's have been written to
1743 -- get the anniversary start and anniversary end dates
1744 -- for the anniversary period as of the calculation date
1745 -- when called in the mode NZ_FORM
1746 --------------------------------------------------------
1747 --
1748
1749 per_accrual_calc_functions.get_carry_over_values
1750 (p_co_formula_id => l_co_formula_id
1751 ,p_assignment_id => p_assignment_id
1752 ,p_calculation_date => l_calculation_date
1753 ,p_accrual_plan_id => p_plan_id
1754 ,p_business_group_id => p_business_group_id
1755 ,p_payroll_id => p_payroll_id
1756 ,p_accrual_term => 'NZ_FORM'
1757 ,p_effective_date => l_anniversary_start_date --l_accrual_period_start_date
1758 ,p_session_date => l_calculation_date
1759 ,p_max_carry_over => l_max_co
1760 ,p_expiry_date => l_anniversary_end_date --l_accrual_period_end_date
1761 );
1762 --
1763 -- The entitlement end date is the day before the start
1764 -- of the current anniversary period... unless the current anniversary
1765 -- period is the first anniversary period, in which case there will be
1766 -- no entitlement only accrual.
1767 --
1768 -- Before first anniversary date accrual_period_start_date = start_date
1769 -- in this case l_max_co will be set to 1 (for sick leave only)
1770 --
1771 l_accrual_period_start_date := l_anniversary_start_date;
1772 l_accrual_period_end_date := l_anniversary_end_date;
1773 --
1774 if l_max_co = 1 then
1775 l_entitlement_period_end_date := l_accrual_period_start_date;
1776 else
1777 l_entitlement_period_end_date := (l_accrual_period_start_date - 1);
1778 end if;
1779 --
1780 if g_debug then
1781 hr_utility.set_location(l_procedure,5);
1782 hr_utility.trace('l_entitlement_period_end_date = '||to_char(l_entitlement_period_end_date,'DD-MON-YYYY'));
1783 hr_utility.trace('l_accrual_period_start_date.. = '||to_char(l_accrual_period_start_date,'DD-MON-YYYY'));
1784 hr_utility.trace('l_accrual_period_endt_date... = '||to_char(l_accrual_period_end_date,'DD-MON-YYYY'));
1785 hr_utility.trace('l_continuous_service_date.... = '||to_char(l_continuous_service_date,'DD-MON-YYYY'));
1786 end if;
1787 --
1788 -------------------------------------------------------
1789 --
1790 -- GET THE NET LEAVE AMOUNT FOR THE ENTITLEMENT PERIOD
1791 --
1792 -------------------------------------------------------
1793 -- Step two find the Net leave at entitlement end date
1794
1795 -- Get the amount of leave which goes toward ENTITLEMENT
1796 -- Sum from start of plan until day before start of
1797 -- current anniversary period
1798 --
1799 -------------------------------------------------------
1800 --
1801
1802 per_accrual_calc_functions.get_net_accrual
1803 (p_assignment_id => p_assignment_id
1804 ,p_plan_id => p_plan_id
1805 ,p_payroll_id => p_payroll_id
1806 ,p_business_group_id => p_business_group_id
1807 ,p_calculation_date => l_entitlement_period_end_date
1808 ,p_start_date => l_start_date
1809 ,p_end_date => l_end_date
1810 ,p_accrual_end_date => l_accrual_end_date
1811 ,p_accrual => l_accrual
1812 ,p_net_entitlement => l_leave_entitlement
1813 );
1814 --
1815 -- Net Entitlement is not used because the net calculation
1816 -- of leave is done manually to allow for absences to be taken
1817 -- from entitlement before accrual
1818 --
1819 l_leave_entitlement := l_accrual;
1820 --
1821 l_others_entitlement := per_accrual_calc_functions.get_other_net_contribution
1822 (p_assignment_id => p_assignment_id
1823 ,p_plan_id => p_plan_id
1824 ,p_start_date => l_start_date
1825 ,p_calculation_date => l_entitlement_period_end_date
1826 ) ;
1827
1828 --
1829 -------------------------------------------------------
1830 --
1831 -- GET THE NET LEAVE TOTAL
1832 --
1833 -------------------------------------------------------
1834 -- Find the Net leave at the calculation_date
1835 -------------------------------------------------------
1836 --
1837 per_accrual_calc_functions.get_net_accrual
1838 (p_assignment_id => p_assignment_id
1839 ,p_plan_id => p_plan_id
1840 ,p_payroll_id => p_payroll_id
1841 ,p_business_group_id => p_business_group_id
1842 ,p_calculation_date => l_calculation_date
1846 ,p_accrual => l_accrual
1843 ,p_start_date => l_start_date
1844 ,p_end_date => l_end_date
1845 ,p_accrual_end_date => l_accrual_end_date
1847 ,p_net_entitlement => l_leave_total
1848 );
1849 --
1850 -- Net Entitlement is not used because the net calculation
1851 -- of leave is done manually to allow for absences to be taken
1852 -- from entitlement before accrual
1853 --
1854 l_leave_total := l_accrual;
1855 --
1856 ------------------------------------------------
1857 --
1858 -- GET THE ADJUSTMENT VALUES FOR ENTITLEMENT
1859 -- We search the entrie accrual period
1860 -- for entitlement adjustments since entitlement
1861 -- is always entitlement.
1862 -- Note: also if the accruals are being run
1863 -- before the entitlement period is reached
1864 -- then the function get_net_accrual does not
1865 -- return a start and end date.
1866 --
1867 ------------------------------------------------
1868 --
1869 -- We search the entire date range since entitlement
1870 -- adjustments are always entitlement
1871 --
1872 l_adjustment_element:= 'Entitlement Adjustment Element';
1873 l_entitlement_adj:= hr_nz_holidays.get_adjustment_values
1874 (p_assignment_id => p_assignment_id
1875 ,p_accrual_plan_id => p_plan_id
1876 ,p_calc_end_date => l_calculation_date
1877 ,p_adjustment_element => l_adjustment_element
1878 ,p_start_date => l_start_date
1879 ,p_end_date => l_end_date
1880 );
1881 if g_debug then
1882 hr_utility.set_location(l_procedure, 40);
1883 hr_utility.trace('l_start_date = '||to_char(l_start_date));
1884 hr_utility.trace('l_end_date = '||to_char(l_end_date));
1885 hr_utility.trace('l_calculation_date = '||to_char(l_calculation_date));
1886 hr_utility.trace('l_entitlement_adj = '||to_char(l_entitlement_adj));
1887 end if;
1888 --
1889
1890 ------------------------------------------------
1891 --
1892 -- GET THE ADJUSTMENT VALUES FOR ACCRUAL
1893 --
1894 ------------------------------------------------
1895 --
1896 -- We need to check for adjustments within
1897 -- the accrual period (ie accrual_period_start_date until calculation_date
1898 -- and the entitlement period (ie start_date until entitlement_period_end_date)
1899 --
1900 l_adjustment_element := 'Accrual Adjustment Element';
1901 l_accrual_adj:= hr_nz_holidays.get_adjustment_values
1902 (p_assignment_id => p_assignment_id
1903 ,p_accrual_plan_id => p_plan_id
1904 ,p_calc_end_date => l_calculation_date
1905 ,p_adjustment_element => l_adjustment_element
1906 ,p_start_date => l_entitlement_period_end_date
1907 ,p_end_date => l_calculation_date
1908 );
1909 if g_debug then
1910 hr_utility.set_location(l_procedure, 50);
1911 hr_utility.trace('l_accrual_adj = '||to_char(l_accrual_adj));
1912 end if;
1913
1914 --
1915 -- Accrual Adjustments which occured during the
1916 -- entitlement period become entitlement
1917 -- Add to the existing entitlement adjustments
1918 --
1919 l_accrual_ent := hr_nz_holidays.get_adjustment_values
1920 (p_assignment_id => p_assignment_id
1921 ,p_accrual_plan_id => p_plan_id
1922 ,p_calc_end_date => l_calculation_date
1923 ,p_adjustment_element => l_adjustment_element
1924 ,p_start_date => l_start_date
1925 ,p_end_date => l_end_date
1926 );
1927 --
1928 if g_debug then
1929 hr_utility.trace('l_entitlement_adj = '||to_char(l_entitlement_adj));
1930 hr_utility.trace('l_accrual_adj.... = '||to_char(l_accrual_adj));
1931 end if;
1932 l_others_accrual := per_accrual_calc_functions.get_other_net_contribution
1933 (p_assignment_id => p_assignment_id
1934 ,p_plan_id => p_plan_id
1935 ,p_start_date => l_accrual_period_start_date
1936 ,p_calculation_date => p_calculation_date
1937 ) ;
1938 --
1939 -- Find out the numder of hours taken during the accrual period
1940 -- If max_co is 1 then no accrual only entitlement
1941 --
1942 if l_max_co = 1
1943 then
1944 l_accrual_absences := per_accrual_calc_functions.get_absence
1945 (p_assignment_id => p_assignment_id
1946 ,p_plan_id => p_plan_id
1947 ,p_start_date => l_accrual_period_start_date
1948 ,p_calculation_date => p_calculation_date
1949 );
1950 if g_debug then
1951 hr_utility.set_location(l_procedure, 60);
1952 hr_utility.trace('..l_accrual_absences = '||to_char(l_accrual_absences));
1953 hr_utility.trace('..l_start_date = '||to_char(l_start_date,'dd/mm/rrrr'));
1957 l_leave_accrual := 0;
1954 hr_utility.trace('..l_calculation_date = '||to_char(l_calculation_date,'dd/mm/rrrr'));
1955 end if;
1956 l_leave_entitlement := l_leave_total - l_accrual_absences;
1958 --
1959 else
1960 l_accrual_absences := per_accrual_calc_functions.get_absence
1961 (p_assignment_id => p_assignment_id
1962 ,p_plan_id => p_plan_id
1963 ,p_start_date => l_start_date
1964 ,p_calculation_date => p_calculation_date
1965 );
1966 if g_debug then
1967 hr_utility.set_location(l_procedure, 70);
1968 hr_utility.trace('..l_start_date = '||to_char(l_start_date,'dd/mm/rrrr'));
1969 hr_utility.trace('..l_calculation_date = '||to_char(l_calculation_date,'dd/mm/rrrr'));
1970 hr_utility.trace('..l_accrual_absences = '||to_char(l_accrual_absences));
1971 end if;
1972 --
1973 -- Get the net entitlement and accrual before checking for absences
1974 -- Determine the amount to go towards accrual portion by subtracting
1975 -- entitlement portion from total
1976 --
1977 if g_debug then
1978 hr_utility.set_location(l_procedure, 75);
1979 hr_utility.trace('l_leave_total = '||to_char(l_leave_total));
1980 hr_utility.trace('l_leave_entitlement = '||to_char(l_leave_entitlement));
1981 end if;
1982
1983 l_leave_accrual := l_leave_total - l_leave_entitlement;
1984 --
1985 l_leave_accrual := l_leave_accrual + l_others_accrual + l_accrual_adj;
1986
1987 -- First year is accrual, not entitlement l_accrual_adj is subtracted.
1988 -- As l_accrual_adj returns value only in the first anniversary year,
1989 -- l_accrual_adj and l_accrual_ent is nullified in the first year and from
1990 -- second year onwards adjusted accrual value is added to the entitlement
1991
1992 l_leave_entitlement := l_leave_entitlement + l_others_entitlement + l_entitlement_adj + l_accrual_ent - l_accrual_adj;
1993 if g_debug then
1994 hr_utility.set_location(l_procedure, 80);
1995 hr_utility.trace('..l_leave_entitlement = '||to_char(l_leave_entitlement));
1996 hr_utility.trace('..l_others_entitlement = '||to_char(l_others_entitlement));
1997 hr_utility.trace('..l_entitlement_adj = '||to_char(l_entitlement_adj));
1998 hr_utility.trace('..l_accrual_ent = '||to_char(l_accrual_ent));
1999 hr_utility.trace('..l_accrual_adj = '||to_char(l_accrual_adj));
2000 hr_utility.trace('..l_leave_accrual = '||to_char(l_leave_accrual));
2001 end if;
2002
2003 -- have to subtract absences taken to calculate net entitlement
2004 -- absences must come off entitlement before accrual
2005 --
2006 if l_leave_entitlement > l_accrual_absences
2007 then
2008 l_leave_entitlement := l_leave_entitlement - l_accrual_absences;
2009 else
2010 -- Subtract from entitlement and leftovers from accrual
2011 l_leave_accrual := l_leave_accrual - (l_accrual_absences - l_leave_entitlement);
2012 l_leave_entitlement := 0;
2013 end if;
2014
2015 end if;
2016
2017 --
2018 -- set up return values
2019 --
2020 p_net_accrual := round(nvl(l_leave_accrual, 0), 3);
2021 p_net_entitlement := round(nvl(l_leave_entitlement, 0), 3);
2022 p_calc_start_date := l_start_date;
2023 p_last_accrual := l_accrual_end_date;
2024 p_next_period_end := l_accrual_period_end_date;
2025 --
2026 if g_debug then
2027 hr_utility.set_location(l_procedure,999);
2028 end if;
2029 --
2030 RETURN (0);
2031 --
2032 END get_accrual_entitlement;
2033 --
2034 ---------------------------------------------------------------------
2035 --
2036 -- ANNUAL_LEAVE_NET_ENTITLEMENT
2037 --
2038 -- Purpose : Wraps get_accrual_entitlement with parameters
2039 -- to match the Leave liability process.
2040 -- Returns : Total entitlement
2041 --
2042 ---------------------------------------------------------------------
2043
2044 PROCEDURE annual_leave_net_entitlement
2045 (p_assignment_id IN NUMBER
2046 ,p_payroll_id IN NUMBER
2047 ,p_business_group_id IN NUMBER
2048 ,p_plan_id IN NUMBER
2049 ,p_calculation_date IN DATE
2050 ,p_start_date OUT NOCOPY DATE
2051 ,p_end_date OUT NOCOPY DATE
2052 ,p_net_entitlement OUT NOCOPY NUMBER
2053 ) IS
2054 --
2055 -- Local Variables
2056 --
2057 l_proc CONSTANT VARCHAR2(72) := g_package||'annual_leave_net_entitlement';
2058 l_net_accrual NUMBER;
2059 l_net_entitlement NUMBER;
2060 l_calc_start_date DATE;
2061 l_last_accrual DATE;
2062 l_next_period_end DATE;
2063 l_dummy_number NUMBER;
2064 --
2065 BEGIN
2066 g_debug := hr_utility.debug_enabled;
2067 --
2068 if g_debug then
2069 hr_utility.trace(' In: ' || l_proc) ;
2070 end if;
2071 --
2072 l_dummy_number := get_accrual_entitlement
2073 (p_assignment_id
2074 ,p_payroll_id
2075 ,p_business_group_id
2079 ,l_net_entitlement
2076 ,p_plan_id
2077 ,p_calculation_date
2078 ,l_net_accrual
2080 ,l_calc_start_date
2081 ,l_last_accrual
2082 ,l_next_period_end
2083 );
2084 --
2085 p_net_entitlement := l_net_entitlement;
2086 p_start_date := l_calc_start_date;
2087 p_end_date := p_calculation_date;
2088 if g_debug then
2089 hr_utility.trace('Out: ' || l_proc);
2090 end if;
2091
2092 END annual_leave_net_entitlement;
2093 --
2094
2095 function get_previous_rate
2096 (p_element_type_id number
2097 ,p_assignment_action_id number
2098 ,p_rate_name varchar2
2099 ) return number is
2100 --
2101 l_procedure constant varchar2(72) := g_package||'get_previous_rate';
2102 --
2103 /*Bug 3654766 - Changed the cursor to improve performance and also
2104 to consider the assignment action id into account.*/
2105 cursor csr_get_rate is
2106 select to_number(result.result_value)
2107 from pay_run_results runs
2108 , pay_input_values_f input
2109 , pay_run_result_values result
2110 , pay_assignment_actions paa
2111 , pay_assignment_actions cur_paa
2112 , pay_payroll_actions cur_ppa
2113 , pay_element_entries_f entry
2114 , per_time_periods ptp
2115 where runs.element_type_id = p_element_type_id
2116 and input.element_type_id = runs.element_type_id
2117 and input.name = p_rate_name
2118 and result.run_result_id = runs.run_result_id
2119 and result.input_value_id = input.input_value_id
2120 and cur_paa.assignment_action_id = p_assignment_action_id
2121 and cur_ppa.payroll_action_id = cur_paa.payroll_action_id
2122 and paa.assignment_action_id = runs.assignment_action_id
2123 and paa.assignment_id = cur_paa.assignment_id
2124 and entry.assignment_id = cur_paa.assignment_id
2125 and entry.element_entry_id = runs.source_id
2126 and ptp.time_period_id = cur_ppa.time_period_id
2127 and cur_ppa.effective_date between input.effective_start_date
2128 and input.effective_end_date
2129 and (ptp.start_date between entry.effective_start_date
2130 and entry.effective_end_date
2131 or ptp.end_date between entry.effective_start_date
2132 and entry.effective_end_date);
2133
2134 l_previous_rate number;
2135 --
2136 begin
2137 --
2138 g_debug := hr_utility.debug_enabled;
2139 --
2140 if g_debug then
2141 hr_utility.set_location(l_procedure, 0) ;
2142 end if;
2143 --
2144 open csr_get_rate;
2145 fetch csr_get_rate into l_previous_rate;
2146 if csr_get_rate%notfound then
2147 l_previous_rate := 0;
2148 end if;
2149 close csr_get_rate;
2150 --
2151 if g_debug then
2152 hr_utility.trace('l_previous_rate = '||to_char(l_previous_rate));
2153 hr_utility.set_location(l_procedure, 999);
2154 end if;
2155 --
2156 --Bug 3620398: Changed the function to return l_previous_rate.
2157 --
2158 return l_previous_rate;
2159 --
2160 end get_previous_rate;
2161 --
2162
2163 -- Bug 3608752
2164 -- Parental leave changes
2165 FUNCTION is_parental_leave_taken(
2166 p_assignment_id IN NUMBER
2167 ,p_business_group_id IN NUMBER
2168 ,p_start_date IN DATE
2169 ,p_end_date IN DATE
2170 )
2171 RETURN NUMBER
2172 IS
2173 --
2174 CURSOR csr_parental_leave_taken(c_assignment_id IN NUMBER
2175 ,c_business_group_id IN NUMBER
2176 ,c_start_date IN DATE
2177 ,c_end_date IN DATE)
2178 IS
2179 --
2180 SELECT 1
2181 FROM per_absence_attendances paa
2182 ,per_absence_attendance_types paat
2183 ,per_assignments_f paf
2184 WHERE paa.person_id = paf.person_id
2185 AND paf.assignment_id = p_assignment_id
2186 AND paa.business_group_id = c_business_group_id
2187 AND paa.business_group_id = paat.business_group_id
2188 AND paa.absence_attendance_type_id = paat.absence_attendance_type_id
2189 AND paat.absence_category = 'NZPL'
2190 AND (paa.date_start BETWEEN c_start_date
2191 AND c_end_date
2192 OR paa.date_end BETWEEN c_start_date
2193 AND c_end_date )
2194 AND c_end_date BETWEEN paf.effective_start_date
2195 AND paf.effective_end_date;
2196 --
2197 l_pleave_taken NUMBER;
2198 l_procedure CONSTANT VARCHAR2(100) := g_package||'.is_parental_leave_taken';
2199 --
2200 BEGIN
2201 --
2202 l_pleave_taken := 0;
2206 hr_utility.set_location('NZ p_start_date : ' || to_char(p_start_date,'dd Mon yyyy'),10) ;
2203 hr_utility.set_location('NZ Entering : ' || l_procedure,10);
2204 hr_utility.set_location('NZ p_assignment_id : ' || to_char(p_assignment_id),10) ;
2205 hr_utility.set_location('NZ p_business_group_id : ' || to_char(p_business_group_id),10);
2207 hr_utility.set_location('NZ p_end_date : ' || to_char(p_end_date,'dd Mon yyyy'),10) ;
2208
2209 OPEN csr_parental_leave_taken(p_assignment_id
2210 ,p_business_group_id
2211 ,p_start_date
2212 ,p_end_date);
2213 FETCH csr_parental_leave_taken
2214 INTO l_pleave_taken;
2215
2216 IF csr_parental_leave_taken%FOUND THEN
2217 --
2218 CLOSE csr_parental_leave_taken;
2219 hr_utility.set_location('NZ l_pleave_taken : ' || to_char(l_pleave_taken),20);
2220 hr_utility.set_location('NZ Leaving : ' || l_procedure,20);
2221 RETURN 1;
2222 --
2223 END IF;
2224 --
2225 CLOSE csr_parental_leave_taken;
2226 hr_utility.set_location('NZ No parental leave taken',30);
2227 hr_utility.set_location('NZ Leaving : ' || l_procedure,30);
2228 RETURN 0;
2229 --
2230 EXCEPTION
2231 --
2232 WHEN others THEN
2233 --
2234 IF csr_parental_leave_taken%ISOPEN THEN
2235 --
2236 CLOSE csr_parental_leave_taken;
2237 --
2238 END IF;
2239 hr_utility.set_location('NZ Error in : ' || l_procedure,40);
2240 RAISE;
2241 --
2242 --
2243 END is_parental_leave_taken;
2244
2245 FUNCTION get_recur_abs_prev_period(
2246 p_assignment_id IN NUMBER
2247 ,p_payroll_id IN NUMBER
2248 ,p_absence_start_date IN DATE
2249 ,p_curr_aniv_start IN DATE
2250 ,p_prev_period_end_date IN DATE
2251 ,p_plan_id IN NUMBER
2252 )
2253 RETURN NUMBER
2254 IS
2255 --
2256 CURSOR get_pay_period_details(c_eff_date IN DATE) IS
2257 --
2258 SELECT ptp.time_period_id
2259 ,ptp.end_date
2260 FROM per_time_periods ptp
2261 WHERE ptp.payroll_id = p_payroll_id
2262 AND c_eff_date BETWEEN ptp.start_date
2263 AND ptp.end_date;
2264 --
2265
2266 CURSOR get_period_assg_act_id(c_time_period_id IN NUMBER)
2267 IS
2268 --
2269 SELECT max(paa.assignment_action_id)
2270 FROM pay_payroll_actions ppa
2271 ,pay_assignment_actions paa
2272 WHERE ppa.payroll_id = p_payroll_id
2273 AND ppa.time_period_id = c_time_period_id
2274 AND ppa.action_type IN ('R','Q')
2275 AND ppa.action_status = 'C'
2276 AND ppa.payroll_action_id = paa.payroll_action_id
2277 AND paa.assignment_id = p_assignment_id
2278 AND paa.action_status = 'C';
2279 --
2280
2281 CURSOR csr_get_recurr_absence(c_assignment_action_id IN NUMBER
2282 ,c_prev_period_end_date IN DATE)
2283 IS
2284 --
2285 SELECT to_number(nvl(prrv.result_value,0))
2286 FROM pay_run_result_values prrv
2287 ,pay_run_results prr
2288 ,pay_element_types_f alp_pet
2289 ,pay_input_values_f alp_piv
2290 ,pay_element_entries_f pee
2291 ,pay_element_links_f pel
2292 ,pay_element_types_f abs_pet
2293 ,pay_input_values_f abs_piv
2294 ,pay_accrual_plans pap
2295 WHERE prr.run_result_id = prrv.run_result_id
2296 AND prr.assignment_action_id = c_assignment_action_id
2297 AND prr.element_type_id = alp_pet.element_type_id
2298 AND alp_pet.element_name = 'Annual Leave Payment'
2299 AND alp_pet.element_type_id = alp_piv.element_type_id
2300 AND alp_piv.name = 'Leave Taken'
2301 AND alp_piv.input_value_id = prrv.input_value_id
2302 AND prr.source_id = pee.element_entry_id
2303 AND pee.creator_type = 'A'
2304 AND pee.effective_end_date > c_prev_period_end_date
2305 AND pee.element_link_id = pel.element_link_id
2306 AND pel.element_type_id = abs_pet.element_type_id
2307 AND abs_pet.processing_type = 'R'
2308 AND abs_pet.element_type_id = abs_piv.element_type_id
2309 AND abs_piv.input_value_id = pap.pto_input_value_id
2310 AND pap.accrual_plan_id = p_plan_id
2311 AND c_prev_period_end_date BETWEEN alp_pet.effective_start_date
2312 AND alp_pet.effective_end_date
2313 AND c_prev_period_end_date BETWEEN alp_piv.effective_start_date
2314 AND alp_piv.effective_end_date
2315 AND c_prev_period_end_date BETWEEN pel.effective_start_date
2316 AND pel.effective_end_date
2320 AND abs_piv.effective_end_date;
2317 AND c_prev_period_end_date BETWEEN abs_pet.effective_start_date
2318 AND abs_pet.effective_end_date
2319 AND c_prev_period_end_date BETWEEN abs_piv.effective_start_date
2321 --
2322 l_eff_date DATE;
2323 l_recurr_leave_taken NUMBER;
2324 l_leave_taken NUMBER;
2325 l_period_assg_act_id NUMBER;
2326 l_time_period_id NUMBER;
2327 l_period_end_date DATE;
2328 l_procedure CONSTANT VARCHAR2(100) := g_package||'.get_recur_abs_prev_period';
2329 --
2330 BEGIN
2331 --
2332 hr_utility.set_location('NZ Entering : ' ||l_procedure,10 );
2333 hr_utility.set_location('NZ p_absence_start_date : ' ||p_absence_start_date,10 );
2334 hr_utility.set_location('NZ p_curr_aniv_start : ' ||p_curr_aniv_start ,10 );
2335 hr_utility.set_location('NZ p_prev_period_end_date: ' ||p_prev_period_end_date ,10);
2336 hr_utility.set_location('NZ p_plan_id : ' ||p_plan_id ,10);
2337 l_recurr_leave_taken := 0;
2338 IF (p_curr_aniv_start <= p_absence_start_date ) THEN
2339 --
2340 -- Loop through starting from the absence start date
2341 -- Till Previous period end date to find the recurring
2342 -- absence processed in the previous runs
2343 l_eff_date := p_absence_start_date;
2344 WHILE (l_eff_date <= p_prev_period_end_date)
2345 LOOP
2346 --
2347 OPEN get_pay_period_details(l_eff_date);
2348 FETCH get_pay_period_details
2349 INTO l_time_period_id,l_period_end_date;
2350 CLOSE get_pay_period_details;
2351
2352 hr_utility.set_location('NZ l_time_period_id : ' || l_time_period_id,20);
2353 hr_utility.set_location('NZ l_prev_period_end_date : ' || l_period_end_date,20);
2354
2355 OPEN get_period_assg_act_id(l_time_period_id);
2356 FETCH get_period_assg_act_id
2357 INTO l_period_assg_act_id;
2358 CLOSE get_period_assg_act_id;
2359
2360 hr_utility.set_location('NZ l_prev_period_assg_act_id : ' || l_period_assg_act_id,30);
2361
2362 OPEN csr_get_recurr_absence(l_period_assg_act_id
2363 ,p_prev_period_end_date);
2364 FETCH csr_get_recurr_absence
2365 INTO l_leave_taken;
2366
2367 IF csr_get_recurr_absence%FOUND THEN
2368 --
2369 hr_utility.set_location('NZ l_leave_taken : ' || l_leave_taken,40);
2370
2371 l_recurr_leave_taken := l_recurr_leave_taken + l_leave_taken;
2372 --
2373 ELSE
2374 --
2375 hr_utility.set_location('NZ No recurring absence in previous periods ',50);
2376 --
2377 END IF;
2378
2379 CLOSE csr_get_recurr_absence;
2380
2381 -- Move to next period
2382 l_eff_date := l_period_end_date +1;
2383 --
2384 END LOOP;
2385 --
2386 END IF;
2387 hr_utility.set_location('NZ Leaving : ' ||l_procedure,60 );
2388 RETURN l_recurr_leave_taken;
2389 --
2390 EXCEPTION
2391 --
2392 WHEN others THEN
2393 --
2394 IF get_pay_period_details%ISOPEN THEN
2395 --
2396 CLOSE get_pay_period_details;
2397 --
2398 END IF;
2399 IF get_period_assg_act_id%ISOPEN THEN
2400 --
2401 CLOSE get_period_assg_act_id;
2402 --
2403 END IF;
2404 IF csr_get_recurr_absence%ISOPEN THEN
2405 --
2406 CLOSE csr_get_recurr_absence;
2407 --
2408 END IF;
2409
2410 hr_utility.set_location('NZ Error in : ' ||l_procedure,70 );
2411 RAISE;
2412 --
2413 END get_recur_abs_prev_period;
2414
2415 FUNCTION get_leave_taken (
2416 p_assignment_id IN NUMBER
2417 ,p_payroll_id IN NUMBER
2418 ,p_business_group_id IN NUMBER
2419 ,p_start_date IN DATE
2420 ,p_end_date IN DATE
2421 ,p_curr_aniv_start IN DATE
2422 ,p_plan_id IN NUMBER
2423 ,p_absence_start_date IN DATE
2424 )
2425 RETURN NUMBER
2426 IS
2427 --
2428 CURSOR csr_get_count_leave(c_assignment_id IN NUMBER
2429 ,c_business_group_id IN NUMBER
2430 ,c_start_date IN DATE
2431 ,c_end_date IN DATE)
2432 IS
2433 --
2434 SELECT nvl(nvl(sum(absence_days),sum(absence_hours)),0) cnt_abs
2435 FROM per_absence_attendances paa
2436 ,per_absence_attendance_types paat
2437 ,pay_accrual_plans pap
2438 ,per_assignments_f paf
2439 WHERE paa.person_id = paf.person_id
2440 AND paf.assignment_id = c_assignment_id
2441 AND paa.business_group_id = c_business_group_id
2442 AND paa.absence_attendance_type_id = paat.absence_attendance_type_id
2443 AND pap.accrual_plan_id = p_plan_id
2444 AND pap.accrual_category = 'NZAL'
2448 AND c_end_date
2445 AND paa.date_start BETWEEN c_start_date
2446 AND c_end_date
2447 AND paa.date_end BETWEEN c_start_date
2449 AND c_end_date BETWEEN paf.effective_start_date
2450 AND paf.effective_end_date;
2451 --
2452
2453
2454 l_days NUMBER;
2455 l_hours NUMBER;
2456 l_leave_taken NUMBER;
2457 l_recurr_leave_prev_period NUMBER;
2458 l_time_period_id NUMBER;
2459 l_period_end_date DATE;
2460 l_period_assg_act_id NUMBER;
2461 l_recurr_leave_taken NUMBER;
2462 l_eff_date DATE;
2463 l_procedure CONSTANT VARCHAR2(100) := g_package||'.get_leave_taken';
2464 --
2465 BEGIN
2466 --
2467 hr_utility.set_location('NZ Entering : ' || l_procedure,10);
2468 hr_utility.set_location('NZ p_assignment_id : ' || to_char(p_assignment_id),10);
2469 hr_utility.set_location('NZ p_payroll_id : ' || p_payroll_id,10);
2470 hr_utility.set_location('NZ p_business_group_id : ' ||to_char(p_business_group_id),10);
2471 hr_utility.set_location('NZ p_start_date : ' || to_char(p_start_date,'dd Mon yyyy'),10);
2472 hr_utility.set_location('NZ p_end_date : ' || to_char(p_end_date,'dd Mon yyyy'),10);
2473
2474 OPEN csr_get_count_leave(p_assignment_id
2475 ,p_business_group_id
2476 ,p_start_date
2477 ,p_end_date);
2478 FETCH csr_get_count_leave
2479 INTO l_leave_taken;
2480 CLOSE csr_get_count_leave;
2481
2482 -- Now find out whether there is any recurring absence that
2483 -- got processed in previous period
2484 -- If the recurring absence started in the previous Anniversary then
2485 -- it will get included in the Net Accrual of the previous Year.
2486 -- So the following calculation need not be done
2487
2488 l_recurr_leave_taken := pay_nz_holidays_2003.get_recur_abs_prev_period
2489 (
2490 p_assignment_id => p_assignment_id
2491 ,p_payroll_id => p_payroll_id
2492 ,p_absence_start_date => p_absence_start_date
2493 ,p_curr_aniv_start => p_curr_aniv_start
2494 ,p_prev_period_end_date => p_end_date
2495 ,p_plan_id => p_plan_id
2496 );
2497 l_leave_taken := l_leave_taken + l_recurr_leave_taken;
2498 hr_utility.set_location('NZ l_leave_taken : ' || l_leave_taken,20);
2499 hr_utility.set_location('NZ Leaving : ' || l_procedure,30);
2500
2501 RETURN l_leave_taken;
2502
2503 --
2504 EXCEPTION
2505 --
2506 WHEN others THEN
2507 --
2508 IF csr_get_count_leave%ISOPEN THEN
2509 --
2510 CLOSE csr_get_count_leave;
2511 --
2512 END IF;
2513
2514 hr_utility.set_location('NZ Erroring in : ' || l_procedure,40);
2515 RAISE;
2516 --
2517 --
2518 END get_leave_taken;
2519
2520
2521
2522 FUNCTION get_entitled_amount(
2523 p_payroll_id NUMBER
2524 ,p_payroll_action_id NUMBER
2525 ,p_assignment_id NUMBER
2526 ,p_business_group_id NUMBER
2527 ,p_accrual_plan_id NUMBER
2528 ,p_absence_start_date DATE
2529 ,p_period_start_date DATE
2530 ,p_period_end_date DATE
2531 ,p_entitled_leave_taken NUMBER
2532 ,p_curr_rate NUMBER
2533 ,p_hire_date DATE
2534 ,p_average_rate_p12mths NUMBER
2535 )
2536 RETURN NUMBER
2537 IS
2538 --
2539
2540 CURSOR get_curr_period_start
2541 IS
2542 --
2543 SELECT ptp.start_date
2544 FROM per_time_periods ptp
2545 ,pay_payroll_actions ppa
2546 WHERE ppa.payroll_action_id = p_payroll_action_id
2547 AND ppa.time_period_id = ptp.time_period_id;
2548 --
2549 l_eff_date DATE;
2550 l_amt NUMBER;
2551 l_dummy NUMBER;
2552 l_anniversary_start_date DATE;
2553 l_anniversary_end_date DATE;
2554 l_years_of_service NUMBER;
2555 l_net_accrual NUMBER;
2556 l_net_entitlement NUMBER;
2557 l_calc_start_date DATE;
2558 l_last_accrual DATE;
2559 l_next_period_end DATE;
2560 l_has_taken_pl NUMBER;
2561 l_rate NUMBER;
2562 l_period_rate NUMBER;
2563 l_def_bal_id NUMBER;
2564 l_gross_earnings_ytd NUMBER;
2565 l_time_worked_ytd NUMBER;
2566 l_std_work_hours NUMBER;
2567 l_entitled_leave_taken NUMBER;
2568 l_leave_taken NUMBER;
2572 --
2569 l_curr_start_date DATE;
2570 l_leave_available NUMBER;
2571 l_procedure CONSTANT VARCHAR2(100) := g_package||'get_entitled_amount';
2573 BEGIN
2574 --
2575 hr_utility.set_location('NZ Entering : ' || l_procedure ,10);
2576 hr_utility.set_location('NZ p_payroll_id : ' || p_payroll_id ,10);
2577 hr_utility.set_location('NZ p_assignment_id : ' || p_assignment_id ,10);
2578 hr_utility.set_location('NZ p_business_group_id : ' || p_business_group_id ,10);
2579 hr_utility.set_location('NZ p_accrual_plan_id : ' || p_accrual_plan_id,10);
2580 hr_utility.set_location('NZ p_period_start_date : ' || p_period_start_date ,10);
2581 hr_utility.set_location('NZ p_period_end_date : ' || p_period_end_date ,10);
2582 hr_utility.set_location('NZ p_entitled_leave_taken : ' || p_entitled_leave_taken ,10);
2583 hr_utility.set_location('NZ p_curr_rate : ' || p_curr_rate,10);
2584 hr_utility.set_location('NZ p_hire_date : ' || p_hire_date,10);
2585 hr_utility.set_location('NZ p_average_rate_p12mths : ' || p_average_rate_p12mths,10);
2586
2587 -- Initialize Variables
2588 l_eff_date := p_hire_date;
2589 l_amt := 0;
2590 l_entitled_leave_taken := p_entitled_leave_taken;
2591
2592 -- This loop when be executed for each anniversary starting from
2593 -- First anniversary to the anniversary before the current anniversary
2594 --
2595 WHILE ( l_eff_date < p_period_start_date)
2596 LOOP
2597 --
2598 hr_utility.set_location('NZ l_eff_Date : ' || l_eff_Date,20);
2599
2600 -- Get Anniversary details for l_eff_date
2601 l_dummy := cache_anniversary_details
2602 (p_payroll_id => p_payroll_id
2603 ,p_assignment_id => p_assignment_id
2604 ,p_accrual_plan_id => p_accrual_plan_id
2605 ,p_calculation_date => l_eff_date
2606 ,p_service_start_date => p_hire_date
2607 ,p_anniversary_start_date => l_anniversary_start_date
2608 ,p_anniversary_end_date => l_anniversary_end_date
2609 ,p_years_of_service => l_years_of_service
2610 );
2611 hr_utility.set_location('NZ l_anniversary_start_date : ' || l_anniversary_start_date,30);
2612 hr_utility.set_location('NZ l_anniversary_end_date : ' || l_anniversary_end_date,30);
2613 hr_utility.set_location('NZ l_years_of_service : ' || l_years_of_service,30);
2614
2615 -- Get the Net Accrual for this anniversary
2616 l_dummy := get_accrual_entitlement
2617 (
2618 p_assignment_id => p_assignment_id
2619 ,p_payroll_id => p_payroll_id
2620 ,p_business_group_id => p_business_group_id
2621 ,p_plan_id => p_accrual_plan_id
2622 ,p_calculation_date => l_anniversary_end_date
2623 ,p_net_accrual => l_net_accrual
2624 ,p_net_entitlement => l_net_entitlement
2625 ,p_calc_start_date => l_calc_start_date
2626 ,p_last_accrual => l_last_accrual
2627 ,p_next_period_end => l_next_period_end
2628 );
2629 hr_utility.set_location('NZ l_net_accrual : ' || l_net_accrual,40);
2630
2631 IF (l_net_accrual > 0) THEN
2632 --
2633 hr_utility.set_location('NZ l_net_accrual is greater than 0',50);
2634 OPEN get_curr_period_start;
2635 FETCH get_curr_period_start
2636 INTO l_curr_start_date;
2637 CLOSE get_curr_period_start;
2638 hr_utility.set_location('NZ after cursor get_curr_period_start',50);
2639
2640 -- Net accrual in this period has to accommodate absences that are
2641 -- taken after this anniversary and before the current payroll period.
2642
2643 -- Leave taken needs to be found only once when the control reaches
2644 -- this point of code for the first time.
2645 IF (l_leave_taken is NULL) THEN -- If it is first anniversary
2646 --
2647 IF (l_anniversary_end_date < l_curr_start_date) THEN
2648 --
2649 hr_utility.set_location('NZ l_leave taken is null',40);
2650 l_leave_taken := get_leave_taken
2651 (
2652 p_assignment_id => p_assignment_id
2653 ,p_payroll_id => p_payroll_id
2654 ,p_business_group_id => p_business_group_id
2655 ,p_start_date => (l_anniversary_end_date + 1)
2656 ,p_end_date => (l_curr_start_date -1)
2657 ,p_curr_aniv_start => p_period_start_date
2658 ,p_plan_id => p_accrual_plan_id
2659 ,p_absence_start_date => p_absence_start_date
2660 );
2661 --
2662 ELSE
2663 --
2664 -- Anniversary has ended in current period
2665 -- Leave taken should be made 0
2666 l_leave_taken := 0;
2667 --
2668 END IF;
2669 --
2670 END IF;
2671 hr_utility.set_location('NZ l_leave_taken : ' || l_leave_taken,50);
2672
2673 -- If 'Net Accrual in this Anniversary is less than 'Leave Taken'
2677 -- Else
2674 -- Then
2675 -- There is no leave available in this anniversary.
2676 -- Leave Taken = Leave Taken - Net Accrual
2678 -- There is leave available in this anniversary.
2679 -- Leave Available = Net Accrual - Leave Taken
2680 -- Leave Taken = 0 as all 'Leave Taken' has been accommodated now.
2681 IF (l_net_accrual <= l_leave_taken ) THEN
2682 --
2683 hr_utility.set_location('NZ Leave not Available in this year',60);
2684 l_leave_taken := l_leave_taken - l_net_accrual;
2685 --
2686 ELSE
2687 --
2688 hr_utility.set_location('NZ Leave Available in this year',70);
2689
2690 l_leave_available := l_net_accrual - l_leave_taken;
2691 l_leave_taken := 0;
2692
2693 hr_utility.set_location('NZ Leave Available : '||l_leave_available,80);
2694
2695 -- Check whether Assignment has taken any parental leave in this
2696 -- anniversary
2697 l_has_taken_pl := is_parental_leave_taken
2698 (
2699 p_assignment_id
2700 ,p_business_group_id
2701 ,l_anniversary_start_date
2702 ,l_anniversary_end_date
2703 );
2704 hr_utility.set_location('NZ l_has_taken_pl : ' || l_has_taken_pl,90);
2705
2706 -- If Assignment has taken parental leave
2707 -- Then
2708 -- Rate as of this anniversary should be computed
2709 -- Else
2710 -- Current Rate should be used
2711 IF (l_has_taken_pl = 1) THEN
2712 --
2713 hr_utility.set_location('NZ Parental leave taken',100);
2714 l_rate := p_average_rate_p12mths;
2715 --
2716 ELSE
2717 --
2718 l_rate := p_curr_rate;
2719 --
2720 END IF;
2721 --
2722 hr_utility.set_location('NZ l_rate : '|| l_rate,130);
2723 hr_utility.set_location('NZ l_entitle_leave_Taken : '|| l_entitled_leave_Taken,130);
2724 hr_utility.set_location('NZ l_net_accrual : '|| l_net_accrual,130);
2725 hr_utility.set_location('NZ l_leave_available : '|| l_leave_available,130);
2726
2727 -- If Entitled Leave taken is less than Leave Available
2728 -- Then
2729 -- Compute the Amount and return
2730 -- Else
2731 -- Need to compute the amount for this anniversary and
2732 -- added it to l_amt
2733 -- Entitled Leave Taken = Entitled Leave Taken - Leave Available
2734 IF ( l_entitled_leave_taken <= l_leave_available ) THEN
2735 --
2736 l_amt := l_amt + l_entitled_leave_taken * l_rate;
2737 hr_utility.set_location('NZ l_amt : ' || l_amt,140);
2738 hr_utility.set_location('NZ l_entitled_leave_taken : ' || l_entitled_leave_taken,140);
2739 hr_utility.set_location('NZ Leaving',140);
2740 RETURN l_amt;
2741 --
2742 ELSE
2743 --
2744 hr_utility.set_location('NZ leave available less than entitled',150);
2745 l_entitled_leave_taken := l_entitled_leave_taken - l_leave_available;
2746 l_amt := l_amt + l_rate * l_leave_available;
2747 hr_utility.set_location('NZ l_amt : ' || l_amt,150);
2751 --
2748 hr_utility.set_location('NZ l_entitled_leave_taken : ' || l_entitled_leave_taken,150);
2749 --
2750 END IF;
2752 END IF; -- 'If leaves available in this year' block
2753 --
2754 END IF; -- 'If NET Accrual <0 ' Block
2755 -- Move to Next Anniversary
2756 l_eff_date := l_anniversary_end_date +1;
2757 --
2758 END LOOP;
2759 hr_utility.set_location('NZ Leaving : ' || l_procedure ,160);
2760 RETURN l_amt;
2761 --
2762 EXCEPTION
2763 --
2764 WHEN others THEN
2765 --
2766 IF get_curr_period_start%ISOPEN THEN
2767 --
2768 CLOSE get_curr_period_start ;
2769 --
2770 END IF;
2771 hr_utility.set_location('NZ Error in : ' || l_procedure ,170);
2772 RAISE;
2773 --
2774 --
2775 END get_entitled_amount;
2776
2777
2778 --
2779 end pay_nz_holidays_2003;