1 PACKAGE BODY PQP_NL_PGGM_FUNCTIONS AS
2 /* $Header: pqpnlpgg.pkb 120.18 2007/07/03 13:20:31 rsahai noship $ */
3
4 --
5 --Cursor to fetch the max. salary value beyond which
6 --the threshold is constant,from global values
7 --
8 CURSOR c_get_global_value(c_global_name IN VARCHAR2,c_date_earned IN DATE) IS
9 SELECT nvl(fnd_number.canonical_to_number(global_value),0)
10 FROM ff_globals_f
11 WHERE global_name = c_global_name
12 AND legislation_code = 'NL'
13 AND (c_date_earned between effective_start_date and effective_end_date);
14
15
16 CURSOR c_get_num_periods_per_year(c_payroll_action_id IN NUMBER) IS
17 SELECT TPTYPE.number_per_fiscal_year
18 FROM pay_payroll_actions PACTION
19 ,per_time_periods TPERIOD
20 ,per_time_period_types TPTYPE
21 WHERE PACTION.payroll_action_id = c_payroll_action_id
22 AND TPERIOD.payroll_id = PACTION.payroll_id
23 AND (PACTION.date_earned between TPERIOD.start_date
24 and TPERIOD.end_date)
25 AND TPTYPE.period_type = TPERIOD.period_type;
26
27 --
28 -- ----------------------------------------------------------------------------
29 -- |------------------------< CHECK_ELIGIBILITY >-----------------------------|
30 -- ----------------------------------------------------------------------------
31 --
32 -- This function is used to check if an employee is eligible to contribute
33 -- towards a particular pension type by verifying that the employee age
34 -- falls between the minimum and maximum ages for the pension type
35
36 FUNCTION CHECK_ELIGIBILITY
37 (p_date_earned IN DATE
38 ,p_business_group_id IN NUMBER
39 ,p_person_age IN NUMBER
40 ,p_pension_type_id IN NUMBER
41 ,p_eligible OUT NOCOPY NUMBER
42 ,p_err_message OUT NOCOPY VARCHAR2)
43
44 RETURN NUMBER IS
45
46 --
47 --Cursor to fetch the min. and max. age specified at the pension type
48 --
49 CURSOR c_get_min_max_ages IS
50 SELECT nvl(minimum_age,0),nvl(maximum_age,100)
51 FROM pqp_pension_types_f
52 WHERE pension_type_id = p_pension_type_id
53 AND p_date_earned BETWEEN effective_start_date
54 AND effective_end_date;
55
56 l_min_age NUMBER := 0;
57 l_max_age NUMBER := 100;
58 l_ret_value NUMBER := 0;
59 l_proc_name VARCHAR2(30) := 'CHECK_ELIGIBILITY';
60
61 BEGIN
62
63 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
64 --Query up the min. and max. age specified at the pension type
65
66 OPEN c_get_min_max_ages;
67 FETCH c_get_min_max_ages INTO l_min_age,l_max_age;
68
69 IF c_get_min_max_ages%FOUND THEN
70 --the min and max ages have been found,now check for eligibility
71
72 CLOSE c_get_min_max_ages;
73 hr_utility.set_location('Min. and Max. ages are : '||l_min_age||
74 ' and '||l_max_age,20);
75
76 IF p_person_age BETWEEN l_min_age and l_max_age THEN
77 --the person is eligible for the pension type
78
79 hr_utility.set_location('Person is eligible, age is : '||p_person_age,30);
80 p_eligible := 1;
81
82 ELSE
83 --the person is not eligible for this pension type
84 hr_utility.set_location('Person is not eligible, age is : '||p_person_age,30);
85 p_err_message := 'This person is not eligible for the pension type';
86 p_eligible := 0;
87 l_ret_value := 2;
88
89 END IF;
90
91 ELSE
92 --no row could be found for this pension type
93 CLOSE c_get_min_max_ages;
94 hr_utility.set_location('No row could be found for this pension type',40);
95 p_err_message := 'No row could be found for this pension type on this date';
96 p_eligible := 0;
97 l_ret_value := 2;
98
99 END IF;
100
101 hr_utility.set_location('Returning from : '||g_pkg_name||l_proc_name,50);
102
103 RETURN 0;
104
105 EXCEPTION
106 WHEN OTHERS THEN
107 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,60);
108 p_eligible := 0;
109 p_err_message := 'Error occured when determining eligibility : '||SQLERRM;
110 RETURN 1;
111
112 END CHECK_ELIGIBILITY;
113
114 --
115 -- ----------------------------------------------------------------------------
116 -- |-------------------------< GET_CONTRIBUTION >-----------------------------|
117 -- ----------------------------------------------------------------------------
118 --
119 -- This function is used to get the contribution percentage / flat amount from
120 -- the org hierarchy or from the pension types table if there is no override
121 -- at the org hierarchy level
122
123 FUNCTION GET_CONTRIBUTION
124 (p_assignment_id IN NUMBER
125 ,p_date_earned IN DATE
126 ,p_business_group_id IN NUMBER
127 ,p_ee_or_total IN NUMBER
128 ,p_pension_type_id IN NUMBER
129 ,p_contrib_value OUT NOCOPY NUMBER
130 ,p_err_message OUT NOCOPY VARCHAR2)
131
132 RETURN NUMBER IS
133
134 --
135 -- Cursor to fetch the org id for a given assignment id
136 --
137 CURSOR c_get_org_id IS
138 SELECT organization_id
139 FROM per_all_assignments_f
140 WHERE assignment_id = p_assignment_id
141 AND p_date_earned BETWEEN effective_start_date
142 AND effective_end_date;
143
144 --
145 -- Cursor to get the parent org id for a given organization
146 -- given the version id of the org hierarchy defined
147 --
148 CURSOR c_get_parent_id(c_org_id IN NUMBER
149 ,c_version_id IN NUMBER) IS
150 SELECT organization_id_parent
151 FROM per_org_structure_elements
152 WHERE organization_id_child = c_org_id
153 AND org_structure_version_id = c_version_id
154 AND business_group_id = p_business_group_id;
155
156 --
157 -- Cursor to get the percentage value from the ORG EIT
158 --
159 CURSOR c_get_contrib_frm_org(c_org_id IN NUMBER) IS
160 SELECT decode(p_ee_or_total,0,nvl(fnd_number.canonical_to_number(org_information4),0)
161 ,nvl(fnd_number.canonical_to_number(org_information5),0))
162 FROM hr_organization_information
163 WHERE org_information_context = 'PQP_NL_PGGM_PT'
164 AND organization_id = c_org_id
165 AND p_date_earned BETWEEN fnd_date.canonical_to_date(org_information1)
166 AND nvl(fnd_date.canonical_to_date(org_information2),hr_api.g_eot)
167 AND fnd_number.canonical_to_number(org_information3) = p_pension_type_id;
168
169 --
170 -- Cursor to get the percentage value from the pension types table
171 --
172 CURSOR c_get_contrib_frm_pt IS
173 SELECT decode(p_ee_or_total,0,nvl(ee_contribution_percent,0)
174 ,nvl(er_contribution_percent,0))
175 FROM pqp_pension_types_f
176 WHERE pension_type_id = p_pension_type_id
177 AND p_date_earned BETWEEN effective_start_date
178 AND effective_end_date;
179
180 l_proc_name VARCHAR2(30) := 'GET_CONTRIBUTION';
181 l_loop_again NUMBER := 1;
182 l_emp_or_total VARCHAR2(30) := 'Employee';
183 l_org_contrib_found NUMBER := 0;
184 l_ret_value NUMBER := 0;
185 l_version_id NUMBER;
186 l_org_id NUMBER;
187 l_contrib_value NUMBER := 0;
188
189
190 BEGIN
191
192 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
193 --First fetch the HR Org Id for the current assignment
194 OPEN c_get_org_id;
195 FETCH c_get_org_id INTO l_org_id;
196 CLOSE c_get_org_id;
197 hr_utility.set_location('Org Id for this assignment is : '||l_org_id,20);
198
199 -- Now fetch the contribution percentages from the ORG EIT
200 -- This will proceed in a loop from the HR Organization
201 -- of this assignment and then up the org the hierarchy until
202 -- we find a EIT row or the topmost parent is reached
203
204 IF p_ee_or_total = 0 THEN
205 l_emp_or_total := 'Employee';
206 ELSE
207 l_emp_or_total := 'Total';
208 END IF;
209 hr_utility.set_location('Now deriving contribution percentage for : '||l_emp_or_total,25);
210
211 --check to see if the version id is already present for this business group
212 IF NOT g_version_info.EXISTS(p_business_group_id) THEN
213 --no cached value of the version id exists for this BG
214 g_version_info(p_business_group_id).version_id
215 := pqp_pension_functions.GET_VERSION_ID(p_business_group_id
216 ,p_date_earned);
217
218 END IF;
219
220 l_version_id := g_version_info(p_business_group_id).version_id;
221 hr_utility.set_location('Org Hierarchy version id : '||l_version_id,27);
222
223 WHILE (l_loop_again = 1)
224 LOOP
225 OPEN c_get_contrib_frm_org(l_org_id);
226 FETCH c_get_contrib_frm_org INTO l_contrib_value;
227
228 IF c_get_contrib_frm_org%FOUND THEN
229 --Contribution percentages have been found at this org
230 hr_utility.set_location('Contribution values found at org : '||l_org_id,30);
231 CLOSE c_get_contrib_frm_org;
232
233 p_contrib_value := fnd_number.canonical_to_number(l_contrib_value);
234
235 --set the flag indicating that contribution percentage has been found at the
236 --ORG level, so we dont need to continue any further
237 l_org_contrib_found := 1;
238
239 hr_utility.set_location('Contribution percentage is : '||p_contrib_value,40);
240 --we no longer need to continue up the hierarchy
241 l_loop_again := 0;
242
243 ELSE
244 --contribution percentages not found at this org, now move up the hierarchy
245 --find the parent org for this current org
246 CLOSE c_get_contrib_frm_org;
247 OPEN c_get_parent_id(c_org_id => l_org_id
248 ,c_version_id => l_version_id);
249 FETCH c_get_parent_id INTO l_org_Id;
250
251 IF c_get_parent_id%FOUND THEN
252 --a parent org has been found,so we can loop again
253 CLOSE c_get_parent_id;
254
255 ELSE
256 --no further parents exist,so exit the loop
257 CLOSE c_get_parent_id;
258 l_loop_again := 0;
259
260 --set the flag indicating that org contributions
261 --have not been found, so derive it from the Pension Type
262 l_org_contrib_found := 0;
263
264 END IF;
265
266 END IF;
267
268 END LOOP;
269
270 --now check to see if the contribution percentage
271 --has been found at the ORG level or do we need to
272 --derive it from the pension type
273 IF l_org_contrib_found = 0 THEN
274 hr_utility.set_location('No contribution values found at the org'||
275 ' ,now deriving it from the pension type',50);
276 --contribution values have not been found at the ORG level
277 --query up the contribution percentages from the pension type
278 OPEN c_get_contrib_frm_pt;
279 FETCH c_get_contrib_frm_pt INTO p_contrib_value;
280
281 IF c_get_contrib_frm_pt%FOUND THEN
282 --contribution percentages have been found from the pension type
283 hr_utility.set_location('Contribution derived from pension type : '
284 ||p_contrib_value,60);
285 CLOSE c_get_contrib_frm_pt;
286
287 ELSE
288 --no data has been found for this pension type, this is an error condition
289 CLOSE c_get_contrib_frm_pt;
290 hr_utility.set_location('No data could be found for the pension type on date earned',70);
291 p_contrib_value := 0;
292 p_err_message := 'No data could be found for the pension type attached to '
293 ||'this scheme on the date earned.';
294 l_ret_value := 2;
295
296 END IF;
297
298 END IF;
299
300 hr_utility.set_location('Returning from : '||g_pkg_name||l_proc_name,80);
301 RETURN l_ret_value;
302
303 EXCEPTION
304 WHEN OTHERS THEN
305 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,90);
306 p_contrib_value := 0;
307 p_err_message := 'Error occured when determining contribution : '||SQLERRM;
308 RETURN 1;
309
310 END GET_CONTRIBUTION;
311
312 --
313 -- ----------------------------------------------------------------------------
314 -- |-----------------------< GET_AGE_DEPENDANT_THLD>--------------------------|
315 -- ----------------------------------------------------------------------------
316 --
317 -- This function is used to derive the age dependant threshold for an employee
318 -- based on his/her age from a user defined table
319
320 FUNCTION GET_AGE_DEPENDANT_THLD
321 (p_person_age IN NUMBER
322 ,p_business_group_id IN NUMBER
323 ,p_date_earned IN DATE)
324
325 RETURN NUMBER IS
326
327 --
328 --Cursor to fetch the maximum age for which thresholds are defined
329 --all ages above this value have the same threshold
330 --
331 CURSOR c_get_max_age IS
332 SELECT max(fnd_number.canonical_to_number(row_low_range_or_name))
333 FROM pay_user_rows_f
334 WHERE p_date_earned BETWEEN effective_start_date
335 AND effective_end_date
336 AND user_table_id = (SELECT user_table_id
337 FROM pay_user_tables
338 WHERE user_table_name = 'PQP_NL_PGGM_AGE_DEPENDANT_THRESHOLD'
339 AND legislation_code = 'NL'
340 );
341
342 l_proc_name VARCHAR2(30) := 'GET_AGE_DEPENDANT_THLD';
343 l_return_value pay_user_column_instances.value%TYPE;
344 l_value_found NUMBER := 0;
345 l_threshold_percentage NUMBER := 0;
346 l_max_age NUMBER;
347
348 BEGIN
349
350 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
351
352 --first check to see if the user defined table for age dependant
353 --thresholds has a row for the person's age, then return this value
354 BEGIN
355 hr_utility.set_location('Checking for threshold percentage for age : '||p_person_age,20);
356 l_return_value :=
357 hruserdt.get_table_value
358 (
359 p_bus_group_id => p_business_group_id
360 ,p_table_name => 'PQP_NL_PGGM_AGE_DEPENDANT_THRESHOLD'
361 ,p_col_name => 'Percentage Of Maximum Threshold'
362 ,p_row_value => p_person_age
363 ,p_effective_date => p_date_earned
364 );
365
366 l_value_found := 1;
367 l_threshold_percentage := nvl(fnd_number.canonical_to_number(l_return_value),0);
368 hr_utility.set_location('Threshold percentage derived as : '||l_threshold_percentage,30);
369
370 EXCEPTION
371 WHEN NO_DATA_FOUND THEN
372 l_value_found := 0;
373
374 END;
375
376 --if no value has been found for the person's age, find the maximum age
377 --for which values have been defined, if the person's age exceeds this age
378 --then the value applicable for the person is the same as the value defined
379 --for the maximum age
380 IF l_value_found = 0 THEN
381
382 hr_utility.set_location('No row found for the person''s age,now finding max age',40);
383 --query up the maximum age defined in the rows for this user defined tbl
384 OPEN c_get_max_age;
385 FETCH c_get_max_age INTO l_max_age;
386 IF c_get_max_age%FOUND THEN
387
388 --Found the maximum age upto which thresholds have been defined
389 hr_utility.set_location('Max age in threshold udt : '||l_max_age,50);
390 CLOSE c_get_max_age;
391
392 --if the person's age is > the max age, then the threshold is the same
393 --as the value defined for this max age
394 IF p_person_age > l_max_age THEN
395
396 BEGIN
397 l_return_value :=
398 hruserdt.get_table_value
399 (
400 p_bus_group_id => p_business_group_id
401 ,p_table_name => 'PQP_NL_PGGM_AGE_DEPENDANT_THRESHOLD'
402 ,p_col_name => 'Percentage Of Maximum Threshold'
403 ,p_row_value => l_max_age
404 ,p_effective_date => p_date_earned
405 );
406 l_threshold_percentage := nvl(fnd_number.canonical_to_number(l_return_value),0);
407 hr_utility.set_location('value of max age used : '||l_threshold_percentage,60);
408
409 EXCEPTION
410 WHEN NO_DATA_FOUND THEN
411 l_threshold_percentage := 0;
412 END;
413
414 --else the person's age is lesser than the max age and no row has been defined
415 ELSE
416
417 l_threshold_percentage := 0;
418
419 END IF;
420
421 --else no rows have been defined for the user defined table
422 --so return the percentage as 0
423 ELSE
424
425 hr_utility.set_location('No rows were defined for the udt',70);
426 CLOSE c_get_max_age;
427 l_threshold_percentage := 0;
428
429 END IF;
430
431 END IF;
432
433 hr_utility.set_location('Value of threshold percentage is : '||l_threshold_percentage,75);
434 hr_utility.set_location('Leaving : '||g_pkg_name||l_proc_name,80);
435
436 RETURN l_threshold_percentage;
437
438 EXCEPTION
439 WHEN OTHERS THEN
440 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,90);
441 RETURN 0;
442
443 END GET_AGE_DEPENDANT_THLD;
444
445 --=============================================================================
446 -- Function to get the age of a person given the effective date
447 --=============================================================================
448 FUNCTION Get_Age
449 (p_assignment_id IN per_all_assignments_f.assignment_id%TYPE
450 ,p_effective_date IN DATE
451 ,p_begin_of_year_date IN DATE)
452 RETURN NUMBER IS
453
454 CURSOR get_dob IS
455 SELECT trunc(date_of_birth)
456 FROM per_all_people_f per
457 ,per_all_assignments_f paf
458 WHERE per.person_id = paf.person_id
459 AND paf.assignment_id = p_assignment_id
460 AND p_effective_date BETWEEN per.effective_start_date
461 AND per.effective_end_date
462 AND p_effective_date BETWEEN paf.effective_start_date
463 AND paf.effective_end_date;
464
465 l_age NUMBER;
466 l_dob DATE;
467
468 BEGIN
469
470 --
471 --Fetch the date of birth
472 --
473 OPEN get_dob;
474 FETCH get_dob INTO l_dob;
475 CLOSE get_dob;
476
477 l_dob := NVL(l_dob,p_effective_date);
478
479 RETURN (TRUNC(MONTHS_BETWEEN(p_begin_of_year_date,l_dob)/12,2));
480
481 END Get_Age;
482
483
484 --
485 -- ----------------------------------------------------------------------------
486 -- |-------------------------< GET_PENSION_BASIS >-----------------------------|
487 -- ----------------------------------------------------------------------------
488 --
489 -- This function is used to derive the pension basis value for a given pension
490 -- type based on the basis method defined
491
492 FUNCTION GET_PENSION_BASIS
493 (
494 p_payroll_action_id IN NUMBER
495 ,p_date_earned IN DATE
496 ,p_business_group_id IN NUMBER
497 ,p_person_age IN NUMBER
498 ,p_pension_type_id IN NUMBER
499 ,p_pension_salary IN NUMBER
500 ,p_part_time_percentage IN NUMBER
501 ,p_pension_basis OUT NOCOPY NUMBER
502 ,p_err_message OUT NOCOPY VARCHAR2
503 ,p_avlb_thld IN OUT NOCOPY NUMBER
504 ,p_used_thld IN OUT NOCOPY NUMBER)
505
506 RETURN NUMBER IS
507
508 --
509 --Cursor to fetch the basis method from the pension type
510 --
511 CURSOR c_get_basis_method IS
512 SELECT pension_basis_calc_method
513 FROM pqp_pension_types_f
514 WHERE pension_type_id = p_pension_type_id
515 AND p_date_earned BETWEEN effective_start_date
516 AND effective_end_date;
517
518 l_proc_name VARCHAR2(30) := 'GET_PENSION_BASIS';
519 l_ret_value NUMBER := 0;
520 l_threshold_salary NUMBER;
521 l_max_salary_threshold NUMBER;
522 l_max_age_threshold NUMBER;
523 l_threshold NUMBER;
524 l_threshold_percentage NUMBER;
525 l_avlb_thld NUMBER := 0;
526 l_used_thld NUMBER := 0;
527 l_basis_method pqp_pension_types_f.pension_basis_calc_method%TYPE;
528 l_num_periods NUMBER :=12;
529
530 BEGIN
531 --hr_utility.trace_on(null,'SS');
532 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
533
534 --first fetch the basis method for this pension type
535 OPEN c_get_basis_method;
536 FETCH c_get_basis_method INTO l_basis_method;
537 CLOSE c_get_basis_method;
538
539 --Get number of payroll periods in a year
540 OPEN c_get_num_periods_per_year(p_payroll_action_id);
541 FETCH c_get_num_periods_per_year INTO l_num_periods;
542 CLOSE c_get_num_periods_per_year;
543
544 --now calculate the basis value depending on the basis method
545 --derived above
546 IF l_basis_method = '6' THEN
547
548 --basis method is (Pension Salary - Salary dependant threshold)
549 -- * Part Time Percentage
550
551 hr_utility.set_location('Basis method : '||'(Pension Salary - Salary threshold)'
552 ||' * Part Time %',20);
553
554 --first derive the salary dependant threshold
555 --query up the maximum salary
556 OPEN c_get_global_value('PQP_NL_PGGM_THRESHOLD_SALARY',p_date_earned);
557 FETCH c_get_global_value INTO l_threshold_salary;
558
559 IF c_get_global_value%FOUND THEN
560 CLOSE c_get_global_value;
561 --the value for the threshold salary has been found
562 hr_utility.set_location('PQP_NL_PGGM_THRESHOLD_SALARY : '||l_threshold_salary,25);
563
564 ELSE
565 CLOSE c_get_global_value;
566 --the global value was not found,raise a warning
567 hr_utility.set_location('PQP_NL_PGGM_THRESHOLD_SALARY not found',25);
568 p_err_message := 'No value was found for the global PQP_NL_PGGM_THRESHOLD_SALARY';
569 l_ret_value := 2;
570
571 END IF;
572
573 --query up the maximum salary dependant threshold
574 OPEN c_get_global_value('PQP_NL_PGGM_MAX_SALARY_THRESHOLD',p_date_earned);
575 FETCH c_get_global_value INTO l_max_salary_threshold;
576
577 IF c_get_global_value%FOUND THEN
578 CLOSE c_get_global_value;
579 --the value for the salary threshold has been found
580 hr_utility.set_location('PQP_NL_PGGM_MAX_SALARY_THRESHOLD : '||l_max_salary_threshold,26);
581
582 ELSE
583 CLOSE c_get_global_value;
584 --the global value was not found,raise a warning
585 hr_utility.set_location('PQP_NL_PGGM_MAX_SALARY_THRESHOLD not found',26);
586 p_err_message := p_err_message || 'No value was found for the global'||
587 'PQP_NL_PGGM_MAX_SALARY_THRESHOLD';
588 l_ret_value := 2;
589
590 END IF;
591
592 IF (p_date_earned < to_date('01-01-2006','DD-MM-YYYY'))THEN
593 IF p_pension_salary >= l_threshold_salary THEN
594 l_threshold := l_max_salary_threshold;
595 ELSE
596 l_threshold := (p_pension_salary * l_max_salary_threshold)/
597 (l_threshold_salary + 1);
598 END IF;
599 ELSE --Legislative year 2006 Change
600 l_threshold := l_max_salary_threshold; -- 9566 fixed value
601 END IF;
602
603 hr_utility.set_location('Salary Dependant Threshold : '||l_threshold,30);
604
605 p_pension_basis := (p_pension_salary - l_threshold)
606 * p_part_time_percentage/100;
607
608 p_pension_basis := p_pension_basis / l_num_periods;
609
610 ELSIF l_basis_method = '7' THEN
611
612 --basis method is Pension Salary * Part Time Percentage
613 hr_utility.set_location('Basis method : '||'(Pension Salary * Part Time %)',20);
614 p_pension_basis := p_pension_salary * p_part_time_percentage/100;
615
616 p_pension_basis := p_pension_basis / l_num_periods;
617
618 ELSIF l_basis_method = '8' THEN
619
620 --basis method is (Pension Salary * Part Time Percentage) -
621 -- Age Dependant Threshold
622 hr_utility.set_location('Basis method : '||'(Pension Salary * Part Time %)'
623 ||' - Age Threshold',20);
624
625 --query up the maximum age dependant threshold
626 OPEN c_get_global_value('PQP_NL_PGGM_MAX_AGE_THRESHOLD',p_date_earned);
627 FETCH c_get_global_value INTO l_max_age_threshold;
628
629 IF c_get_global_value%FOUND THEN
630 CLOSE c_get_global_value;
631 --the value for the age threshold has been found
632 hr_utility.set_location('PQP_NL_PGGM_MAX_AGE_THRESHOLD : '||l_max_age_threshold,22);
633
634 ELSE
635 CLOSE c_get_global_value;
636 --the global value was not found,raise a warning
637 hr_utility.set_location('PQP_NL_PGGM_MAX_AGE_THRESHOLD not found',22);
638 p_err_message := p_err_message || 'No value was found for the global'||
639 'PQP_NL_PGGM_MAX_AGE_THRESHOLD';
640 l_ret_value := 2;
641
642 END IF;
643
644 l_threshold_percentage := GET_AGE_DEPENDANT_THLD(p_person_age => p_person_age
645 ,p_business_group_id => p_business_group_id
646 ,p_date_earned => p_date_earned);
647
648 IF l_threshold_percentage = 0 THEN
649 p_err_message := p_err_message ||' The age dependant threshold could not be '
650 ||'derived for this person and 0 will be used';
651 l_ret_value := 2;
652 END IF;
653
654 --Calculate Age dependent Threshold value and drop the decimals
655 l_threshold := trunc(l_max_age_threshold * l_threshold_percentage/100);
656
657 hr_utility.set_location('Age Dependant Threshold : '||l_threshold,30);
658 hr_utility.set_location('Available threshold : '||l_avlb_thld,30);
659 hr_utility.set_location('Used Threshold : '||l_used_thld,30);
660
661 l_avlb_thld := l_threshold/l_num_periods;
662
663 l_threshold := GREATEST((p_avlb_thld + l_threshold/l_num_periods - p_used_thld),0);
664
665 p_pension_basis := (p_pension_salary * p_part_time_percentage/100)/l_num_periods -
666 l_threshold;
667
668 IF p_pension_basis < 0 THEN
669 l_used_thld := (p_pension_salary * p_part_time_percentage/100)/l_num_periods;
670 ELSE
671 l_used_thld := l_threshold;
672 END IF;
673
674 END IF;
675
676 /*
677 Bug 5215600
678 SR : 5461519.993
679 --if the calculated pension basis is < 0 then restrict it to 0
680 IF p_pension_basis < 0 THEN
681 p_pension_basis := 0;
682 END IF;
683 */
684 p_avlb_thld := l_avlb_thld;
685 p_used_thld := l_used_thld;
686
687 hr_utility.set_location('Calculated pension basis value : '||p_pension_basis,40);
688 hr_utility.set_location('Available threshold : '||l_avlb_thld,40);
689 hr_utility.set_location('Used Threshold : '||l_used_thld,40);
690
691 hr_utility.set_location('Leaving : '||g_pkg_name||l_proc_name,50);
692 --hr_utility.trace_off;
693
694 RETURN l_ret_value;
695
696 EXCEPTION
697 WHEN OTHERS THEN
698 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,60);
699 p_pension_basis := 0;
700 p_err_message := 'Error occured while deriving the pension basis : '||SQLERRM;
701 RETURN 1;
702
703 END GET_PENSION_BASIS;
704
705 --
706 -- ----------------------------------------------------------------------------
707 -- |---------------------------< DO_PRORATION >-------------------------------|
708 -- ----------------------------------------------------------------------------
709 --
710 -- This function is used to perform a calendar day proration of the deduction
711 -- amount for starter/leavers
712
713 FUNCTION DO_PRORATION
714 (p_assignment_id IN NUMBER
715 ,p_payroll_action_id IN NUMBER
716 ,p_period_start_date IN DATE
717 ,p_period_end_date IN DATE
718 ,p_dedn_amount IN OUT NOCOPY NUMBER
719 ,p_err_message OUT NOCOPY VARCHAR2)
720
721 RETURN NUMBER IS
722
723 --
724 --Cursor to fetch the range of dates for which the assignment
725 --is active in the pay period
726 --
727 CURSOR c_get_asg_dates IS
728 SELECT asg.effective_start_date start_date
729 ,nvl(asg.effective_end_date,p_period_end_date) end_date
730 FROM per_all_assignments_f asg,per_assignment_status_types past
731 WHERE asg.assignment_id = p_assignment_id
732 AND asg.assignment_status_type_id = past.assignment_status_type_id
733 AND past.per_system_status = 'ACTIVE_ASSIGN'
734 AND asg.effective_start_date <= p_period_end_date
735 AND nvl(asg.effective_end_date,p_period_end_date)
736 >= p_period_start_date;
737
738 --
739 --Cursor to fetch period type of payroll attached to assignment
740 --
741 CURSOR c_get_period_type(c_payroll_action_id IN NUMBER)
742 IS
743 SELECT TPERIOD.period_type
744 FROM pay_payroll_actions PACTION
745 ,per_time_periods TPERIOD
746 WHERE PACTION.payroll_action_id = c_payroll_action_id
747 AND TPERIOD.payroll_id = PACTION.payroll_id
748 AND (PACTION.date_earned between TPERIOD.start_date
749 and TPERIOD.end_date);
750
751
752 c_asg_row c_get_asg_dates%ROWTYPE;
753
754 l_proc_name VARCHAR2(30) := 'DO_PRORATION';
755 l_ret_value NUMBER := 0;
756 l_start_date DATE;
757 l_end_date DATE;
758 l_days NUMBER := 0;
759 l_payroll_days NUMBER := 0;
760 l_non_insured_days NUMBER := 0;
761 l_proration_factor NUMBER := 1;
762 l_period_type VARCHAR2(150);
763 l_num_of_days_in_period NUMBER:=30;
764
765 BEGIN
766
767 --first fetch the range of dates when the assignment is
768 --active in the pay period
769 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
770
771 OPEN c_get_period_type(p_payroll_action_id);
772 FETCH c_get_period_type INTO l_period_type;
773 CLOSE c_get_period_type;
774 IF l_period_type='Calendar Month' THEN
775 l_num_of_days_in_period:= 30;
776 ELSE IF l_period_type = 'Lunar Month' THEN
777 l_num_of_days_in_period:=28;
778 ELSE IF l_period_type = 'Week' THEN
779 l_num_of_days_in_period:=7;
780 ELSE IF l_period_type = 'Quarter' THEN
781 l_num_of_days_in_period:=90;
782 END IF;
783 END IF;
784 END IF;
785 END IF;
786
787 FOR c_asg_row IN c_get_asg_dates
788 LOOP
789 --loop through all assignment rows effective in this pay period
790 --and find the number of days the person is insured for
791 IF c_asg_row.start_date < p_period_start_date THEN
792 l_start_date := p_period_start_date;
793 ELSE
794 l_start_date := c_asg_row.start_date;
795 END IF;
796
797 IF c_asg_row.end_date > p_period_end_date THEN
798 l_end_date := p_period_end_date;
799 ELSE
800 l_end_date := c_asg_row.end_date;
801 END IF;
802
803 l_days := l_days + (l_end_date - l_start_date) + 1;
804
805 END LOOP;
806
807 hr_utility.set_location('Assignment was active for : '||l_days||' days',20);
808
809 --now find the days the person was not insured for in this period
810 --first find the total number of days in this pay period
811
812 l_payroll_days := p_period_end_date - p_period_start_date + 1;
813 hr_utility.set_location('Days in pay period : '||l_payroll_days,30);
814
815 --the non insured days in the difference of the pay period days and
816 --the number of days the assignment has been active
817 --if the assignment has not been active any day in the pay period
818 --then the non insured days is taken as 30 to make the proration
819 --factor 0
820
821 IF l_days > 0 THEN
822 l_non_insured_days := l_payroll_days - l_days;
823 ELSE
824 l_non_insured_days := l_num_of_days_in_period;
825 p_err_message := 'Assignment was not active in this pay period, so '||
826 'deduction amount is prorated as 0';
827 l_ret_value := 2;
828 END IF;
829
830 hr_utility.set_location('Non insured days : '||l_non_insured_days,40);
831
832 --now derive the proration factor, the days in a pay period are
833 --taken as 30 for this purpose, so we need to first find the days the
834 --person has been insured for in the period, ie (30 - days not insured)
835 --the proration factor is then this number divided by 30
836
837 l_proration_factor := (l_num_of_days_in_period - l_non_insured_days) / l_num_of_days_in_period;
838 hr_utility.set_location('Proration factor is : '||l_proration_factor,50);
839
840 --now multiply the deduction amount with the proration factor to
841 --find the prorated amount
842 hr_utility.set_location('Original deduction amount : '||p_dedn_amount,60);
843
844 p_dedn_amount := p_dedn_amount * l_proration_factor;
845
846 hr_utility.set_location('Prorated deduction amount : '||p_dedn_amount,70);
847 hr_utility.set_location('Leaving : '||g_pkg_name||l_proc_name,80);
848
849 RETURN l_ret_value;
850
851 EXCEPTION
852 WHEN OTHERS THEN
853 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,90);
854 p_dedn_amount := 0;
855 p_err_message := 'Error occured while prorating : '||SQLERRM;
856 RETURN 1;
857
858 END DO_PRORATION;
859
860 --
861 -- ----------------------------------------------------------------------------
862 -- |--------------------------< GET_GENERAL_INFO >-----------------------------|
863 -- ----------------------------------------------------------------------------
864 --
865 -- This function is used to derive the general information such as holiday allowance
866 -- and end of year bonus percentage from the org extra information by traversing
867 -- the org hierarchy
868
869 FUNCTION GET_GENERAL_INFO
870 (p_assignment_id IN NUMBER
871 ,p_business_group_id IN NUMBER
872 ,p_date_earned IN DATE
873 ,p_code IN NUMBER
874 ,p_value OUT NOCOPY NUMBER)
875
876 RETURN NUMBER IS
877
878 --
879 -- Cursor to fetch the org id for the current assignment
880 --
881 CURSOR c_get_org_id IS
882 SELECT organization_id
883 FROM per_all_assignments_f
884 WHERE assignment_id = p_assignment_id
885 AND p_date_earned BETWEEN effective_start_date
886 AND effective_end_date;
887
888 --
889 -- Cursor to fetch the parent id for a given organization id
890 -- for a particular hierarchy version id
891 --
892 CURSOR c_get_parent_id(c_org_id IN NUMBER
893 ,c_version_id IN NUMBER) IS
894 SELECT organization_id_parent
895 FROM per_org_structure_elements
896 WHERE organization_id_child = c_org_id
897 AND org_structure_version_id = c_version_id
898 AND business_group_id = p_business_group_id;
899
900 --
901 -- Cursor to fetch the holiday allowance or eoy bonus
902 -- percentage from the relevant segment based on the
903 -- code passed in
904 -- Code 0 => Holiday Allowance Percentage
905 -- Code 1 => End Of Year Bonus Percentage
906 --
907 CURSOR c_get_general_info(c_org_id IN NUMBER) IS
908 SELECT decode(p_code,0,org_information3,1,org_information4)
909 FROM hr_organization_information
910 WHERE organization_id = c_org_id
911 AND org_information_context = 'PQP_NL_PGGM_INFO'
912 AND p_date_earned BETWEEN fnd_date.canonical_to_date(org_information1)
913 AND fnd_date.canonical_to_date(nvl(org_information2,fnd_date.date_to_canonical(hr_api.g_eot)))
914 AND decode(p_code,0,org_information3,1,org_information4) IS NOT NULL;
915
916 l_proc_name VARCHAR2(30) := 'GET_GENERAL_INFO';
917 l_org_id NUMBER;
918 l_value hr_organization_information.org_information1%TYPE;
919 l_loop_again NUMBER := 1;
920 l_version_id NUMBER;
921
922 BEGIN
923 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
924
925 --initialise the percentage return value to 0
926 p_value := 0;
927
928 -- fetch the org id for the organization this assignment is attached to
929 OPEN c_get_org_id;
930 FETCH c_get_org_id INTO l_org_id;
931 IF c_get_org_id%NOTFOUND THEN
932 --org id for the assignment could not be found
933 --return 1 and a value of 0
934 CLOSE c_get_org_id;
935 p_value := 0;
936 RETURN 1;
937 ELSE
938 --org id was found
939 CLOSE c_get_org_id;
940 hr_utility.set_location('Org id for the ASG : '||l_org_id,20);
941
942 -- now find the holiday allowance/eoy bonus percentage from the
943 -- org extra information and by traversing the org hierarchy
944 --check to see if the version id is already present for this business group
945
946 IF NOT g_version_info.EXISTS(p_business_group_id) THEN
947 --no cached value of the version id exists for this BG
948 g_version_info(p_business_group_id).version_id
949 := pqp_pension_functions.GET_VERSION_ID(p_business_group_id
950 ,p_date_earned);
951
952 END IF;
953
954 l_version_id := g_version_info(p_business_group_id).version_id;
955 hr_utility.set_location('Org Hierarchy version id : '||l_version_id,30);
956
957 WHILE (l_loop_again = 1)
958 LOOP
959 OPEN c_get_general_info(l_org_id);
960 FETCH c_get_general_info INTO l_value;
961
962 IF c_get_general_info%FOUND THEN
963 --holiday allowance /eoy bonus percentages have been found at this org
964 hr_utility.set_location('Percentages found at org : '||l_org_id,40);
965 CLOSE c_get_general_info;
966
967 p_value := fnd_number.canonical_to_number(l_value);
968
969 hr_utility.set_location('Percentage is : '||p_value,50);
970 --we no longer need to continue up the hierarchy
971 l_loop_again := 0;
972
973 ELSE
974 -- percentages not found at this org, now move up the hierarchy
975 --find the parent org for this current org
976 CLOSE c_get_general_info;
977 OPEN c_get_parent_id(c_org_id => l_org_id
978 ,c_version_id => l_version_id);
979 FETCH c_get_parent_id INTO l_org_Id;
980
981 IF c_get_parent_id%FOUND THEN
982 --a parent org has been found,so we can loop again
983 CLOSE c_get_parent_id;
984
985 ELSE
986 --no further parents exist,so exit the loop
987 CLOSE c_get_parent_id;
988 l_loop_again := 0;
989
990 -- no value has been found , so set it to 0
991 p_value := 0;
992
993 END IF;
994
995 END IF;
996
997 END LOOP;
998
999 END IF;
1000
1001 hr_utility.set_location('Percentage value : '||p_value,55);
1002 hr_utility.set_location('Leaving : '||g_pkg_name||l_proc_name,60);
1003
1004 RETURN 0;
1005
1006 EXCEPTION
1007 WHEN OTHERS THEN
1008 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,70);
1009 p_value := 0;
1010 RETURN 1;
1011
1012 END GET_GENERAL_INFO;
1013
1014
1015 -- ----------------------------------------------------------------------------
1016 -- |------------------------<GET_PENSION_SALARY >------------------------------|
1017 -- ----------------------------------------------------------------------------
1018 --
1019 FUNCTION GET_PENSION_SALARY
1020 (p_assignment_id IN NUMBER
1021 ,p_date_earned IN DATE
1022 ,p_business_group_id IN NUMBER
1023 ,p_payroll_id IN NUMBER
1024 ,p_period_start_date IN DATE
1025 ,p_period_end_date IN DATE
1026 ,p_scale_salary IN NUMBER
1027 ,p_scale_salary_h IN NUMBER
1028 ,p_scale_salary_e IN NUMBER
1029 ,p_ft_rec_payments IN NUMBER
1030 ,p_ft_rec_payments_h IN NUMBER
1031 ,p_ft_rec_payments_e IN NUMBER
1032 ,p_pt_rec_payments IN NUMBER
1033 ,p_pt_rec_payments_h IN NUMBER
1034 ,p_pt_rec_payments_e IN NUMBER
1035 ,p_salary_balance_value OUT NOCOPY NUMBER
1036 ,p_err_message OUT NOCOPY VARCHAR2
1037 ,p_err_message1 OUT NOCOPY VARCHAR2
1038 ,p_err_message2 OUT NOCOPY VARCHAR2
1039 )
1040 RETURN NUMBER IS
1041
1042 --
1043 -- Cursor to get the hire date of the person
1044 --
1045 CURSOR c_hire_dt_cur(c_asg_id IN NUMBER) IS
1046 SELECT max(date_start)
1047 FROM per_all_assignments_f asg
1048 ,per_periods_of_service pps
1049 WHERE pps.person_id = asg.person_id
1050 AND asg.assignment_id = c_asg_id
1051 AND pps.business_group_id = p_business_group_id
1052 AND date_start <= p_date_earned;
1053
1054 --
1055 --Cursor to fetch the part time percentage from the
1056 --assignment standard conditions for a given effective date
1057 --
1058 CURSOR c_pt_cur (c_effective_date IN DATE) IS
1059 SELECT fnd_number.canonical_to_number(NVL(target.SEGMENT29,'100')) pt_perc
1060 FROM per_assignments_f asg
1061 ,hr_soft_coding_keyflex target
1062 WHERE asg.assignment_id = p_assignment_id
1063 AND target.soft_coding_keyflex_id = asg.soft_coding_keyflex_id
1064 AND trunc(c_effective_date) between asg.effective_start_date
1065 AND asg.effective_end_date
1066 AND target.enabled_flag = 'Y';
1067
1068 --
1069 --Cursor to fetch the assignment start date
1070 --
1071 CURSOR c_get_asg_start IS
1072 SELECT min(effective_start_date)
1073 FROM per_all_assignments_f
1074 WHERE assignment_id = p_assignment_id;
1075
1076 --
1077 -- Cursor to get the defined balance id for a given balance and dimension
1078 --
1079 CURSOR csr_defined_bal (c_balance_name IN VARCHAR2
1080 ,c_dimension_name IN VARCHAR2
1081 ,c_business_group_id IN NUMBER) IS
1082 SELECT db.defined_balance_id
1083 FROM pay_balance_types pbt
1084 ,pay_defined_balances db
1085 ,pay_balance_dimensions bd
1086 WHERE pbt.balance_name = c_balance_name
1087 AND pbt.balance_type_id = db.balance_type_id
1088 AND bd.balance_dimension_id = db.balance_dimension_id
1089 AND bd.dimension_name = c_dimension_name
1090 AND (pbt.business_group_id = c_business_group_id OR
1091 pbt.legislation_code = 'NL')
1092 AND (db.business_group_id = pbt.business_group_id OR
1093 db.legislation_code = 'NL');
1094
1095 --
1096 -- Cursor to get the holiday allowance global
1097 --
1098 CURSOR c_global_cur(c_global_name IN VARCHAR2) IS
1099 SELECT fnd_number.canonical_to_number(global_value)
1100 FROM ff_globals_f
1101 WHERE global_name = c_global_name
1102 AND trunc (p_date_earned) BETWEEN effective_start_date
1103 AND effective_end_date;
1104
1105 --
1106 -- Cursor to get the collective agreement name as of 1 Jan/Hire Date
1107 --
1108 CURSOR c_cag_name (c_asg_id IN NUMBER
1109 ,c_eff_date IN DATE) IS
1110 SELECT cola.name
1111 FROM per_collective_agreements cola
1112 ,per_all_assignments_f asg
1113 WHERE asg.assignment_id = c_asg_id
1114 AND asg.collective_agreement_id = cola.collective_agreement_id
1115 AND cola.status = 'A'
1116 AND c_eff_date BETWEEN asg.effective_start_date
1117 AND asg.effective_end_date
1118 AND c_eff_date BETWEEN cola.start_date
1119 AND NVL(cola.end_date,to_date('31/12/4712','DD/MM/YYYY'));
1120
1121 --
1122 -- Cursor to get the number of pay periods per year.
1123 --
1124 CURSOR c_pp_cur IS
1125 SELECT pety.number_per_fiscal_year
1126 FROM pay_payrolls_f ppaf
1127 ,per_time_period_types pety
1128 WHERE ppaf.payroll_id = p_payroll_id
1129 AND ppaf.period_type = pety.period_type;
1130
1131 --
1132 --Cursor to fetch the org id for the organization
1133 --attached to this assignment
1134 --
1135 CURSOR c_get_org_id(c_eff_date IN DATE) IS
1136 SELECT organization_id
1137 FROM per_all_assignments_f
1138 WHERE assignment_id = p_assignment_id
1139 AND c_eff_date BETWEEN effective_start_date
1140 AND effective_end_date;
1141
1142 --
1143 -- Cursor to get the value for EOY Bonus override percent
1144 --
1145 CURSOR c_eoy_per_or (c_asg_id IN NUMBER
1146 ,c_effective_date IN DATE) IS
1147 select min (fffunc.cn(decode(
1148 decode(INPUTV.uom,'M','N','N','N','I','N',null),'N',decode(INPUTV.hot_default_flag,'Y',nvl(EEV.screen_entry_value,
1149 nvl(LIV.default_value,INPUTV.default_value)),'N',EEV.screen_entry_value),null))) eoy_or
1150 FROM pay_element_entry_values_f EEV,
1151 pay_element_entries_f EE,
1152 pay_link_input_values_f LIV,
1153 pay_input_values_f INPUTV,
1154 pay_element_types_f pet
1155 WHERE INPUTV.element_type_id = pet.element_type_id
1156 AND INPUTV.name = 'End of Year Bonus Percentage'
1157 AND c_effective_date BETWEEN INPUTV.effective_start_date
1158 AND INPUTV.effective_end_date
1159 AND INPUTV.element_type_id = pet.element_type_id
1160 AND c_effective_date BETWEEN pet.effective_start_date
1161 AND pet.effective_end_date
1162 AND pet.element_name = 'PGGM Pensions General Information'
1163 AND pet.legislation_code = 'NL'
1164 AND LIV.input_value_id = INPUTV.input_value_id
1165 AND c_effective_date BETWEEN LIV.effective_start_date
1166 AND LIV.effective_end_date
1167 AND EEV.input_value_id + 0 = INPUTV.input_value_id
1168 AND EEV.element_entry_id = EE.element_entry_id
1169 AND EEV.effective_start_date = EE.effective_start_date
1170 AND EEV.effective_end_date = EE.effective_end_date
1171 AND EE.element_link_id = LIV.element_link_id
1172 AND EE.assignment_id = c_asg_id
1173 AND c_effective_date BETWEEN EE.effective_start_date
1174 AND EE.effective_end_date ;
1175
1176 --
1177 -- Cursor to get the value for Holiday Allowance override percent
1178 --
1179 CURSOR c_ha_per_or (c_asg_id IN NUMBER
1180 ,c_effective_date IN DATE) IS
1181 select min (fffunc.cn(decode(
1182 decode(INPUTV.uom,'M','N','N','N','I','N',null),'N',decode(INPUTV.hot_default_flag,'Y',nvl(EEV.screen_entry_value,
1183 nvl(LIV.default_value,INPUTV.default_value)),'N',EEV.screen_entry_value),null))) ha_or
1184 FROM pay_element_entry_values_f EEV,
1185 pay_element_entries_f EE,
1186 pay_link_input_values_f LIV,
1187 pay_input_values_f INPUTV,
1188 pay_element_types_f pet
1189 WHERE INPUTV.element_type_id = pet.element_type_id
1190 AND INPUTV.name = 'Holiday Allowance Percentage'
1191 AND c_effective_date BETWEEN INPUTV.effective_start_date
1192 AND INPUTV.effective_end_date
1193 AND INPUTV.element_type_id = pet.element_type_id
1194 AND c_effective_date BETWEEN pet.effective_start_date
1195 AND pet.effective_end_date
1196 AND pet.element_name = 'PGGM Pensions General Information'
1197 AND pet.legislation_code = 'NL'
1198 AND LIV.input_value_id = INPUTV.input_value_id
1199 AND c_effective_date BETWEEN LIV.effective_start_date
1200 AND LIV.effective_end_date
1201 AND EEV.input_value_id + 0 = INPUTV.input_value_id
1202 AND EEV.element_entry_id = EE.element_entry_id
1203 AND EEV.effective_start_date = EE.effective_start_date
1204 AND EEV.effective_end_date = EE.effective_end_date
1205 AND EE.element_link_id = LIV.element_link_id
1206 AND EE.assignment_id = c_asg_id
1207 AND c_effective_date BETWEEN EE.effective_start_date
1208 AND EE.effective_end_date ;
1209
1210 -- =============================================================================
1211 --Cursor to fetch Start date of a year
1212 -- =============================================================================
1213 CURSOR c_get_period_start_date ( c_year IN VARCHAR2
1214 )
1215 IS
1216 SELECT NVL(min(PTP.start_date),to_date('0101'||c_year,'DDMMYYYY'))
1217 FROM per_time_periods PTP
1218 WHERE
1219 PTP.payroll_id = p_payroll_id
1220 AND (substr(PTP.period_name,4,4)=c_year
1221 OR substr(PTP.period_name,3,4)=c_year);
1222
1223 l_loop_again NUMBER;
1224 l_valid_pt NUMBER;
1225 l_org_id NUMBER;
1226 l_run_year NUMBER;
1227 l_begin_of_year_date DATE;
1228 l_end_of_last_year DATE;
1229 l_effective_date DATE;
1230 l_hire_date DATE;
1231 l_asg_st_date DATE;
1232 l_jan_hire_ptp NUMBER;
1233 l_error_message VARCHAR2(1000);
1234 l_defined_balance_id NUMBER;
1235 l_scale_salary NUMBER := nvl(p_scale_salary,0);
1236 l_scale_salary_h NUMBER := nvl(p_scale_salary_h,0);
1237 l_scale_salary_e NUMBER := nvl(p_scale_salary_e,0);
1238 l_ft_rec_paymnt NUMBER := nvl(p_ft_rec_payments,0);
1239 l_ft_rec_paymnt_h NUMBER := nvl(p_ft_rec_payments_h,0);
1240 l_ft_rec_paymnt_e NUMBER := nvl(p_ft_rec_payments_e,0);
1241 l_pt_rec_paymnt NUMBER := nvl(p_pt_rec_payments,0);
1242 l_pt_rec_paymnt_h NUMBER := nvl(p_pt_rec_payments_h,0);
1243 l_pt_rec_paymnt_e NUMBER := nvl(p_pt_rec_payments_e,0);
1244 l_holiday_allowance NUMBER := 0;
1245 l_holiday_allow_per NUMBER := 0;
1246 l_min_holiday_allow NUMBER := 0;
1247 l_min_holiday_char VARCHAR2(80);
1248 l_eoy_bonus NUMBER := 0;
1249 l_eoy_bonus_per NUMBER := 0;
1250 l_min_eoy_bonus NUMBER := 0;
1251 l_min_eoy_bonus_char VARCHAR2(80);
1252 l_cag_name per_collective_agreements.name%TYPE;
1253 l_max_periods NUMBER;
1254 l_max_ptp NUMBER := 0;
1255 l_prev_max_ptp NUMBER := 0;
1256 l_ret_val NUMBER := 0;
1257 l_error_status CHAR;
1258 l_message_flag CHAR;
1259 UDT_CONTAINS_NO_DATA EXCEPTION;
1260 l_proc_name VARCHAR2(30) := 'GET_PENSION_SALARY';
1261 l_asg_eoy_bonus_per NUMBER;
1262 l_asg_ha_per NUMBER;
1263 l_ignore_eoy_cag NUMBER;
1264 l_ignore_ha_cag NUMBER;
1265 l_min_age_holiday_allow VARCHAR2(50);
1266 l_person_age NUMBER;
1267 l_first_date_of_year DATE;
1268
1269 BEGIN
1270 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
1271 --hr_utility.trace_on(null,'SS');
1272
1273 --initialise the error message params
1274 p_err_message := ' ';
1275 p_err_message1 := ' ';
1276 p_err_message2 := ' ';
1277
1278 --derive the year in which payroll is being run
1279 l_run_year := to_number(to_char(p_date_earned,'YYYY'));
1280 hr_utility.set_location('Payroll run year : '||l_run_year,20);
1281
1282 OPEN c_get_period_start_date(l_run_year);
1283 FETCH c_get_period_start_date INTO l_first_date_of_year;
1284 CLOSE c_get_period_start_date;
1285
1286 -- Get the first date of the run year
1287 l_begin_of_year_date := l_first_date_of_year;
1288
1289 -- Get the latest start date of the assignment
1290 OPEN c_get_asg_start;
1291 FETCH c_get_asg_start INTO l_asg_st_date;
1292
1293 IF c_get_asg_start%FOUND THEN
1294 CLOSE c_get_asg_start;
1295 ELSE
1296 CLOSE c_get_asg_start;
1297 p_err_message := 'Error: Unable to find the start date of the assignment';
1298 p_salary_balance_value := 0;
1299 RETURN 1;
1300
1301 END IF;
1302
1303 hr_utility.set_location('Asg start date : '||l_asg_st_date,30);
1304
1305 -- Get the hire date
1306 OPEN c_hire_dt_cur (p_assignment_id);
1307 FETCH c_hire_dt_cur INTO l_hire_date;
1308
1309 IF c_hire_dt_cur%FOUND THEN
1310 CLOSE c_hire_dt_cur;
1311 hr_utility.set_location('Hire date is : '||l_hire_date,40);
1312 -- The effective date is now the valid assignemnt
1313 --start date for the assignment
1314 l_effective_date := pqp_nl_abp_functions.get_valid_start_date
1315 (p_assignment_id,
1316 p_date_earned,
1317 l_error_status,
1318 l_error_message);
1319
1320 --if an error occured while fetching the valid start date
1321 IF(l_error_status = trim(to_char(1,'9'))) THEN
1322 hr_utility.set_location('Error occured while fetching valid start date',50);
1323 fnd_message.set_name('PQP',l_error_message);
1324 p_err_message :='Error : '|| fnd_message.get();
1325 p_salary_balance_value :=0;
1326 RETURN 1;
1327 ELSE
1328 hr_utility.set_location('Valid start date fetched : '||l_effective_date,50);
1329 END IF;
1330
1331 ELSE
1332 CLOSE c_hire_dt_cur;
1333 hr_utility.set_location('Hire date could not be found',60);
1334 p_err_message := 'Error: Unable to find the hire date for the person ';
1335 p_salary_balance_value :=0;
1336 RETURN 1;
1337 END IF;
1338
1339 -- Get the maximum number of periods in a year.
1340 OPEN c_pp_cur;
1341 FETCH c_pp_cur INTO l_max_periods;
1342
1343 IF c_pp_cur%NOTFOUND THEN
1344 p_err_message := 'Error: Unable to find the pay periods per year';
1345 p_salary_balance_value :=0;
1346 CLOSE c_pp_cur;
1347 RETURN 1;
1348 ELSE
1349 CLOSE c_pp_cur;
1350 END IF;
1351
1352 hr_utility.set_location('Number of periods in a year : '||l_max_periods,70);
1353 hr_utility.set_location('Deriving the part time percentage',80);
1354
1355 -- Calculate the ptp as of 1 jan or Hire Date
1356 OPEN c_pt_cur (l_effective_date);
1357 FETCH c_pt_cur INTO l_jan_hire_ptp;
1358
1359 IF c_pt_cur%NOTFOUND THEN
1360 CLOSE c_pt_cur;
1361 hr_utility.set_location('No value found for part time percentage',90);
1362 p_err_message := 'Error: Unable to find the part time percentage.';
1363 p_err_message := p_err_message || 'Please enter a value as of 1 January or Hire Date';
1364 p_salary_balance_value :=0;
1365 RETURN 1;
1366 ELSE
1367 CLOSE c_pt_cur;
1368 END IF;
1369
1370 IF l_jan_hire_ptp = 0 THEN
1371 l_jan_hire_ptp := 100;
1372 END IF;
1373
1374 l_jan_hire_ptp := LEAST(l_jan_hire_ptp,125);
1375
1376 hr_utility.set_location('Part Time Percentage used for salary : '||l_jan_hire_ptp,100);
1377 l_jan_hire_ptp := l_jan_hire_ptp/100;
1378
1379 -- Divide all the part time balances by this value
1380
1381 l_pt_rec_paymnt := l_pt_rec_paymnt/l_jan_hire_ptp;
1382 l_pt_rec_paymnt_h := l_pt_rec_paymnt_h/l_jan_hire_ptp;
1383 l_pt_rec_paymnt_e := l_pt_rec_paymnt_e/l_jan_hire_ptp;
1384
1385 --
1386 -- EOY Bonus Calculation
1387 -- This section will calculate the end of year bonus
1388 -- based on the EOY Bonus percentage specified at the
1389 -- org level. These will be derived from the following
1390 -- three balances.
1391 --
1392 -- PGGM Scale Salary For End Of Year Bonus
1393 -- PGGM Full Time Recurring Payments For End Of Year Bonus
1394 -- PGGM Part Time Recurring Payments For End Of Year Bonus
1395 --
1396
1397 --
1398 -- Check to see if the EOY Bonus has been overridden
1399 -- at the assignment input value level. If it has been overridden
1400 -- and is not null. Use this value and do not derive from the org.
1401 -- Otherwise derive it from the org.
1402 -- It is imp to note that if the value is 0, then do not consider
1403 -- the min at the CAG level.
1404 --
1405 OPEN c_eoy_per_or(p_assignment_id
1406 ,l_effective_date);
1407 FETCH c_eoy_per_or INTO l_asg_eoy_bonus_per;
1408 IF c_eoy_per_or%FOUND THEN
1409
1410 l_eoy_bonus_per := l_asg_eoy_bonus_per;
1411 hr_utility.set_location('EOY Bonus Override at the I/V Level',105);
1412
1413 END IF;
1414
1415 CLOSE c_eoy_per_or;
1416
1417 --
1418 -- Call the function to derive EOY Bonus
1419 -- percentage from the org level only if it is null at the asg i/v level.
1420 --
1421 IF NVL(l_eoy_bonus_per,-99) = -99 THEN
1422
1423 l_ret_val := pqp_nl_pggm_functions.get_general_info
1424 (p_assignment_id => p_assignment_id
1425 ,p_business_group_id => p_business_group_id
1426 ,p_date_earned => p_date_earned
1427 ,p_code => 1
1428 ,p_value => l_eoy_bonus_per
1429 );
1430
1431 IF l_ret_val <> 0 THEN
1432 l_eoy_bonus_per := 0;
1433 END IF;
1434 hr_utility.set_location('EOY Bonus Calculated from the org',106);
1435
1436 END IF;
1437
1438 --
1439 -- Check if the final calculated value for EOY Bonus % is 0
1440 -- If it is zero then ignore the min EOY Bonus specified
1441 -- at the CAG ( Collective Agreement) level.
1442 --
1443 IF l_eoy_bonus_per = 0 THEN
1444 l_ignore_eoy_cag := 1;
1445 ELSE
1446 l_ignore_eoy_cag := 0;
1447 END IF;
1448
1449 hr_utility.set_location('EOY Bonus % used for calculation is : '||l_eoy_bonus_per,110);
1450
1451 --
1452 -- Calculate the EOY Bonus that needs to be included for
1453 -- PGGM Pension Salary calculations
1454 --
1455 l_eoy_bonus := (l_scale_salary_e
1456 +l_ft_rec_paymnt_e
1457 +l_pt_rec_paymnt_e
1458 )
1459 * l_eoy_bonus_per/100
1460 * l_max_periods;
1461
1462 hr_utility.set_location('EOY Bonus amount calculated : '||l_eoy_bonus,120);
1463
1464 --
1465 -- Holiday Allowance Calculation
1466 -- This section will calculate the holiday allowance
1467 -- based on the holiday allowance percentage specified
1468 -- at the org level. These will be derived from the
1469 -- following three balances.
1470 --
1471 -- PGGM Scale Salary For Holiday Allowance
1472 -- PGGM Full Time Recurring Payments For Holiday Allowance
1473 -- PGGM Part Time Recurring Payments For Holiday Allowance
1474 --
1475
1476 --
1477 -- Check to see if the Holiday Allowance % has been overridden
1478 -- at the assignment input value level. If it has been overridden
1479 -- and is not null, Use this value and do not derive from the org.
1480 -- Otherwise derive it from the org.
1481 -- It is imp to note that if the value is 0, the do not consider
1482 -- the min at the cag level.
1483 --
1484 OPEN c_ha_per_or(p_assignment_id
1485 ,l_effective_date);
1486 FETCH c_ha_per_or INTO l_asg_ha_per;
1487
1488 IF c_ha_per_or%FOUND THEN
1489
1490 l_holiday_allow_per := l_asg_ha_per;
1491 hr_utility.set_location('Holiday Allowance overridden at the iv level ',125);
1492
1493 END IF;
1494
1495 CLOSE c_ha_per_or;
1496 --
1497 -- Call the function to derive Holiday allowance
1498 -- percentage from the org level only if it is null at the asg i/v level.
1499 --
1500 IF NVL(l_holiday_allow_per,-99) = -99 THEN
1501
1502 l_ret_val := pqp_nl_pggm_functions.get_general_info
1503 (p_assignment_id => p_assignment_id
1504 ,p_business_group_id => p_business_group_id
1505 ,p_date_earned => p_date_earned
1506 ,p_code => 0
1507 ,p_value => l_holiday_allow_per
1508 );
1509
1510 IF l_ret_val <> 0 THEN
1511 l_holiday_allow_per := 0;
1512 END IF;
1513 hr_utility.set_location('Holiday Allowance Calculated from the org',125);
1514
1515 END IF;
1516
1517 hr_utility.set_location('Holiday allow % used for calculation is : '
1518 ||l_holiday_allow_per,130);
1519
1520 --
1521 -- Check if the final calculated value for HA % is 0
1522 -- If it is zero then ignore the min HA specified
1523 -- at the CAG (Collective Agreement) level.
1524 --
1525 IF l_holiday_allow_per = 0 THEN
1526 l_ignore_ha_cag := 1;
1527 ELSE
1528 l_ignore_ha_cag := 0;
1529 END IF;
1530
1531 l_holiday_allowance := (l_scale_salary_h
1532 +l_ft_rec_paymnt_h
1533 +l_pt_rec_paymnt_h
1534 )
1535 * l_holiday_allow_per/100
1536 * l_max_periods;
1537
1538 hr_utility.set_location('Calculated holiday allowance : '||l_holiday_allowance,140);
1539
1540 -- Find the minimum values for EOY Bonus and Holiday
1541 -- allowance that may have been defined for this
1542 -- assignment. The value of holiday allowance and EOY
1543 -- bonus used in pension salary calculation should
1544 -- not be lesser than this defined minimum
1545
1546 -- First get the CAG Name
1547 OPEN c_cag_name (c_asg_id => p_assignment_id
1548 ,c_eff_date => l_effective_date) ;
1549
1550 FETCH c_cag_name INTO l_cag_name;
1551
1552 IF c_cag_name%FOUND THEN
1553
1554 -- We found a CAG at the asg level . Now get the Min End Of
1555 -- Year Bonus for this CAG from the UDT.
1556 hr_utility.set_location('CAG attached to the asg : '||l_cag_name,150);
1557 BEGIN
1558 l_min_eoy_bonus_char := hruserdt.get_table_value
1559 (
1560 p_bus_group_id => p_business_group_id
1561 ,p_table_name => 'PQP_NL_MIN_END_OF_YEAR_BONUS'
1562 ,p_col_name => 'PGGM Minimum End Of Year Bonus'
1563 ,p_row_value => l_cag_name
1564 ,p_effective_date => l_effective_date
1565 );
1566
1567 --
1568 -- Calculate the min EOY bonus only if the override percentage is not 0
1569 --
1570 IF NVL(l_ignore_eoy_cag,0) = 0 THEN
1571 l_min_eoy_bonus := fnd_number.canonical_to_number(NVL(l_min_eoy_bonus_char,'0'));
1572 ELSIF NVL(l_ignore_eoy_cag,0) = 1 THEN
1573 l_min_eoy_bonus := 0;
1574 END IF;
1575
1576 EXCEPTION
1577 WHEN NO_DATA_FOUND THEN
1578 hr_utility.set_location('Exception occured :NO_DATA_FOUND ',160);
1579 l_min_eoy_bonus := 0;
1580 END;
1581
1582 -- We found a CAG at the asg level . Now get the Min holiday
1583 -- allowance for this CAG from the UDT.
1584 BEGIN
1585 l_min_age_holiday_allow:= hruserdt.get_table_value
1586 (
1587 p_bus_group_id => p_business_group_id
1588 ,p_table_name => 'PQP_NL_MIN_HOLIDAY_ALLOWANCE'
1589 ,p_col_name => 'PGGM Min Age for Holiday Allowance'
1590 ,p_row_value => l_cag_name
1591 ,p_effective_date => l_effective_date
1592 );
1593 --Get the age of the person
1594 hr_utility.set_location('l_begin_of_year_date'||l_begin_of_year_date,161);
1595 l_person_age := Get_age(p_assignment_id,l_effective_date,l_begin_of_year_date);
1596 hr_utility.set_location('l_person_age'||l_person_age,162);
1597 hr_utility.set_location('l_min_age_holiday_allow'||l_min_age_holiday_allow,163);
1598
1599 --Comapre it with min age defined at CAG level
1600 IF (l_person_age < to_number(l_min_age_holiday_allow) ) THEN
1601 --Person is not eligible for Min holiday allowance
1602 l_min_holiday_allow :=0;
1603 p_err_message2 :=p_err_message2|| 'Min. holiday allowance is set to 0 as'
1604 ||'person age is less than min age defined at collective agreement ';
1605 l_ret_val := 2;
1606 ELSE
1607 l_min_holiday_char := hruserdt.get_table_value
1608 (
1609 p_bus_group_id => p_business_group_id
1610 ,p_table_name => 'PQP_NL_MIN_HOLIDAY_ALLOWANCE'
1611 ,p_col_name => 'PGGM Minimum Holiday Allowance'
1612 ,p_row_value => l_cag_name
1613 ,p_effective_date => l_effective_date
1614 );
1615 hr_utility.set_location('l_min_holiday_char'||l_min_holiday_char,165);
1616 --
1617 -- Calculate the min HA only if the override percentage is not 0
1618 --
1619 IF NVL(l_ignore_ha_cag,0) = 0 THEN
1620 l_min_holiday_allow := fnd_number.canonical_to_number(NVL(l_min_holiday_char,'0'));
1621 ELSIF NVL(l_ignore_ha_cag,0) = 1 THEN
1622 l_min_holiday_allow := 0;
1623 END IF;
1624 END IF; -- End of person age check
1625
1626 EXCEPTION
1627 WHEN NO_DATA_FOUND THEN
1628 hr_utility.set_location('Exception occured :NO_DATA_FOUND ',170);
1629 l_min_holiday_allow := 0;
1630 END;
1631
1632 --no collective agreement defined for this assignment
1633 ELSE
1634 -- set Min EOY bonus and Min Holiday allowance to 0 .
1635 hr_utility.set_location('No CAG attached',160);
1636 l_min_eoy_bonus := 0;
1637 l_min_holiday_allow := 0;
1638 END IF;
1639
1640 CLOSE c_cag_name;
1641
1642 hr_utility.set_location('Min. EOY bonus : '||l_min_eoy_bonus,170);
1643 hr_utility.set_location('Min. Holiday allowance : '||l_min_holiday_allow,180);
1644
1645 --now compare the calculated eoy bonus and the min. eoy bonus
1646 IF l_eoy_bonus < l_min_eoy_bonus THEN
1647 p_err_message1 :=p_err_message1|| 'Min. end of year bonus for the collective agreement'
1648 ||' was used for Pension Salary calculation ';
1649 l_ret_val := 2;
1650 END IF;
1651
1652 l_eoy_bonus := GREATEST(l_eoy_bonus,nvl(l_min_eoy_bonus,0));
1653
1654 hr_utility.set_location('Final EOY Bonus value : '||l_eoy_bonus,190);
1655
1656 --now compare the calculated holiday allowance and the min. holiday allowance
1657 IF l_holiday_allowance < l_min_holiday_allow THEN
1658 p_err_message2 :=p_err_message2|| 'Min. holiday allowance for the collective agreement'
1659 ||' was used for Pension Salary calculation ';
1660 l_ret_val := 2;
1661 END IF;
1662
1663 l_holiday_allowance := GREATEST(l_holiday_allowance,nvl(l_min_holiday_allow,0));
1664
1665 hr_utility.set_location('Final Holiday Allowance value : '||l_holiday_allowance,200);
1666
1667 p_salary_balance_value := (l_scale_salary
1668 +l_ft_rec_paymnt
1669 +l_pt_rec_paymnt
1670 ) * l_max_periods
1671 +l_holiday_allowance
1672 +l_eoy_bonus;
1673
1674 p_salary_balance_value := CEIL(p_salary_balance_value);
1675
1676 hr_utility.set_location('Leaving : '||g_pkg_name||l_proc_name,210);
1677 --hr_utility.trace_off;
1678 RETURN l_ret_val;
1679
1680 EXCEPTION
1681 WHEN OTHERS THEN
1682 p_salary_balance_value := 0;
1683 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,220);
1684 p_err_message := 'Error occured while deriving the PGGM Pension Salary'
1685 ||' value : '||SQLERRM;
1686 RETURN 1;
1687
1688 END GET_PENSION_SALARY;
1689
1690 -- ----------------------------------------------------------------------------
1691 -- |----------------------<GET_PART_TIME_PERCENTAGE >--------------------------|
1692 -- ----------------------------------------------------------------------------
1693 --
1694 FUNCTION GET_PART_TIME_PERCENTAGE
1695 (p_assignment_id IN NUMBER
1696 ,p_payroll_action_id IN NUMBER
1697 ,p_date_earned IN DATE
1698 ,p_business_group_id IN NUMBER
1699 ,p_period_start_date IN DATE
1700 ,p_period_end_date IN DATE
1701 ,p_override_value IN NUMBER
1702 ,p_parental_leave IN VARCHAR2
1703 ,p_extra_hours IN NUMBER
1704 ,p_hours_worked OUT NOCOPY NUMBER
1705 ,p_total_hours OUT NOCOPY NUMBER
1706 ,p_part_time_percentage OUT NOCOPY NUMBER
1707 ,p_err_message OUT NOCOPY VARCHAR2
1708 )
1709 RETURN NUMBER IS
1710
1711 --
1712 -- Cursor to fetch the earliest start date of the assignment
1713 -- for this period
1714 --
1715 CURSOR c_get_st_date IS
1716 SELECT min(effective_start_date)
1717 FROM per_all_assignments_f
1718 WHERE assignment_id = p_assignment_id
1719 AND effective_end_date >= p_period_start_date;
1720 --
1721 --Cursor to fetch the part time percentage from the
1722 --assignment standard conditions for a given effective date
1723 --
1724 CURSOR c_get_ptp(c_effective_date IN DATE) IS
1725 SELECT fnd_number.canonical_to_number(NVL(target.SEGMENT29,'0')) pt_perc
1726 FROM per_assignments_f asg
1727 ,hr_soft_coding_keyflex target
1728 WHERE asg.assignment_id = p_assignment_id
1729 AND target.soft_coding_keyflex_id = asg.soft_coding_keyflex_id
1730 AND c_effective_date between asg.effective_start_date
1731 AND asg.effective_end_date
1732 AND target.enabled_flag = 'Y';
1733
1734 --
1735 -- cursor to fetch the date tracked assignment rows
1736 -- for all changes in the pay period
1737 -- the calendar day average value of all these changes
1738 -- is taken as the average part time percentage of this period
1739 --
1740 CURSOR c_get_asg_rows IS
1741 SELECT fnd_number.canonical_to_number(NVL(target.segment28,'0')) hours_worked
1742 ,nvl(asg.normal_hours,0) total_hours
1743 ,nvl(asg.frequency,'W') freq
1744 ,asg.effective_start_date start_date
1745 ,asg.effective_end_date end_date
1746 FROM per_assignments_f asg
1747 ,per_assignment_status_types ast
1748 ,hr_soft_coding_keyflex target
1749 WHERE asg.assignment_id = p_assignment_id
1750 AND asg.assignment_status_type_id = ast.assignment_status_type_id
1751 AND ast.per_system_status = 'ACTIVE_ASSIGN'
1752 AND target.soft_coding_keyflex_id = asg.soft_coding_keyflex_id
1753 AND asg.effective_start_date <= p_period_end_date
1754 AND asg.effective_end_date >= p_period_start_date;
1755
1756
1757 --
1758 --Cursor to fetch period type of payroll attached to assignment
1759 --
1760 CURSOR c_get_period_type(c_payroll_action_id IN NUMBER)
1761 IS
1762 SELECT TPERIOD.period_type
1763 FROM pay_payroll_actions PACTION
1764 ,per_time_periods TPERIOD
1765 WHERE PACTION.payroll_action_id = c_payroll_action_id
1766 AND TPERIOD.payroll_id = PACTION.payroll_id
1767 AND (PACTION.date_earned between TPERIOD.start_date
1768 and TPERIOD.end_date);
1769
1770 c_asg_row c_get_asg_rows%ROWTYPE;
1771
1772 l_proc_name VARCHAR2(30) := 'GET_PART_TIME_PERCENTAGE';
1773 l_eff_date DATE;
1774 l_ptp NUMBER := 100;
1775 l_emp_kind NUMBER := 1;
1776 l_start_date DATE;
1777 l_end_date DATE;
1778 l_days NUMBER;
1779 l_pay_days NUMBER;
1780 l_tot_days NUMBER := 0;
1781 hours_worked NUMBER := 0;
1782 total_hours NUMBER := 0;
1783 l_hours_worked NUMBER;
1784 l_total_hours NUMBER;
1785 l_ret_value NUMBER := 0;
1786 l_num_periods NUMBER :=12;
1787 l_period_type VARCHAR2(150):='Calendar Month';
1788 l_num_of_days_in_period NUMBER:=30;
1789
1790 BEGIN
1791 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
1792
1793 OPEN c_get_period_type(p_payroll_action_id);
1794 FETCH c_get_period_type INTO l_period_type;
1795 CLOSE c_get_period_type;
1796 IF l_period_type='Calendar Month' THEN
1797 l_num_of_days_in_period:= 30;
1798 ELSE IF l_period_type = 'Lunar Month' THEN
1799 l_num_of_days_in_period:=28;
1800 ELSE IF l_period_type = 'Week' THEN
1801 l_num_of_days_in_period:=7;
1802 ELSE IF l_period_type = 'Quarter' THEN
1803 l_num_of_days_in_period:=90;
1804 END IF;
1805 END IF;
1806 END IF;
1807 END IF;
1808
1809 p_err_message := '';
1810 --
1811 -- check if the person is a full timer or part timer
1812 -- if the person is a part timer, then the final part time
1813 -- percentage cannot exceed 100% and it cannot exceed 125%
1814 -- for a full timer
1815 -- If the part time percentage derived from the standard
1816 -- conditions is < 100 then the person is a part time employee
1817 -- if the value is equal to or exceeds 100 then this is a full
1818 -- timer
1819 --
1820
1821 -- fetch the part time percentage on the period start date
1822 -- first fetch the date on which this part time percentage needs
1823 -- to be derived on
1824
1825 OPEN c_get_st_date;
1826 FETCH c_get_st_date INTO l_eff_date;
1827 CLOSE c_get_st_date;
1828
1829 hr_utility.set_location('Start date of asg for this period : '||l_eff_date,20);
1830
1831 -- the date on which ptp needs to be derived is the greater of the asg start date
1832 -- and the period start date
1833
1834 l_eff_date := GREATEST(l_eff_date,p_period_start_date);
1835
1836 hr_utility.set_location('date on which check is performed : '||l_eff_date,30);
1837
1838 --Get number of payroll periods in a year
1839 OPEN c_get_num_periods_per_year(p_payroll_action_id);
1840 FETCH c_get_num_periods_per_year INTO l_num_periods;
1841 CLOSE c_get_num_periods_per_year;
1842
1843
1844 --now derive the ptp from standard conditions on this eff date to check
1845 -- for part/full timers
1846
1847 OPEN c_get_ptp(l_eff_date);
1848 FETCH c_get_ptp INTO l_ptp;
1849 CLOSE c_get_ptp;
1850
1851 hr_utility.set_location('PTP on the start date : '||l_ptp,40);
1852
1853 IF l_ptp < 100 THEN
1854 -- the employee is a part time employee
1855 l_emp_kind := 0;
1856 ELSE
1857 -- the employee is full time
1858 l_emp_kind := 1;
1859 END IF;
1860
1861 hr_utility.set_location('Employee Kind : '||l_emp_kind,50);
1862
1863 --calculate the number of days in this pay period
1864 l_pay_days := TRUNC(p_period_end_date) - TRUNC(p_period_start_date) + 1;
1865
1866 --now loop through the asg changes to find the total average hours worked
1867 FOR c_asg_row IN c_get_asg_rows
1868 LOOP
1869 --if the start date is before period start,use period start
1870 IF c_asg_row.start_date < p_period_start_date THEN
1871 l_start_date := p_period_start_date;
1872 ELSE
1873 l_start_date := c_asg_row.start_date;
1874 END IF;
1875
1876 -- if end date is after period end,use period end
1877 IF c_asg_row.end_date > p_period_end_date THEN
1878 l_end_date := p_period_end_date;
1879 ELSE
1880 l_end_date := c_asg_row.end_date;
1881 END IF;
1882
1883 hr_utility.set_location('Start Date : '||l_start_date,60);
1884 hr_utility.set_location('End Date : '||l_end_date,70);
1885 hr_utility.set_location('Hours worked : '||c_asg_row.hours_worked,80);
1886 hr_utility.set_location('Total Hours : '||c_asg_row.total_hours,90);
1887 hr_utility.set_location('Frequency : '||c_asg_row.freq,100);
1888
1889 --calculate the hours per week based on the frequency
1890 IF c_asg_row.freq = 'D' THEN
1891 l_hours_worked := c_asg_row.hours_worked * 5;
1892 l_total_hours := c_asg_row.total_hours * 5;
1893 ELSIF c_asg_row.freq = 'M' THEN
1894 l_hours_worked := c_asg_row.hours_worked * l_num_periods/52;
1895 l_total_hours := c_asg_row.total_hours * l_num_periods/52;
1896 ELSIF c_asg_row.freq = 'Y' THEN
1897 l_hours_worked := c_asg_row.hours_worked/52;
1898 l_total_hours := c_asg_row.total_hours/52;
1899 ELSE
1900 l_hours_worked := c_asg_row.hours_worked;
1901 l_total_hours := c_asg_row.total_hours;
1902 END IF;
1903
1904 --calculate the days for this asg row
1905 l_days := TRUNC(l_end_date) - TRUNC(l_start_date) + 1;
1906 l_tot_days := l_tot_days + l_days;
1907
1908 --the total days should always be l_num_of_days_in_period,
1909 --adjust the last l_days so that it adds up to l_num_of_days_in_period
1910 IF l_tot_days = l_pay_days THEN
1911 --the number of days is equal to the number of days in the
1912 --pay period,but this has to always be l_num_of_days_in_period
1913 l_days := l_days + (l_num_of_days_in_period - l_tot_days);
1914 END IF;
1915
1916 hr_utility.set_location('l_days : '||l_days,110);
1917
1918 hours_worked := hours_worked +
1919 l_hours_worked * l_days/l_num_of_days_in_period;
1920
1921 total_hours := total_hours +
1922 l_total_hours * l_days/l_num_of_days_in_period;
1923 END LOOP;
1924
1925 --hours worked and total hours for the month is the average calculated
1926 -- above * 52/12
1927 hours_worked := hours_worked * 52/l_num_periods;
1928 total_hours := total_hours * 52/l_num_periods;
1929
1930 hr_utility.set_location('Avg. Hours worked : '||hours_worked,120);
1931 hr_utility.set_location('Avg. Total Hours : '||total_hours,130);
1932
1933 --
1934 -- check if an override has been entered, if so then the part time
1935 -- percentage is the same as the value entered in the override
1936 -- however for the case where the person is on parental leave,
1937 -- the override part time percentage needs to be added with
1938 -- the extra hours entered
1939 --
1940
1941 IF p_override_value <> -99 THEN
1942 --override has been entered
1943 l_ptp := p_override_value;
1944 hr_utility.set_location('Override exists : '||l_ptp,140);
1945 --check if the employee is also on parental leave
1946 IF p_parental_leave = 'Y' THEN
1947 --we also need to add any increase in ptp due to extra hours
1948 hr_utility.set_location('parental leave exists',150);
1949 IF total_hours > 0 THEN
1950 --only if the employee is part time,extra hours can be considered
1951 IF l_emp_kind = 0 THEN
1952 l_ptp := l_ptp + (nvl(p_extra_hours,0)/total_hours) * 100;
1953 END IF;
1954 END IF;
1955 END IF;
1956
1957 ELSE
1958 --no override exists
1959 hr_utility.set_location('No override exists',160);
1960 --final ptp value is calculated value + increase due to extra hours
1961 IF total_hours > 0 THEN
1962 --only if emp is part time, then consider extra hours
1963 IF l_emp_kind = 0 THEN
1964 l_ptp := ((hours_worked + nvl(p_extra_hours,0))/total_hours) * 100;
1965 ELSE
1966 l_ptp := (hours_worked/total_hours) * 100;
1967 END IF;
1968 ELSE
1969 l_ptp := 0;
1970 END IF;
1971 END IF;
1972
1973 l_ptp := nvl(l_ptp,0);
1974
1975 hr_utility.set_location('Calculated PTP : '||l_ptp,170);
1976 /*
1977 PGGM 2006 Legislative change
1978 No max limit for Part time percentage
1979 --
1980 -- Restrict the final value of PTP to 125
1981 --
1982 IF l_ptp > 125 THEN
1983 p_err_message := 'Part time percentage has been restricted to 125%';
1984 l_ret_value := 2;
1985 END IF;
1986
1987 l_ptp := LEAST(l_ptp,125);
1988 */
1989
1990 hr_utility.set_location('Final ptp value : '||l_ptp,180);
1991
1992 p_part_time_percentage := round(nvl(l_ptp,0),2);
1993 p_hours_worked := round(nvl(hours_worked,0),2);
1994 p_total_hours := round(nvl(total_hours,0),2);
1995
1996 hr_utility.set_location('Leaving : '||g_pkg_name||l_proc_name,190);
1997
1998 RETURN l_ret_value;
1999
2000 EXCEPTION
2001 WHEN OTHERS THEN
2002 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,200);
2003 p_part_time_percentage := 0;
2004 p_hours_worked := 0;
2005 p_total_hours := 0;
2006 p_err_message := 'Error occured while deriving part time percentage : '||SQLERRM;
2007 RETURN 1;
2008
2009 END GET_PART_TIME_PERCENTAGE;
2010
2011 -- ----------------------------------------------------------------------------
2012 -- |----------------------<GET_INCI_WKR_CODE >--------------------------------|
2013 -- ----------------------------------------------------------------------------
2014 --
2015 FUNCTION GET_INCI_WKR_CODE
2016 (p_assignment_id IN NUMBER
2017 ,p_business_group_id IN NUMBER
2018 ,p_date_earned IN DATE
2019 ,p_result_value OUT NOCOPY VARCHAR2
2020 ,p_err_message OUT NOCOPY VARCHAR2
2021 )
2022 RETURN NUMBER IS
2023 CURSOR csr_get_inci_wkr_code(c_assignment_id NUMBER,c_date_earned DATE) IS
2024 SELECT scl.SEGMENT1
2025 FROM per_all_assignments_f asg
2026 ,hr_soft_coding_keyflex scl
2027 WHERE asg.assignment_id = c_assignment_id
2028 AND c_date_earned BETWEEN asg.effective_start_date
2029 AND asg.effective_end_date
2030 AND asg.soft_coding_keyflex_id = scl.soft_coding_keyflex_id;
2031
2032 l_proc_name VARCHAR2(30) := 'GET_INCI_WKR_CODE';
2033 l_inci_code VARCHAR2(1):='N';
2034 l_ret_value NUMBER:=0;
2035 BEGIN
2036 hr_utility.set_location('Entering : '||g_pkg_name||l_proc_name,10);
2037
2038 OPEN csr_get_inci_wkr_code(p_assignment_id,p_date_earned);
2039 FETCH csr_get_inci_wkr_code INTO l_inci_code;
2040
2041 IF csr_get_inci_wkr_code%FOUND THEN
2042 p_result_value:=l_inci_code;
2043 ELSE
2044 p_result_value:='N';
2045 END IF;
2046 CLOSE csr_get_inci_wkr_code;
2047
2048 hr_utility.set_location('Leaving : '||g_pkg_name||l_proc_name,190);
2049 RETURN l_ret_value;
2050 EXCEPTION
2051 WHEN OTHERS THEN
2052 hr_utility.set_location('Exception occured in : '||g_pkg_name||l_proc_name,200);
2053 p_err_message := 'Error occured while deriving incidental worker code : '||SQLERRM;
2054 RETURN 1;
2055 END GET_INCI_WKR_CODE;
2056
2057 END PQP_NL_PGGM_FUNCTIONS;