1 package body SSP_SSP_PKG as
2 /* $Header: spsspapi.pkb 120.22 2011/09/23 05:57:05 pbalu ship $
3 +==============================================================================+
4 | Copyright (c) 1994 Oracle Corporation |
5 | Redwood Shores, California, USA |
6 | All rights reserved. |
7 +==============================================================================+
8 --
9 Name
10 Statutory Sick Pay Business Process
11 --
12 Purpose
13 To perform calculation of entitlement and payment for SSP purposes.
14 --
15 History
16 11 Sep 95 N Simpson Created
17 19 Sep 95 N Simpson Removed LEL constant and replaced it
18 with ssp_SMP_pkg.c_LEL. Added procedure
19 check_sickness_date_change.
20 27 Oct 95 N Simpson Renamed all ssp objects to begin with
21 ssp_ instead of hr_
22 31 Oct 95 N Simpson Added workaround for 10.6 to check
23 pay_legislation_rules for indication
24 of SSP installation. This fix should
25 be removed from the code after 10.7.
26 See ssp_is_installed function.
27 3 Nov 95 N Simpson Modified function linked_PIW_end_date.
28 The check on whether the cursor
29 returned a row or not was not valid
30 because MAX ensures a row is always
31 returned. Changed the test to look for
32 a value in the return variable.
33 15 Nov 95 N Simpson Removed hr_utility.trace from
34 linked_PIW_end_date because of pragma
35 added to header.
36 16 Nov 95 N Simpson Renamed parameter call to
37 get_entry_details
38 29 Nov 95 N Simpson Added error trapping to
39 get_SSP...element procedures.
40 29 Nov 95 N Simpson Added to_char to convert date pl/sql
41 variables prior to insert into entry
42 values in insert_element_entry calls.
43 29 Nov 95 N Simpson Changed value placed in qualifying days
44 entry value from qualifying days in the
45 calendar week to qualifying days in the
46 absence period.
47 5 Dec 95 N Simpson Removed test for length of absence from
48 cursor PIW because it was restricting
49 unnecessarily to absences longer than
50 the PIW threshhold. If an absence has
51 a linked_absence_id then it must be a
52 PIW anyway, even if it is too short to
53 be a PIW in its own right.
54 9 Feb 96 N Simpson When calculating amount of SSP, add
55 0.004 before rounding instead of 0.0049
56 so that decimal places after the third
57 one are ignored.
58 4 Apr 96 N Simpson Modified absence_is_a_PIW to take
59 account of contiguous absences AFTER
60 the one being checked as well as
61 those prior to it.
62 Modified linked_absence_id to cascade
63 a linked_absence_id to contiguous
64 absences which become part of a PIW
65 by virtue of the insertion of a new
66 absence which takes the total unbroken
67 absence period over the threshhold.
68 9 Apr 96 N Simpson New procedure update_linked_absence_IDs
69 24 Aug 96 C Barbieri Changed the select stmt in the
70 csr_missing_links cursor definition in
71 order to use index per_absence_attendan
72 ces_fk4.
73 13 Nov 96 C Barbieri Bug. 418895: changed the check about the
74 SSP entitlement. Now when an absence is
75 entered that is not in a PIW, we delete
76 all the old entries and stoppages.
77 21 Jan 97 C Barbieri Bg 441738: Changed this_week.date_earned
78 to pick up the absence start_date,
79 instead of the previous Sunday.
80 Change List
81 ===========
82 Version Date BugNo Author Comment
83 -------+----------+----------+----------+-------------------------------------
84 30.42 02-May-97 467870 Khabibul Changes in check_for_break_in_linked_PIW
85 csr_previous_absence. Removed NVL around
86 the indexed column and replaced it with
87 'OR'. The sql is then more efficient,
88 with no full table scan.
89 ***Same fix was applied to version 30.41
90 which was a backport of Prod14 (taken
91 from 30.12) ****
92 This is the latest version of package
93 for any latest Prod releases. ****
94 Also added new 'Change List' header to
95 comply with PKM standards.
96 30.43 09-jun-97 502108 RThirlby Forced SSP_rate_figure to be based
97 on the sickness_start_date instead
98 of the PIW_start_date.
99 30.44 18-jul-97 513292 RThirlby Altered qualifying_days_in_period to
100 return default BG qualifying pattern
101 if a person has a default as well as
102 personal pattern at any time during
103 their absence (linked or not).
104 30.45 12-Sep-97 550269 RThirlby Explicitly open csr_qualifying_pattern
105 to prevent invalid_cursor error.
106 30.46 29-Sep-97 504386 RThirlby Call qualifying_days_in_period for the
107 absence as a whole so that the pl/sql
108 table in hr_calendar_pkg is populated
109 once for the whole sickness absence.
110 30.47 03-Dec-97 589806 RThirlby Made allowance for open ended absence
111 in call to qualifying_days_in_period.
112 30.48 05-Dec-97 593097 RThirlby Forces end_date to be the next
113 Saturday, after the Sunday before
114 the sickness_start_date.
115 30.49 11-dec-97 555505 RThirlby Added <= rather than < so that one
116 day absences are accounted for.
117 30.50 24-mar-98 563202 RThirlby Performance fix on cursor PIW and
118 csr_qualifying_pattern.
119 30.51 04-Jun-98 668368 AMyers Change so that previous stoppages are
120 retrieved if the id is either the PIW
121 OR the absence id and actioned
122 30.52 19-Jun-98 563202 AParkes Re-wrote absence_is_a_PIW to avoid
123 calling unnecessary sql.
124 Changed csr_existing_entries to avoid
125 using dt views and stop calling
126 ssp_smp_support_pkg.value
127 Added history for 30.51
128 30.53 19-AUG-98 563202 A.Myers Loads of changes to improve efficiency,
129 /701750 such as using pl/sql tables, creating
130 calendar for the whole PIW, not just
131 for each absence. Also added standard
132 trace.
133 110.13 16-AUG-99 886707 MVilrokx The initialisation of l_stopage_found
134 parameter was not correct. Moved it
135 inside the loop so it is reset every
136 time. This assurs that a wating days
137 are still generated after a user
138 created stoppage.
139 115.9 08-NOV-99 1020757 MVilrokx Fixed two problems with date conversion,
140 one in the cursor csr_existing_entries
141 and twice when calling insert_element_entry
142 115.10 04-AUG-00 1320737 DFoster Amended the logic of the
143 check_disqualifying_period which was
144 causing the update of the MPP start
145 date to be calculated incorrectly where
146 a period of sickness went over the sixth
147 week prior to the EWC
148 115.11 14-AUG-00 1304683 DFoster Amended the check_average_earnings
149 procedure so that it calls the new
150 version of the procedure to calculate
151 average earnings so that Sicknesses
152 and Maternities can be dealt with
153 differently.
154 115.14 31-JUL-01 1754802 GButler Changed ssp_is_installed procedure.
155 Procedure was checking PAY_LEGISLATION_
156 RULES table for evidence that ssp was
157 installed. This check was made obsolete
158 in 10.7 and was causing incorrect results
159 to be returned when checking for SSP
160 installation
161 115.16 22-FEB-02 1310170 ABhaduri Added cursor csr_previous_reason to populate
162 the ssp_smp_support_pkg.reason_for_no_earnings
163 variable when the employee is rehired and the
164 absence is getting saved for the second time.
165 115.21 05-NOV-02 2620894 srjadhav Changed the code so that MPP start date is
166 the next day after first working day
167 of (EWC - sickness_trigger_weeks) week.
168 115.22 12-DEC-02 AMills nocopy addition.
169 115.23 27-JAN-03 GButler further nocopy change to check_average
170 _earnings to include 2nd dummy variable
171 to act as placeholder for OUT param from
172 ssp_ern_ins
173 115.24 03-FEB-03 ABlinko added further restriction to maternity_details
174 cursor. Only returns records with a leave_type
175 of MA or null
176 115.25 12-MAY-03 GButler Changes for SSP Legislative Requirements 2003.
177 Commented out stoppage code for Fixed Contract Too
178 Short stoppage and changed check_service procedure
179 accordingly. Also added new check_link_letter
180 procedure
181 115.26 13-JUN-03 GButler Bug 2984845 - changes to do_PIW_calculations to
182 fix issue where PIW lasted max time stoppage not
183 being raised correctly
184 115.27 21-JUL-03 ASENGAR BUG 2984577- Added exception evidence_not_available
185 to the procedure ENTITLED_TO_SSP to raise
186 exception when sickness end date is not mentioned.
187
188 115.28 07-AUG-03 SSEKHAR BUG 2984458- Added another column to csr_person
189 cursor(leaving_reason) to give a stoppage as
190 'Employee Died' when the employee has deceased.
191
192 115.29 08-AUG-03 SSEKHAR BUG 2984458- The check_sql utility was not run
193 last time when the file was arcsed in.
194 115.32 21-OCT-03 ASENGAR BUG 2984577- Added code to handle linked absences
195 when evidence is not present.
196 115.33 24-OCT-03 ABLINKO BUG 3208325- Removed hardcoded SATURDAY and
197 SUNDAY references
198 115.34 03-DEC-03 SSEKHAR BUG 2984458 - Added condition to check if the
199 Employee is deceased before raising the exception
200 piw_max_length_reached
201 115.35 02-MAR-04 ABLINKO BUG 3456918 - Added rtrim when deriving
202 l_saturday and l_sunday
203 115.36 22-MAR-04 3466672 ABLINKO Added procedure medical_control
204 115.37 08-JUL-04 3750125 ABLINKO Added g_absence_del to limit use of
205 medical_control during absence deletion
206 115.38 12-JUL-04 ABLINKO check_evidence now resets last_entitled_day to
207 stoppage start date - 1
208 115.39 21-JUL-04 3769536 ABLINKO Amended person_control to work with open-ended
209 absences
210 115.40 12-APR-06 5126163 KTHAMPAN Amended do_PIW_calculation to check for total_SSP_weeks
211 115.41 04-AUG-06 5444012 KTHAMPAN Amended do_PIW_calculation to reset days_remaining
212 115.42 23-AUG-06 5482199 KTHAMPAN Statutory Changes for 2007.
213 115.45 25-AUG-06 5482199 KTHAMPAN Amend function check_average_earnings to
214 update the effective_date of the earnings calculations
215 for employee over 65.
216 Also change function check_employee_too_old to
217 check for stoppage on the main absence.
218 115.46 31-AUG-06 5504380 KTHAMPAN Added overload function linked_piw_start_date
219 and linked_piw_end_date.
220 115.49 06-SEP-06 5510601 KTHAMPAN Amend linked_PIW_start_date/end_date functions.
221 Added overload function linked_PIW_start_date,
222 linked_PIW_end_date and absence_is_a_PIW.
223 5517272 KTHAMPAN Amend check_age to pass the least of PIW_end_date
224 and 1 0ctober 2006 to the stoppage end date.
225 115.51 08-SEP-06 5517272 KTHAMPAN Amend the check_age to use the absence end date
226 instead of 1 October 2006.
227 115.52 09-SEP-06 5517272 HWINSOR Changed nocopy declaration
228 115.53 19-SEP-06 5550795 KTHAMPAN Amend the check_age
229 115.54 12-OCT-06 5583730 NPERSHAD Modified the function absence_is_a_PIW with 4 parameters.
230 115.55 09-DEC-06 5706912 KTHAMPAN Amend procedure ins_ssp_temp_affected_rows_PIW,
231 update_linked_absence_ids and person_control
232 115.56 19-MAR-07 5932995 HWINSOR Arcs in KTHAMPAN changes. Employees starting
233 post 1-Oct-06 have correct PIW start dates.
234 115.57 23-DEC-07 6658285 PBALU Changed a For loop in qualifying_days_in_period to use
235 PL/sql table instead of cursor as the cursor is opened/closed
236 inside the for loop.
237 115.58 19-Sep-08 6860926 EMUNISEK Changed the less than zero condition on weeks_remaining to
238 account for the rounding error of decimal values
239 115.60 03-Feb-09 7688727 NPANNAMP When creating SSP correction element previously LSP was passed
240 now it is changed to Final Process date similar to SMP/SAP corrections
241 115.61 09-Apr-09 8356706 NPANNAMP variables l_saturday, l_sunday moved from package body level to
242 ENTITLED_TO_SSP function variables, to avoid issues of package state
243 not resetting when used in OA Pages.
244 115.62 23-Sep-11 12552547 PBALU Sickness absence should not be linked with absences taken in different period of service.
245 ===============================================================================
246 */
247 g_package constant varchar2 (31) := 'SSP_SSP_pkg.';
248 g_SSP_is_installed boolean;
249 g_SSP_legislation ssp_SSP_pkg.csr_SSP_element_details%rowtype;
250 g_SSP_correction ssp_SSP_pkg.csr_SSP_element_details%rowtype;
251 g_PIW_id number := null;
252 g_absence_del varchar2(1) := 'N';
253 PIW_start_date date;
254 PIW_end_date date;
255 all_pat_calendar_days number;
256 perf_start_date date;
257 perf_end_date date;
258 /* Bug Fix 8356706 Begin
259 l_saturday varchar2(100) := rtrim(to_char(to_date('06/01/2001','DD/MM/YYYY'),'DAY'));
260 l_sunday varchar2(100) := rtrim(to_char(to_date('07/01/2001','DD/MM/YYYY'),'DAY'));
261 -- These variables moved inside of ENTITLED_TO_SSP function
262 Bug Fix 8356706 End */
263 --
264 attempt_to_add_to_end_of_time exception;
265 pragma exception_init (attempt_to_add_to_end_of_time,-01841);
266 --
267 -- Bug 2984458 Column leaving_reason has been included in this cursor
268 cursor csr_person (
269 --
270 -- Personal details of absentee, including their current period of
271 -- service, their age etc.
272 --
273 p_date_start in date,
274 p_person_id in number) is
275 --
276 select person.date_of_birth,
277 person.date_of_death,
278 person.person_id,
279 person.sex,
280 person.full_name,
281 service.date_start,
282 service.prior_employment_SSP_weeks,
283 service.prior_employment_SSP_paid_to,
284 nvl (service.projected_termination_date,
285 hr_general.end_of_time) PROJECTED_TERMINATION_DATE,
286 nvl (service.actual_termination_date,
287 hr_general.end_of_time) ACTUAL_TERMINATION_DATE,
288 nvl (service.last_standard_process_date,
289 hr_general.end_of_time) LAST_STANDARD_PROCESS_DATE,
290 /* 7688727 begin */
291 nvl (service.final_process_date,
292 hr_general.end_of_time) FINAL_PROCESS_DATE,
293 /* 7688727 End */
294 service.leaving_reason
295 from per_all_people_f PERSON,
296 per_periods_of_service SERVICE
297 where person.person_id = p_person_id
298 and service.person_id = person.person_id
299 and p_date_start between service.date_start
300 and nvl (service.actual_termination_date,
301 hr_general.end_of_time);
302 --
303 absentee csr_person%rowtype;
304 --
305 cursor csr_absence_details (p_absence_attendance_id in number) is
306 --
307 -- Get the details of an absence, given its ID.
308 --
309 select *
310 from per_absence_attendances
311 where absence_attendance_id = p_absence_attendance_id;
312 --
313 g_absence per_absence_attendances%rowtype;
314 --
315 cursor PIW is
316 --
317 -- Get all the PIWs which link to this one
318 --
319 -- 563202 nvl removed from the where clause as was implicitly causing the
320 -- index to be removed.
321 select sickness_start_date,
322 nvl(sickness_end_date,hr_general.end_of_time) sickness_end_date,
323 business_group_id,
324 absence_attendance_id,
325 pregnancy_related_illness
326 from per_absence_attendances
327 where (g_PIW_id = absence_attendance_id and linked_absence_id is null)
328 or g_PIW_ID = linked_absence_id
329 order by sickness_start_date;
330 --
331 type number_table is table of number index by binary_integer;
332 type date_table is table of date index by binary_integer;
333 type varchar_table is table of varchar2 (255) index by binary_integer;
334 --
335 type SSP_info is record (
336 --
337 element_entry_id number_table,
338 effective_start_date date_table,
339 effective_end_date date_table,
340 element_link_id number_table,
341 assignment_id number_table,
342 date_from date_table,
343 date_to date_table,
344 amount number_table,
345 rate number_table,
346 qualifying_days number_table,
347 SSP_days_due number_table,
348 withheld_days number_table,
349 SSP_weeks number_table,
350 dealt_with varchar_table);
351 --
352 -- A store for all the SSP entries that may be granted to the absentee.
353 --
354 new_entry SSP_info;
355 empty_record SSP_info; -- Used to initialise SSP_info records
356 --------------------------------------------------------------------------------
357 procedure get_absence_details (p_absence_attendance_id in number) is
358 --
359 -- Get the details of the absence from the absence id passed in.
360 --
361 l_proc varchar2 (72) := g_package||'get_absence_details';
362 --
363 procedure check_parameters is
364 --
365 begin
366 --
367 hr_utility.trace (l_proc||' p_absence_attendance_id = ' ||
368 to_char (p_absence_attendance_id));
369 --
370 hr_api.mandatory_arg_error (
371 p_api_name => l_proc,
372 p_argument => 'absence_attendance_id',
373 p_argument_value=> p_absence_attendance_id);
374 --
375 end check_parameters;
376 --
377 begin
378 --
379 hr_utility.set_location('Entering:'||l_proc,1);
380 --
381 check_parameters;
382 --
383 open csr_absence_details (p_absence_attendance_id);
384 fetch csr_absence_details into g_absence;
385 --
386 if csr_absence_details%notfound
387 then
388 --
389 -- The cursor unexpectedly returned no rows.
390 --
391 close csr_absence_details;
392 fnd_message.set_name ('PAY', 'HR_6153_ALL_PROCEDURE_FAIL');
393 fnd_message.set_token ('PROCEDURE','ssp_ssp_pkg.get_absence_details');
394 fnd_message.set_token ('STEP','1');
395 fnd_message.raise_error;
396 else
397 close csr_absence_details;
398 end if;
399 --
400 hr_utility.set_location('Leaving :'||l_proc,100);
401 --
402 end get_absence_details;
403 --------------------------------------------------------------------------------
404 function Standard_week_fraction (
405 --
406 -- Returns the legislative standard fraction to be used for a specified number
407 -- of qualifying days in a week.
408 --
409 p_qualifying_days in integer)
410 --
411 return number is
412 --
413 standard_fraction number;
414 l_proc varchar2 (72) := g_package||'Standard_week_fraction';
415 --
416 procedure check_parameters is
417 --
418 all_parameters_valid constant boolean := (p_qualifying_days is not null
419 and p_qualifying_days in (1,2,3,4,5,6,7));
420 --
421 begin
422 --
423 hr_utility.trace (l_proc||' p_qualifying_days = ' ||
424 to_char (p_qualifying_days));
425 --
426 hr_general.assert_condition (all_parameters_valid);
427 --
428 end check_parameters;
429 --
430 begin
431 --
432 hr_utility.set_location('Entering:'||l_proc,1);
433 --
434 check_parameters;
435 --
436 if p_qualifying_days = 1 then standard_fraction := 1;
437 elsif p_qualifying_days = 2 then standard_fraction := 0.5;
438 elsif p_qualifying_days = 3 then standard_fraction := 0.334;
439 elsif p_qualifying_days = 4 then standard_fraction := 0.25;
440 elsif p_qualifying_days = 5 then standard_fraction := 0.2;
441 elsif p_qualifying_days = 6 then standard_fraction := 0.167;
442 elsif p_qualifying_days = 7 then standard_fraction := 0.143;
443 end if;
444 --
445 hr_utility.trace (l_proc||' standard_fraction = '||to_char(standard_fraction));
446 hr_utility.set_location('Leaving :'||l_proc,100);
447 --
448 return standard_fraction;
449 --
450 end standard_week_fraction;
451 --------------------------------------------------------------------------------
452 procedure get_SSP_element (p_effective_date in date) is
453 --
454 -- Get the SSP element legislative parameters
455 --
456 begin
457 --
458 if g_SSP_legislation.element_type_id is null or
459 p_effective_date not between g_SSP_legislation.effective_start_date
460 and g_SSP_legislation.effective_end_date
461 then
462 --
463 -- If we have not already done so, do the following:
464 --
465 open ssp_SSP_pkg.csr_SSP_element_details (p_effective_date);
466 fetch ssp_SSP_pkg.csr_SSP_element_details into g_SSP_legislation;
467 close ssp_SSP_pkg.csr_SSP_element_details;
468 end if;
469 --
470 /* Commented out to comply with pragma
471 -- Check element returned expected values (this is belt and braces checking
472 -- because if the check fails then it was seed data which has been incorrectly
473 -- set up. However, failing here may prevent more inexplicable errors
474 -- elsewhere).
475 --
476 if g_SSP_legislation.element_type_id is null
477 then
478 fnd_message.set_name ('SSP', 'SSP_35077_NO_SSP_ELEMENT');
479 fnd_message.set_token ('EFFECTIVE_DATE',p_effective_date);
480 fnd_message.raise_error;
481 else
482 --
483 -- The element type exists
484 --
485 if (g_SSP_legislation.SSP_DAYS_DUE_ID is null
486 or g_SSP_legislation.AMOUNT_ID is null
487 or g_SSP_legislation.FROM_ID is null
488 or g_SSP_legislation.TO_ID is null
489 or g_SSP_legislation.RATE_ID is null
490 or g_SSP_legislation.WITHHELD_DAYS_ID is null
491 or g_SSP_legislation.SSP_WEEKS_ID is null
492 or g_SSP_legislation.QUALIFYING_DAYS_ID is null)
493 then
494 --
495 -- One of the input values is missing.
496 --
497 fnd_message.set_name ('SSP','SSP_36071_INCORRECT_INPUT_VALS');
498 fnd_message.set_token ('ELEMENT_NAME',c_SSP_element_name);
499 fnd_message.raise_error;
500 end if;
501 --
502 if (g_SSP_legislation.MAXIMUM_SSP_PERIOD is null
503 or g_SSP_legislation.MAXIMUM_AGE is null
504 or g_SSP_legislation.LINKING_PERIOD_DAYS is null
505 or g_SSP_legislation.WAITING_DAYS is null
506 or g_SSP_legislation.PIW_THRESHHOLD is null
507 or g_SSP_legislation.MAXIMUM_LINKED_PIW_YEARS is null
508 or g_SSP_legislation.PERCENTAGE_THRESHHOLD is null)
509 then
510 --
511 -- One of the DDF segments has not been entered.
512 --
513 fnd_message.set_name ('SSP','SSP_36070_MISSING_DDF_SEGMENT');
514 fnd_message.set_token ('ELEMENT_NAME',c_SSP_element_name);
515 fnd_message.raise_error;
516 end if;
517 end if;
518 --
519 */
520 end get_SSP_element;
521 --------------------------------------------------------------------------------
522 procedure get_SSP_correction_element (p_effective_date in date) is
523 --
524 -- Get the SSP element legislative parameters
525 --
526 l_proc varchar2 (72) := g_package||'get_SSP_correction_element';
527 --
528 procedure check_parameters is
529 --
530 begin
531 --
532 hr_utility.trace (l_proc||' p_effective_date = ' ||
533 to_char (p_effective_date));
534 --
535 hr_api.mandatory_arg_error (
536 p_api_name => l_proc,
537 p_argument => 'effective_date',
538 p_argument_value=> p_effective_date);
539 --
540 end check_parameters;
541 --
542 begin
543 --
544 hr_utility.set_location('Entering:'||l_proc,1);
545 --
546 check_parameters;
547 --
548 hr_utility.set_location(l_proc,2);
549 if g_SSP_correction.element_type_id is null or
550 p_effective_date not between g_SSP_correction.effective_start_date
551 and g_SSP_correction.effective_end_date
552 then
553 --
554 -- If we have not already done so, do the following:
555 --
556 hr_utility.set_location(l_proc,3);
557 open ssp_SSP_pkg.csr_SSP_element_details (p_effective_date,
558 c_SSP_correction_element_name);
559 fetch ssp_SSP_pkg.csr_SSP_element_details into g_SSP_correction;
560 close ssp_SSP_pkg.csr_SSP_element_details;
561 end if;
562 hr_utility.trace(l_proc||' g_SSP_correction.element_type_id :'||g_SSP_correction.element_type_id);
563 hr_utility.trace(l_proc||' g_SSP_correction.effective_start_date :'||g_SSP_correction.effective_start_date);
564 hr_utility.trace(l_proc||' g_SSP_correction.effective_end_date :'||g_SSP_correction.effective_end_date);
565 hr_utility.trace(l_proc||' g_SSP_correction.MAXIMUM_SSP_PERIOD :'||g_SSP_correction.MAXIMUM_SSP_PERIOD);
566 hr_utility.trace(l_proc||' g_SSP_correction.MAXIMUM_AGE :'||g_SSP_correction.MAXIMUM_AGE);
567 hr_utility.trace(l_proc||' g_SSP_correction.LINKING_PERIOD_DAYS :'||g_SSP_correction.LINKING_PERIOD_DAYS);
568 hr_utility.trace(l_proc||' g_SSP_correction.WAITING_DAYS :'||g_SSP_correction.WAITING_DAYS);
569 hr_utility.trace(l_proc||' g_SSP_correction.PIW_THRESHHOLD :'||g_SSP_correction.PIW_THRESHHOLD);
570 hr_utility.trace(l_proc||' g_SSP_correction.MAXIMUM_LINKED_PIW_YEARS :'||g_SSP_correction.MAXIMUM_LINKED_PIW_YEARS);
571 hr_utility.trace(l_proc||' g_SSP_correction.PERCENTAGE_THRESHHOLD :'||g_SSP_correction.PERCENTAGE_THRESHHOLD);
572 hr_utility.trace(l_proc||' g_SSP_correction.SSP_DAYS_DUE_ID :'||g_SSP_correction.SSP_DAYS_DUE_ID);
573 hr_utility.trace(l_proc||' g_SSP_correction.AMOUNT_ID :'||g_SSP_correction.AMOUNT_ID);
574 hr_utility.trace(l_proc||' g_SSP_correction.FROM_ID :'||g_SSP_correction.FROM_ID);
575 hr_utility.trace(l_proc||' g_SSP_correction.TO_ID :'||g_SSP_correction.TO_ID);
576 hr_utility.trace(l_proc||' g_SSP_correction.RATE_ID :'||g_SSP_correction.RATE_ID);
577 hr_utility.trace(l_proc||' g_SSP_correction.WITHHELD_DAYS_ID :'||g_SSP_correction.WITHHELD_DAYS_ID);
578 hr_utility.trace(l_proc||' g_SSP_correction.SSP_WEEKS_ID :'||g_SSP_correction.SSP_WEEKS_ID);
579 hr_utility.trace(l_proc||' g_SSP_correction.QUALIFYING_DAYS_ID :'||g_SSP_correction.QUALIFYING_DAYS_ID);
580 hr_utility.trace(l_proc||' g_SSP_correction.input_currency_code :'||g_SSP_correction.input_currency_code);
581
582 --
583 -- Check element returned expected values (this is belt and braces checking,
584 -- if the check fails then it was seed data which has been incorrectly set up.
585 -- However, failing here may prevent more inexplicable errors elsewhere.
586 --
587 if g_SSP_correction.element_type_id is null
588 then
589 fnd_message.set_name ('SSP', 'SSP_35078_NO_SSP_CORR_ELEMENT');
590 fnd_message.set_token ('EFFECTIVE_DATE',p_effective_date);
591 fnd_message.raise_error;
592 else
593 --
594 -- The element type exists
595 --
596 if (g_SSP_correction.SSP_DAYS_DUE_ID is null
597 or g_SSP_correction.AMOUNT_ID is null
598 or g_SSP_correction.FROM_ID is null
599 or g_SSP_correction.TO_ID is null
600 or g_SSP_correction.RATE_ID is null
601 or g_SSP_correction.WITHHELD_DAYS_ID is null
602 or g_SSP_correction.SSP_WEEKS_ID is null
603 or g_SSP_correction.QUALIFYING_DAYS_ID is null)
604 then
605 --
606 -- One of the input values is missing.
607 --
608 fnd_message.set_name ('SSP','SSP_36071_INCORRECT_INPUT_VALS');
609 fnd_message.set_token ('ELEMENT_NAME',c_SSP_element_name);
610 fnd_message.raise_error;
611 end if;
612 --
613 if (g_SSP_correction.MAXIMUM_SSP_PERIOD is null
614 or g_SSP_correction.MAXIMUM_AGE is null
615 or g_SSP_correction.LINKING_PERIOD_DAYS is null
616 or g_SSP_correction.WAITING_DAYS is null
617 or g_SSP_correction.PIW_THRESHHOLD is null
618 or g_SSP_correction.MAXIMUM_LINKED_PIW_YEARS is null
619 or g_SSP_correction.PERCENTAGE_THRESHHOLD is null)
620 then
621 --
622 -- One of the DDF segments has not been entered.
623 --
624 fnd_message.set_name ('SSP','SSP_36070_MISSING_DDF_SEGMENT');
625 fnd_message.set_token ('ELEMENT_NAME',c_SSP_element_name);
626 fnd_message.raise_error;
627 end if;
628 end if;
629 --
630 hr_utility.set_location('Leaving :'||l_proc,100);
631 --
632 end get_SSP_correction_element;
633 --------------------------------------------------------------------------------
634 procedure update_linked_absence_ids is
635 --
636 -- Updates linked_absence_IDs where the absence has either become part of a
637 -- series or dropped out of a series due to date changes on the absence.
638 --
639 l_proc constant varchar2 (72) := g_package||'update_linked_absence_ids';
640 l_new_linked_absence_id number (15) := null;
641 absence_links_but_shouldnt boolean := FALSE;
642 absence_doesnt_link_but_should boolean := FALSE;
643 --
644 cursor csr_missing_links is
645 --
646 -- Get all the absences affected by the current transaction.
647 --
648 select absence.*
649 from per_absence_attendances ABSENCE,
650 ssp_temp_affected_rows TRANSACTION
651 where
652 ( (transaction.PIW_ID = absence.absence_attendance_id and
653 absence.linked_absence_id IS NULL)
654 or
655 transaction.piw_id = absence.linked_absence_id)
656 and transaction.locked = to_char(userenv('sessionid'));
657 --
658 begin
659 --
660 hr_utility.set_location('Entering:'||l_proc,1);
661 --
662 for new_link in csr_missing_links
663 LOOP
664 --
665 -- For each absence affected by the current transaction, check that it has
666 -- the correct linked_absence_id.
667 --
668 -- Get the linked_absence_id the absence SHOULD have.
669 l_new_linked_absence_id := ssp_ssp_pkg.linked_absence_id (
670 new_link.person_id,
671 new_link.sickness_start_date,
672 new_link.sickness_end_date);
673 --
674 absence_links_but_shouldnt := (l_new_linked_absence_id is null and
675 new_link.linked_absence_id is not null);
676 --
677 absence_doesnt_link_but_should := (l_new_linked_absence_id is not null and
678 new_link.linked_absence_id is null);
679 --
680 if (absence_links_but_shouldnt or absence_doesnt_link_but_should)
681 then
682 --
683 -- update the absence's linked absence ID to the calculated one
684 --
685 update per_absence_attendances
686 set linked_absence_id = l_new_linked_absence_id
687 where absence_attendance_id = new_link.absence_attendance_id;
688 --
689 if l_new_linked_absence_id is not null
690 --
691 -- if the absence has been updated from being a whole PIW series in
692 -- its own right to being just one of another series.
693 then
694 --
695 -- Update the list of PIWs affected by the current transaction to
696 -- reflect the PIW series actually affected.
697 --
698 update ssp_temp_affected_rows
699 set PIW_ID = l_new_linked_absence_id
700 where PIW_ID = new_link.absence_attendance_id;
701 end if;
702 end if;
703 end loop;
704 --
705 hr_utility.set_location('Leaving :'||l_proc, 100);
706 --
707 end update_linked_absence_ids;
708 --------------------------------------------------------------------------------
709 --
710 -- Return the absence_attendance_id of the first absence in a series of
711 -- sickness absences which are separated by less than a defined period.
712 --
713 function linked_absence_id(p_person_id in number,
714 p_sickness_start_date in date,
715 p_sickness_end_date in date) return number is
716 l_proc varchar2 (72) := g_package||'linked_absence_id';
717 --
718 -- Get all sickness absences prior to the current one, that do not have
719 -- a linked_absence_id and are not the start absence of the PIW.
720 cursor csr_contiguous_absences is
721 select absence_attendance_id,
722 sickness_start_date,
723 sickness_end_date
724 from per_absence_attendances
725 where person_id = p_person_id
726 and sickness_start_date is not null
727 and sickness_start_date < p_sickness_start_date
728 and linked_absence_id is null
729 order by sickness_start_date desc
730 for update;
731 --
732 cursor csr_linked_absence (x_sickness_start_date date) is
733 select absence_attendance_id
734 from per_absence_attendances
735 where sickness_start_date = x_sickness_start_date
736 and person_id = p_person_id;
737 --
738 l_PIW_id number := null;
739 l_PIW_start date := null;
740 l_current_sickness_start date := p_sickness_start_date;
741 --
742 procedure check_parameters is
743 all_parameters_valid constant boolean :=
744 (p_person_id is not null and
745 p_sickness_start_date <= p_sickness_end_date and
746 p_sickness_start_date = trunc (p_sickness_start_date) and
747 p_sickness_end_date = trunc (p_sickness_end_date));
748 begin
749 hr_utility.trace(l_proc||' p_person_id = '||to_char (p_person_id));
750 hr_utility.trace(l_proc||' p_sickness_start_date = '||to_char (p_sickness_start_date));
751 hr_utility.trace(l_proc||' p_sickness_end_date = '||to_char (p_sickness_end_date));
752 hr_general.assert_condition (all_parameters_valid);
753 end check_parameters;
754 begin
755 --
756 hr_utility.set_location('Entering:'||l_proc,1);
757 --
758 check_parameters;
759 --
760 -- If the sickness start date is null then this cannot be a sickness absence.
761 -- If SSP is not installed then this functionality is not available.
762 if p_sickness_start_date is null or (not SSP_is_installed) then
763 -- Return null as no linked absence is possible.
764 l_PIW_id := null;
765 else
766 -- Get the absence_attendance_id of the first PIW in the series
767 l_PIW_start := (ssp_ssp_pkg.linked_PIW_start_date(p_person_id => p_person_id,
768 p_sickness_start_date => p_sickness_start_date,
769 p_sickness_end_date => p_sickness_end_date));
770 -- if there is a PIW start date
771 -- and the PIW start date is not the start date for the current absence
772 if l_PIW_start is not null and l_PIW_start <> p_sickness_start_date then
773 open csr_linked_absence (l_PIW_start);
774 fetch csr_linked_absence into l_PIW_id;
775 close csr_linked_absence;
776 --
777 -- It is possible to enter separate but contiguous sickness absences. That
778 -- means that a series of absences could be entered consisting of four,
779 -- one-day absences. Each individual day would not itself comprise a PIW,
780 -- but taken together, a PIW is formed. Since absences must be entered in
781 -- chronological order, this would be detected on entry of the fourth one.
782 -- However, if the PIW thus formed links to a previous absence, then the
783 -- PIW ID must be applied to all four of the absences, not just the fourth
784 -- one as it is inserted.
785 for previous in csr_contiguous_absences loop
786 -- previous absence is not in a contiguous series with the current one
787 -- or the previous absence is the first in the current PIW
788 exit when(previous.sickness_end_date <> l_current_sickness_start - 1 or
789 previous.absence_attendance_id = l_PIW_ID);
790 --
791 -- Set the PIW ID of the previous absence the same as the current one
792 update per_absence_attendances
793 set linked_absence_id = l_PIW_ID
794 where current of csr_contiguous_absences;
795 --
796 l_current_sickness_start := previous.sickness_start_date;
797 end loop;
798 end if;
799 end if;
800 --
801 hr_utility.set_location('Leaving :'||l_proc||', l_PIW_id = '||to_char (l_PIW_id),100);
802 --
803 return l_PIW_id;
804 --
805 end linked_absence_id;
806 --------------------------------------------------------------------------------
807 --
808 -- Returns TRUE if the parameter absence constitutes a PIW in its own right
809 -- or if it forms part of a contiguous set of rows which together form a PIW
810 --
811 -- NB Do not add hr_utility calls in here because this function is used by
812 -- other functions which must maintain purity level WNDS, WNPS.
813 --
814 function absence_is_a_PIW(p_person_id number,
815 p_sickness_start_date date,
816 p_sickness_end_date date) return boolean is
817 --
818 --select the number of days, within the period specified,
819 --for which the person has absences
820 cursor csr_abs_days(p_start date, p_end date) is
821 select nvl(sum(nvl(least(sickness_end_date,p_end),p_end) -
822 greatest(sickness_start_date,p_start) + 1),0)
823 from per_absence_attendances
824 where person_id = p_person_id
825 and sickness_start_date <= p_end
826 and nvl(sickness_end_date,hr_general.end_of_time) >= p_start;
827 --
828 cursor csr_contig_abs(p_start date, p_end date,
829 p_start2 date, p_end2 date) is
830 -- select the dates for the continuous absence formed by the parameter
831 -- absence and any absences adjacent to it.
832 select least(min(sickness_start_date),p_start),
833 greatest(max(nvl(sickness_end_date,hr_general.end_of_time)),p_end)
834 from per_absence_attendances
835 where person_id = p_person_id
836 and (sickness_end_date = p_start2 or sickness_start_date = p_end2);
837 --
838 l_days_absent number := 0;
839 l_prev_sickness_start date := null;
840 l_prev_sickness_end date := null;
841 l_sickness_start_date date := p_sickness_start_date;
842 l_sickness_end_date date := nvl (p_sickness_end_date,hr_general.end_of_time);
843 l_absence_is_a_PIW boolean := FALSE;
844 --
845 begin
846 get_SSP_element (p_sickness_start_date);
847 if (l_sickness_end_date - p_sickness_start_date) + 1 >= g_SSP_legislation.PIW_threshhold then
848 l_absence_is_a_PIW := TRUE; -- The absence is a PIW in its own right
849 else
850 -- Check if the absence has contiguous absences which effectively
851 -- extend the sickness start and end dates (and thus may cause a PIW to
852 -- be formed).
853 <<loop_form_PIW>>
854 loop
855 l_prev_sickness_start := l_sickness_start_date;
856 l_prev_sickness_end := l_sickness_end_date;
857
858 -- Find contiguous absences which may contribute to a PIW
859 open csr_contig_abs(l_prev_sickness_start, l_prev_sickness_end,
860 l_prev_sickness_start - 1, l_prev_sickness_end + 1);
861 fetch csr_contig_abs into l_sickness_start_date,
862 l_sickness_end_date;
863
864 --No contiguous absences (null returned by max function)
865 if l_sickness_start_date is null then
866 exit loop_form_PIW;
867 elsif (l_sickness_end_date - l_sickness_start_date) +1
868 >= g_SSP_legislation.PIW_threshhold then
869 -- The absence formed is a PIW
870 l_absence_is_a_PIW := TRUE; -- The absence formed is a PIW
871 exit loop_form_PIW;
872 elsif l_prev_sickness_end = l_sickness_end_date then
873 -- There is no contiguous future absence so look for number of days
874 -- absent within threshold period before PIW formed so far
875 open csr_abs_days(l_sickness_end_date - g_SSP_legislation.PIW_threshhold +1,
876 l_sickness_start_date -1);
877 fetch csr_abs_days into l_days_absent;
878 close csr_abs_days;
879 --
880 if (l_sickness_end_date - l_sickness_start_date) +1 +
881 l_days_absent >= g_SSP_legislation.PIW_threshhold then
882 l_absence_is_a_PIW := TRUE; -- The absence formed is a PIW
883 end if;
884 exit loop_form_PIW;
885 elsif l_prev_sickness_start = l_sickness_start_date then
886 -- There is no contiguous past absence so look for number of days
887 -- absent within threshold period after PIW formed so far
888 open csr_abs_days(l_sickness_end_date +1,l_sickness_start_date -1
889 + g_SSP_legislation.PIW_threshhold);
890 fetch csr_abs_days into l_days_absent;
891 close csr_abs_days;
892 if (l_sickness_end_date - l_sickness_start_date) +1 + l_days_absent
893 >= g_SSP_legislation.PIW_threshhold then
894 l_absence_is_a_PIW := TRUE; -- The absence formed is a PIW
895 end if;
896 exit loop_form_PIW;
897 end if;
898 --else two contiguous abs, so search for past and future
899 --contiguous abs again
900 close csr_contig_abs;
901 end loop loop_form_PIW;
902 close csr_contig_abs;
903 end if;
904 --
905 return l_absence_is_a_PIW;
906 end absence_is_a_PIW;
907 --------------------------------------------------------------------------------
908 --
909 -- Overload function for the absence_is_a_PIW
910 function absence_is_a_PIW(p_person_id number,
911 p_sickness_start_date date,
912 p_sickness_end_date date,
913 p_absence_attendance_id number) return boolean is
914 --
915 --select the number of days, within the period specified,
916 --for which the person has absences
917 cursor csr_abs_days(p_start date, p_end date) is
918 select nvl(sum(nvl(least(sickness_end_date,p_end),p_end) -
919 greatest(sickness_start_date,p_start) + 1),0)
920 from per_absence_attendances
921 where person_id = p_person_id
922 and sickness_start_date <= p_end
923 and nvl(sickness_end_date,hr_general.end_of_time) >= p_start;
924 --
925 cursor csr_contig_abs(p_start date, p_end date,
926 p_start2 date, p_end2 date) is
927 -- select the dates for the continuous absence formed by the parameter
928 -- absence and any absences adjacent to it.
929 select least(min(sickness_start_date),p_start),
930 greatest(max(nvl(sickness_end_date,hr_general.end_of_time)),p_end)
931 from per_absence_attendances
932 where person_id = p_person_id
933 and (sickness_end_date = p_start2 or sickness_start_date = p_end2);
934 --
935 cursor csr_linked_id is
936 select linked_absence_id
937 from per_absence_attendances
938 where absence_attendance_id = p_absence_attendance_id;
939 --
940 l_days_absent number := 0;
941 l_linked number := null;
942 l_prev_sickness_start date := null;
943 l_prev_sickness_end date := null;
944 l_sickness_start_date date := p_sickness_start_date;
945 l_sickness_end_date date := nvl (p_sickness_end_date,hr_general.end_of_time);
946 l_absence_is_a_PIW boolean := FALSE;
947 --
948 begin
949 get_SSP_element (p_sickness_start_date);
950 if (l_sickness_end_date - p_sickness_start_date) + 1 >= g_SSP_legislation.PIW_threshhold then
951 l_absence_is_a_PIW := TRUE; -- The absence is a PIW in its own right
952 else
953 open csr_linked_id;
954 fetch csr_linked_id into l_linked;
955 --if csr_linked_id%found then
956 if l_linked is not null then --for bug fix 5583730
957 l_absence_is_a_PIW := TRUE;
958 else
959 -- Check if the absence has contiguous absences which effectively
960 -- extend the sickness start and end dates (and thus may cause a PIW to
961 -- be formed).
962 <<loop_form_PIW>>
963 loop
964 l_prev_sickness_start := l_sickness_start_date;
965 l_prev_sickness_end := l_sickness_end_date;
966
967 -- Find contiguous absences which may contribute to a PIW
968 open csr_contig_abs(l_prev_sickness_start, l_prev_sickness_end,
969 l_prev_sickness_start - 1, l_prev_sickness_end + 1);
970 fetch csr_contig_abs into l_sickness_start_date,
971 l_sickness_end_date;
972
973 --No contiguous absences (null returned by max function)
974 if l_sickness_start_date is null then
975 exit loop_form_PIW;
976 elsif (l_sickness_end_date - l_sickness_start_date) +1
977 >= g_SSP_legislation.PIW_threshhold then
978 -- The absence formed is a PIW
979 l_absence_is_a_PIW := TRUE; -- The absence formed is a PIW
980 exit loop_form_PIW;
981 elsif l_prev_sickness_end = l_sickness_end_date then
982 -- There is no contiguous future absence so look for number of days
983 -- absent within threshold period before PIW formed so far
984 open csr_abs_days(l_sickness_end_date - g_SSP_legislation.PIW_threshhold +1,
985 l_sickness_start_date -1);
986 fetch csr_abs_days into l_days_absent;
987 close csr_abs_days;
988 --
989 if (l_sickness_end_date - l_sickness_start_date) +1 +
990 l_days_absent >= g_SSP_legislation.PIW_threshhold then
991 l_absence_is_a_PIW := TRUE; -- The absence formed is a PIW
992 end if;
993 exit loop_form_PIW;
994 elsif l_prev_sickness_start = l_sickness_start_date then
995 -- There is no contiguous past absence so look for number of days
996 -- absent within threshold period after PIW formed so far
997 open csr_abs_days(l_sickness_end_date +1,l_sickness_start_date -1
998 + g_SSP_legislation.PIW_threshhold);
999 fetch csr_abs_days into l_days_absent;
1000 close csr_abs_days;
1001 if (l_sickness_end_date - l_sickness_start_date) +1 + l_days_absent
1002 >= g_SSP_legislation.PIW_threshhold then
1003 l_absence_is_a_PIW := TRUE; -- The absence formed is a PIW
1004 end if;
1005 exit loop_form_PIW;
1006 end if;
1007 --else two contiguous abs, so search for past and future
1008 --contiguous abs again
1009 close csr_contig_abs;
1010 end loop loop_form_PIW;
1011 close csr_contig_abs;
1012 end if;
1013 end if;
1014 --
1015 return l_absence_is_a_PIW;
1016 end absence_is_a_PIW;
1017 --------------------------------------------------------------------------------
1018 procedure check_sickness_date_change (
1019 --
1020 -- Called from AFTER update of sickness_start_date, sickness_end_date trigger.
1021 -- Prevents update if the change would invalidate the linked_absence_id of
1022 -- either this row or the next one.
1023 --
1024 p_person_id in number,-- :old.person_id
1025 p_linked_absence_id in number,-- :old.linked_absence_id
1026 p_absence_attendance_id in number,-- :old.absence_attendance_id
1027 p_new_sickness_start_date in date,-- :new.sickness_start_date
1028 p_new_sickness_end_date in date, -- :new.sickness_end_date
1029 p_old_sickness_end_date in date -- :old.sickness_end_date
1030 ) is
1031 --
1032 cursor csr_next_absence is
1033 --
1034 -- Get the chronologically next sickness absence
1035 --
1036 select abs.linked_absence_id,
1037 abs.sickness_start_date,
1038 abs.sickness_end_date
1039 from per_absence_attendances ABS
1040 where abs.sickness_start_date is not null
1041 and person_id = p_person_id
1042 and abs.sickness_start_date = (
1043 --
1044 select min (abs2.sickness_start_date)
1045 from per_absence_attendances ABS2
1046 where abs2.sickness_start_date >= p_old_sickness_end_date
1047 and person_id = p_person_id);
1048 --
1049 l_proc varchar2 (72) := g_package||'check_sickness_date_change';
1050 l_next_absence csr_next_absence%rowtype;
1051 PIW_broken exception;
1052 --
1053 procedure check_parameters is
1054 --
1055 all_parameters_valid constant boolean := (p_person_id is not null and
1056 p_absence_attendance_id is not null);
1057 --
1058 begin
1059 --
1060 hr_utility.trace (' p_person_id = '||to_char (p_person_id));
1061 hr_utility.trace (' p_linked_absence_id = '
1062 ||to_char (p_linked_absence_id));
1063 hr_utility.trace (' p_absence_attendance_id = '
1064 ||to_char (p_absence_attendance_id));
1065 hr_utility.trace (' p_new_sickness_start_date = '
1066 ||to_char (p_new_sickness_start_date));
1067 hr_utility.trace (' p_new_sickness_end_date = '
1068 ||to_char (p_new_sickness_end_date));
1069 hr_utility.trace (' p_old_sickness_end_date = '
1070 ||to_char (p_old_sickness_end_date));
1071 --
1072 hr_general.assert_condition (all_parameters_valid);
1073 --
1074 end check_parameters;
1075 --
1076 begin
1077 --
1078 hr_utility.set_location('Entering:'||l_proc,1);
1079 --
1080 check_parameters;
1081 --
1082 open csr_next_absence;
1083 fetch csr_next_absence into l_next_absence;
1084 --
1085 -- Compare the current values of the linked absence ids with the values they
1086 -- are recalculated to have after the update has gone through
1087 --
1088 if
1089 -- if there is a future sickness absence
1090 csr_next_absence%found
1091 --
1092 -- and if the PIW series to which the updated absence belongs will change
1093 and (nvl (p_linked_absence_id,-1) <> nvl (linked_absence_id (p_person_id,
1094 p_new_sickness_start_date,
1095 p_new_sickness_end_date),
1096 nvl (p_linked_absence_id,-1))
1097 -- or the PIW series to which the following absence belongs will change
1098 or (csr_next_absence%found
1099 and nvl (l_next_absence.linked_absence_id, -1)
1100 <> nvl (linked_absence_id (p_person_id,
1101 l_next_absence.sickness_start_date,
1102 l_next_absence.sickness_end_date), -1)))
1103 then
1104 --
1105 -- The change in sickness dates will change the PIW of the current or next
1106 -- sickness absence and so the update must be prevented.
1107 --
1108 close csr_next_absence;
1109 raise PIW_broken;
1110 else
1111 close csr_next_absence;
1112 end if;
1113 --
1114 hr_utility.set_location('Leaving :'||l_proc,100);
1115 --
1116 exception
1117 --
1118 when PIW_broken then
1119 --
1120 fnd_message.set_name ('SSP','SSP_35037_PIW_BROKEN');
1121 fnd_message.raise_error;
1122 --
1123 end check_sickness_date_change;
1124 --------------------------------------------------------------------------------
1125 procedure CHECK_FOR_BREAK_IN_LINKED_PIW
1126 --
1127 -- Check the effect of removal of a sickness absence from a linked PIW.
1128 -- See header for full description of this procedure.
1129 --
1130 (
1131 p_sickness_start_date in date,
1132 p_sickness_end_date in date,
1133 p_linked_absence_id in number,
1134 p_absence_attendance_id in number
1135 )
1136 is
1137 --
1138 l_proc varchar2 (72) := g_package||'check_for_break_in_linked_PIW';
1139 l_PIW_id number := nvl (p_linked_absence_id, p_absence_attendance_id);
1140 l_next_start_date date := null;
1141 l_previous_end_date date := null;
1142 l_dummy integer (1) := null;
1143 break_in_PIW exception;
1144 --
1145 cursor csr_PIW is
1146 --
1147 -- Return a row if there are any sickness absences in a series of
1148 -- which this absence is first.
1149 --
1150 select 1
1151 from per_absence_attendances
1152 where linked_absence_id = p_absence_attendance_id;
1153 --
1154 cursor csr_next_absence is
1155 --
1156 -- Get the absence which is next in the linked series of which this
1157 -- absence is a part.
1158 --
1159 select max (sickness_end_date)
1160 from per_absence_attendances
1161 where p_linked_absence_id = linked_absence_id
1162 and sickness_end_date <= p_sickness_start_date;
1163 --
1164 cursor csr_previous_absence is
1165 --
1166 -- Get the absence which is the previous one in the linked series of
1167 -- which this absence is a part.
1168 --
1169 select min (sickness_start_date)
1170 from per_absence_attendances
1171 where (l_PIW_id = linked_absence_id and absence_attendance_id is null)
1172 or (l_PIW_id = absence_attendance_id and linked_absence_id is null)
1173 and sickness_start_date >= p_sickness_end_date;
1174 --
1175 procedure check_parameters is
1176 --
1177 all_parameters_valid constant boolean := (p_absence_attendance_id is not null
1178 and p_sickness_start_date <= p_sickness_end_date
1179 and p_sickness_start_date = trunc (p_sickness_start_date)
1180 and p_sickness_end_date = trunc (p_sickness_end_date)
1181 and p_linked_absence_id <> p_absence_attendance_id);
1182 --
1183 begin
1184 --
1185 hr_utility.trace (l_proc||' p_sickness_start_date = '
1186 ||to_char (p_sickness_start_date));
1187 hr_utility.trace (l_proc||' p_sickness_end_date = '
1188 ||to_char (p_sickness_end_date));
1189 hr_utility.trace (l_proc||' p_linked_absence_id = '
1190 ||to_char (p_linked_absence_id));
1191 hr_utility.trace (l_proc||' p_absence_attendance_id = '
1192 ||to_char (p_absence_attendance_id));
1193 --
1194 hr_general.assert_condition (all_parameters_valid);
1195 --
1196 end check_parameters;
1197 --
1198 begin
1199 --
1200 hr_utility.set_location('Entering:'||l_proc,1);
1201 --
1202 check_parameters;
1203 --
1204 if SSP_is_installed and p_sickness_start_date is not null
1205 then
1206 --
1207 -- The SSP functionality is available and the absence is a sickness absence.
1208 --
1209 -- Is the absence the first in a linked series of absences?
1210 --
1211 open csr_PIW;
1212 fetch csr_PIW into l_dummy;
1213 --
1214 if csr_PIW%found then
1215 --
1216 -- This is the first absence in a linked series and may not be removed
1217 --
1218 close csr_PIW;
1219 raise break_in_PIW;
1220 else
1221 --
1222 -- This is not the first absence in a linked series
1223 --
1224 close csr_PIW;
1225 --
1226 -- Is the absence the last in a linked series?
1227 --
1228 open csr_next_absence;
1229 fetch csr_next_absence into l_next_start_date;
1230 --
1231 if csr_next_absence%found then
1232 --
1233 -- The absence is between other absences in a linked series.
1234 --
1235 close csr_next_absence;
1236 --
1237 -- Find the previous absence
1238 --
1239 open csr_previous_absence;
1240 fetch csr_previous_absence into l_previous_end_date;
1241 --
1242 -- Get the legislative parameters for SSP
1243 --
1244 get_SSP_element (p_sickness_start_date);
1245 --
1246 -- Can the next absence link directly to the previous absence without
1247 -- the current absence in the middle?
1248 --
1249 if l_previous_end_date
1250 <= (l_next_start_date - g_SSP_legislation.linking_period_days)
1251 then
1252 --
1253 -- The linked series will be broken by removal of this absence
1254 --
1255 raise break_in_PIW;
1256 end if;
1257 end if;
1258 end if;
1259 end if;
1260 --
1261 hr_utility.set_location('Leaving :'||l_proc,100);
1262 --
1263 exception
1264 when break_in_PIW then
1265 --
1266 -- Stop, with the message:
1267 -- "You may not delete this sickness absence record because to do so would
1268 -- result in a linked Period of Incapacity for Work (PIW) being broken. To
1269 -- get round this, you must first remove all the later sickness absences in
1270 -- the same PIW."
1271 --
1272 hr_utility.set_location('Leaving :'||l_proc||', Error',999);
1273 fnd_message.set_name ('SSP','SSP_35037_PIW_BROKEN');
1274 fnd_message.raise_error;
1275 --
1276 end check_for_break_in_linked_PIW;
1277 --------------------------------------------------------------------------------
1278 function get_age_at_PIW(p_person_id in number,
1279 p_date in date,
1280 p_date_of_birth in date default null) return number is
1281 l_age number;
1282
1283 cursor get_age is
1284 select months_between(p_date,date_of_birth)/12
1285 from per_all_people_f
1286 where person_id = p_person_id
1287 and effective_end_date = (select max(effective_end_date)
1288 from per_all_people_f
1289 where person_id = p_person_id);
1290
1291 cursor get_age2 is
1292 select months_between(p_date,p_date_of_birth)/12
1293 from dual;
1294
1295 begin
1296 if p_date_of_birth is null then
1297 open get_age;
1298 fetch get_age into l_age;
1299 close get_age;
1300 else
1301 open get_age2;
1302 fetch get_age2 into l_age;
1303 close get_age2;
1304 end if;
1305
1306 return l_age;
1307 end get_age_at_PIW;
1308 --------------------------------------------------------------------------------
1309 function check_linked_absence(p_absence_attendance_id in number,
1310 p_start_date out nocopy date,
1311 p_end_date out nocopy date) return boolean is
1312 --
1313 l_linked_id number;
1314 l_start_date date;
1315 l_end_date date;
1316 l_found boolean;
1317 --
1318 -- Get the linked ID from the absence
1319 cursor csr_linked_id(p_absence_id number) is
1320 select linked_absence_id
1321 from per_absence_attendances
1322 where absence_attendance_id = p_absence_id;
1323 --
1324 cursor csr_start_date(p_absence_id number) is
1325 select sickness_start_date
1326 from per_absence_attendances
1327 where absence_attendance_id = p_absence_id;
1328 --
1329 cursor csr_end_date(p_absence_id number) is
1330 select sickness_end_date
1331 from per_absence_attendances
1332 where (absence_attendance_id = p_absence_id
1333 or
1334 linked_absence_id = p_absence_id)
1335 order by sickness_end_date desc;
1336 --
1337 begin
1338 l_found := false;
1339 open csr_linked_id(p_absence_attendance_id);
1340 fetch csr_linked_id into l_linked_id;
1341 if csr_linked_id%found and l_linked_id is not null then
1342 l_found := true;
1343 end if;
1344 close csr_linked_id;
1345
1346 if l_found then
1347 open csr_start_date(l_linked_id);
1348 fetch csr_start_date into l_start_date;
1349 close csr_start_date;
1350 --
1351 open csr_end_date(l_linked_id);
1352 fetch csr_end_date into l_end_date;
1353 close csr_end_date;
1354 --
1355 p_start_date := l_start_date;
1356 p_end_date := l_end_date;
1357 end if;
1358
1359 return l_found;
1360 end check_linked_absence;
1361 --------------------------------------------------------------------------------
1362 function linked_PIW_start_date(p_person_id in number,
1363 p_sickness_start_date in date,
1364 p_sickness_end_date in date,
1365 p_date_of_birth in date) return date is
1366 --
1367 PIW_start date := null;
1368 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
1369 l_proc varchar2(72) := g_package||'linked_PIW_start_date';
1370 l_sickness_end_date date := nvl(p_sickness_end_date,hr_general.end_of_time);
1371 l_age number;
1372 l_s_date date;
1373 l_e_date date;
1374 --
1375 -- Get the linked series of sickness absences
1376 cursor PIW_series(p_start_date date) is
1377 select sickness_start_date,
1378 sickness_end_date,
1379 absence_attendance_id
1380 from per_absence_attendances
1381 where person_id = p_person_id
1382 and sickness_start_date is not null
1383 and sickness_start_date < p_sickness_start_date
1384 and (p_start_date is null or
1385 sickness_start_date >= p_start_date)
1386 order by sickness_start_date desc;
1387 --
1388 begin
1389 if p_sickness_start_date is not null then
1390 --
1391 -- This is a sickness absence
1392 --
1393 if ssp_ssp_pkg.absence_is_a_PIW(p_person_id => p_person_id,
1394 p_sickness_start_date => p_sickness_start_date,
1395 p_sickness_end_date => p_sickness_end_date) then
1396 -- The current absence is a PIW
1397 --
1398 PIW_start := p_sickness_start_date;
1399 --
1400 get_SSP_element (p_sickness_start_date);
1401 --
1402 l_age := get_age_at_PIW(p_person_id, l_01_October_06, p_date_of_birth);
1403 -----------------------------------------
1404 -- Age < 16 and sick after 01-Oct-2006 --
1405 -----------------------------------------
1406 if l_age < 16 and p_sickness_start_date >= l_01_October_06 then
1407 for preceeding in PIW_series(l_01_October_06) LOOP
1408 if (PIW_start - preceeding.sickness_end_date) <= g_SSP_legislation.linking_period_days and
1409 ssp_ssp_pkg.absence_is_a_PIW(p_sickness_start_date => preceeding.sickness_start_date,
1410 p_sickness_end_date => preceeding.sickness_end_date,
1411 p_person_id => p_person_id) then
1412 --
1413 -- The previous absence links to the current one
1414 -- Decrement the PIW start to the start of the previous absence
1415 --
1416 if check_linked_absence(preceeding.absence_attendance_id,
1417 l_s_date, l_e_date) then
1418 PIW_start := l_s_date;
1419 exit;
1420 end if;
1421 PIW_start := preceeding.sickness_start_date;
1422 end if;
1423 end loop;
1424 end if;
1425
1426 ---------------
1427 -- Other Age --
1428 ---------------
1429 if (l_age >= 16) or (p_sickness_start_date < l_01_October_06) then
1430 for preceeding in PIW_series(null) LOOP
1431 if (PIW_start - preceeding.sickness_end_date) <= g_SSP_legislation.linking_period_days and
1432 ssp_ssp_pkg.absence_is_a_PIW(p_sickness_start_date => preceeding.sickness_start_date,
1433 p_sickness_end_date => preceeding.sickness_end_date,
1434 p_person_id => p_person_id) then
1435 --
1436 -- The previous absence links to the current one
1437 -- Decrement the PIW start to the start of the previous absence
1438 --
1439 if check_linked_absence(preceeding.absence_attendance_id,
1440 l_s_date, l_e_date) then
1441 PIW_start := l_s_date;
1442 exit;
1443 end if;
1444 PIW_start := preceeding.sickness_start_date;
1445 end if;
1446 end loop;
1447 end if;
1448 --
1449 end if;
1450 --
1451 end if;
1452 --
1453 return PIW_start;
1454 --
1455 end linked_PIW_start_date;
1456 --------------------------------------------------------------------------------
1457 function linked_PIW_start_date(p_person_id in number,
1458 p_sickness_start_date in date,
1459 p_sickness_end_date in date) return date is
1460 --
1461 PIW_start date := null;
1462 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
1463 l_proc varchar2(72) := g_package||'linked_PIW_start_date';
1464 l_sickness_end_date date := nvl(p_sickness_end_date,hr_general.end_of_time);
1465 l_age number;
1466 l_linked_id number;
1467 l_s_date date;
1468 l_e_date date;
1469 --
1470 -- Get the linked series of sickness absences
1471 /* 12552547 Begin
1472 - Absences in different periods of service should not be linked.
1473 cursor PIW_series(p_start_date date) is
1474 select sickness_start_date,
1475 sickness_end_date,
1476 absence_attendance_id
1477 from per_absence_attendances
1478 where person_id = p_person_id
1479 and sickness_start_date is not null
1480 and sickness_start_date < p_sickness_start_date
1481 and (p_start_date is null or
1482 sickness_start_date >= p_start_date)
1483 order by sickness_start_date desc;
1484 */
1485
1486 l_PERIOD_OF_SERVICE_ID PER_PERIODS_OF_SERVICE.PERIOD_OF_SERVICE_ID%type;
1487
1488 cursor PIW_series(p_start_date date) is
1489 select sickness_start_date,
1490 sickness_end_date,
1491 absence_attendance_id
1492 from per_absence_attendances per,
1493 per_periods_of_service service
1494 where per.person_id = p_person_id
1495 and per.sickness_start_date is not null
1496 and per.sickness_start_date < p_sickness_start_date
1497 and (p_start_date is null or
1498 per.sickness_start_date >= p_start_date)
1499 and per.sickness_start_date between service.DATE_START and nvl(service.actual_termination_date,hr_general.end_of_time)
1500 and service.PERIOD_OF_SERVICE_ID = l_PERIOD_OF_SERVICE_ID
1501 order by sickness_start_date desc;
1502
1503 Cursor POS_series(p_start_date date) is
1504 select PERIOD_OF_SERVICE_ID from per_periods_of_service service
1505 where PERSON_ID = p_person_id
1506 and p_start_date between DATE_START and nvl(service.actual_termination_date,hr_general.end_of_time);
1507
1508 --12552547 End
1509
1510 --
1511 begin
1512 if p_sickness_start_date is not null then
1513 --
1514 -- This is a sickness absence
1515 --
1516 if ssp_ssp_pkg.absence_is_a_PIW(p_person_id => p_person_id,
1517 p_sickness_start_date => p_sickness_start_date,
1518 p_sickness_end_date => p_sickness_end_date) then
1519 -- The current absence is a PIW
1520 --
1521 PIW_start := p_sickness_start_date;
1522 --
1523 -- 12552547 Begin
1524 open POS_series(PIW_start);
1525 fetch POS_series into l_PERIOD_OF_SERVICE_ID; -- The period of service id corresponding absence start date
1526 close POS_series;
1527 -- 12552547 End
1528 --
1529 get_SSP_element (p_sickness_start_date);
1530 --
1531 l_age := get_age_at_PIW(p_person_id, l_01_October_06);
1532 -----------------------------------------
1533 -- Age < 16 and sick after 01-Oct-2006 --
1534 -----------------------------------------
1535 if l_age < 16 and p_sickness_start_date >= l_01_October_06 then
1536 for preceeding in PIW_series(l_01_October_06) LOOP
1537 if (PIW_start - preceeding.sickness_end_date) <= g_SSP_legislation.linking_period_days and
1538 ssp_ssp_pkg.absence_is_a_PIW(p_sickness_start_date => preceeding.sickness_start_date,
1539 p_sickness_end_date => preceeding.sickness_end_date,
1540 p_person_id => p_person_id) then
1541 --
1542 -- The previous absence links to the current one
1543 -- Decrement the PIW start to the start of the previous absence
1544 --
1545 if check_linked_absence(preceeding.absence_attendance_id,
1546 l_s_date, l_e_date) then
1547 PIW_start := l_s_date;
1548 exit;
1549 end if;
1550 PIW_start := preceeding.sickness_start_date;
1551 end if;
1552 end loop;
1553 end if;
1554
1555 ---------------
1556 -- Other Age --
1557 ---------------
1558 if (l_age >= 16) or (p_sickness_start_date < l_01_October_06) then
1559 for preceeding in PIW_series(null) LOOP
1560 if (PIW_start - preceeding.sickness_end_date) <= g_SSP_legislation.linking_period_days and
1561 ssp_ssp_pkg.absence_is_a_PIW(p_sickness_start_date => preceeding.sickness_start_date,
1562 p_sickness_end_date => preceeding.sickness_end_date,
1563 p_person_id => p_person_id) then
1564 --
1565 -- The previous absence links to the current one
1566 -- Decrement the PIW start to the start of the previous absence
1567 --
1568 if check_linked_absence(preceeding.absence_attendance_id,
1569 l_s_date, l_e_date) then
1570 PIW_start := l_s_date;
1571 exit;
1572 end if;
1573 PIW_start := preceeding.sickness_start_date;
1574 end if;
1575 end loop;
1576 end if;
1577 --
1578 end if;
1579 --
1580 end if;
1581 --
1582 return PIW_start;
1583 --
1584 end linked_PIW_start_date;
1585 --------------------------------------------------------------------------------
1586 --
1587 -- Overload function with absence_attendance_id
1588 function linked_PIW_start_date(p_person_id in number,
1589 p_sickness_start_date in date,
1590 p_sickness_end_date in date,
1591 p_absence_attendance_id number) return date is
1592 --
1593 PIW_start date := null;
1594 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
1595 l_proc varchar2(72) := g_package||'linked_PIW_start_date';
1596 l_sickness_end_date date := nvl(p_sickness_end_date,hr_general.end_of_time);
1597 l_age number;
1598 l_s_date date;
1599 l_e_date date;
1600 --
1601 -- Get the linked series of sickness absences
1602 /* 12552547 - begin
1603 --Absences with differenct period of service id should not be linked
1604 cursor PIW_series(p_start_date date) is
1605 select sickness_start_date,
1606 sickness_end_date,
1607 absence_attendance_id
1608 from per_absence_attendances
1609 where person_id = p_person_id
1610 and sickness_start_date is not null
1611 and sickness_start_date < p_sickness_start_date
1612 and (p_start_date is null or
1613 sickness_start_date >= p_start_date)
1614 order by sickness_start_date desc;
1615 */
1616
1617 l_PERIOD_OF_SERVICE_ID PER_PERIODS_OF_SERVICE.PERIOD_OF_SERVICE_ID%type;
1618
1619 cursor PIW_series(p_start_date date) is
1620 select sickness_start_date,
1621 sickness_end_date,
1622 absence_attendance_id
1623 from per_absence_attendances per,
1624 per_periods_of_service service
1625 where per.person_id = p_person_id
1626 and per.sickness_start_date is not null
1627 and per.sickness_start_date < p_sickness_start_date
1628 and (p_start_date is null or
1629 per.sickness_start_date >= p_start_date)
1630 and per.person_id = service.person_id
1631 and per.sickness_start_date between service.DATE_START and nvl(service.actual_termination_date,hr_general.end_of_time)
1632 and service.PERIOD_OF_SERVICE_ID = l_PERIOD_OF_SERVICE_ID
1633 order by sickness_start_date desc;
1634
1635 --
1636
1637 Cursor POS_series(p_start_date date) is
1638 select PERIOD_OF_SERVICE_ID
1639 from per_periods_of_service service
1640 where PERSON_ID = p_person_id
1641 and p_start_date between DATE_START and nvl(service.actual_termination_date,hr_general.end_of_time);
1642
1643 --12552547 End
1644
1645 --
1646 begin
1647 if p_sickness_start_date is not null then
1648 --
1649 -- This is a sickness absence
1650 --
1651 if ssp_ssp_pkg.absence_is_a_PIW(p_person_id => p_person_id,
1652 p_sickness_start_date => p_sickness_start_date,
1653 p_sickness_end_date => p_sickness_end_date,
1654 p_absence_attendance_id => p_absence_attendance_id) then
1655 -- The current absence is a PIW
1656 --
1657 PIW_start := p_sickness_start_date;
1658 --
1659 -- 12552547 Begin
1660 open POS_series(PIW_start);
1661 fetch POS_series into l_PERIOD_OF_SERVICE_ID; -- The period of service id corresponding absence start date
1662 close POS_series;
1663 -- 12552547 End
1664 get_SSP_element (p_sickness_start_date);
1665 --
1666 l_age := get_age_at_PIW(p_person_id, l_01_October_06);
1667 -----------------------------------------
1668 -- Age < 16 and sick after 01-Oct-2006 --
1669 -----------------------------------------
1670 if l_age < 16 and p_sickness_start_date >= l_01_October_06 then
1671 for preceeding in PIW_series(l_01_October_06) LOOP
1672 if (PIW_start - preceeding.sickness_end_date) <= g_SSP_legislation.linking_period_days and
1673 ssp_ssp_pkg.absence_is_a_PIW(p_sickness_start_date => preceeding.sickness_start_date,
1674 p_sickness_end_date => preceeding.sickness_end_date,
1675 p_person_id => p_person_id,
1676 p_absence_attendance_id => preceeding.absence_attendance_id) then
1677 --
1678 -- The previous absence links to the current one
1679 -- Decrement the PIW start to the start of the previous absence
1680 --
1681 if check_linked_absence(preceeding.absence_attendance_id,
1682 l_s_date, l_e_date) then
1683 PIW_start := l_s_date;
1684 exit;
1685 end if;
1686 PIW_start := preceeding.sickness_start_date;
1687 end if;
1688 end loop;
1689 end if;
1690
1691 ---------------
1692 -- Other Age --
1693 ---------------
1694 if (l_age >= 16) or (p_sickness_start_date < l_01_October_06) then
1695 for preceeding in PIW_series(null) LOOP
1696 if (PIW_start - preceeding.sickness_end_date) <= g_SSP_legislation.linking_period_days and
1697 ssp_ssp_pkg.absence_is_a_PIW(p_sickness_start_date => preceeding.sickness_start_date,
1698 p_sickness_end_date => preceeding.sickness_end_date,
1699 p_person_id => p_person_id,
1700 p_absence_attendance_id => preceeding.absence_attendance_id) then
1701 --
1702 -- The previous absence links to the current one
1703 -- Decrement the PIW start to the start of the previous absence
1704 --
1705 if check_linked_absence(preceeding.absence_attendance_id,
1706 l_s_date, l_e_date) then
1707 PIW_start := l_s_date;
1708 exit;
1709 end if;
1710 PIW_start := preceeding.sickness_start_date;
1711 end if;
1712 end loop;
1713 end if;
1714 --
1715 end if;
1716 --
1717 end if;
1718 --
1719 return PIW_start;
1720 --
1721 end linked_PIW_start_date;
1722 --------------------------------------------------------------------------------
1723 function linked_PIW_end_date(p_person_id in number,
1724 p_sickness_start_date in date,
1725 p_sickness_end_date in date,
1726 p_date_of_birth in date) return date is
1727 PIW_end date := null;
1728 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
1729 l_limit_date date := null;
1730 l_age number;
1731 l_s_date date;
1732 l_e_date date;
1733 --
1734 -- Get all sicknesses for the person which follow the parameter dates
1735 cursor PIW_series(p_start_date date) is
1736 select sickness_start_date,
1737 sickness_end_date,
1738 absence_attendance_id
1739 from per_absence_attendances
1740 where person_id = p_person_id
1741 and sickness_start_date is not null
1742 and sickness_start_date > p_sickness_start_date
1743 and (p_start_date is null or
1744 sickness_start_date < p_start_date)
1745 order by sickness_start_date;
1746 begin
1747 if (p_sickness_start_date is null or p_sickness_end_date is null) then
1748 PIW_end := null;
1749 else
1750 if ssp_ssp_pkg.absence_is_a_PIW(p_person_id => p_person_id,
1751 p_sickness_start_date => p_sickness_start_date,
1752 p_sickness_end_date => p_sickness_end_date) then
1753 PIW_end := p_sickness_end_date;
1754 --
1755 get_SSP_element (p_sickness_start_date);
1756 --
1757 l_age := get_age_at_PIW(p_person_id, l_01_October_06,p_date_of_birth);
1758 --
1759 if (l_age < 16) and p_sickness_start_date < l_01_October_06 then
1760 l_limit_date := l_01_October_06;
1761 end if;
1762 --
1763 --
1764 for next in PIW_series(l_limit_date) LOOP
1765 -- if the next sickness period links to the current one
1766 -- and the next sickness period is a PIW
1767 if (next.sickness_start_date - PIW_end) <= g_SSP_legislation.linking_period_days and
1768 ssp_ssp_pkg.absence_is_a_PIW (p_person_id => p_person_id,
1769 p_sickness_start_date => next.sickness_start_date,
1770 p_sickness_end_date => next.sickness_end_date)then
1771 --
1772 -- Increment the end date to that of the next sickness period
1773 --
1774 if check_linked_absence(next.absence_attendance_id,
1775 l_s_date, l_e_date) then
1776 PIW_end := l_e_date;
1777 exit;
1778 end if;
1779 PIW_end := next.sickness_end_date;
1780 end if;
1781 end loop;
1782 end if;
1783 end if;
1784 --
1785 return PIW_end;
1786 --
1787 end linked_PIW_end_date;
1788 --------------------------------------------------------------------------------
1789 function linked_PIW_end_date(p_person_id in number,
1790 p_sickness_start_date in date,
1791 p_sickness_end_date in date) return date is
1792 PIW_end date := null;
1793 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
1794 l_limit_date date := null;
1795 l_age number;
1796 l_s_date date;
1797 l_e_date date;
1798 --
1799 -- Get all sicknesses for the person which follow the parameter dates
1800 cursor PIW_series(p_start_date date) is
1801 select sickness_start_date,
1802 sickness_end_date,
1803 absence_attendance_id
1804 from per_absence_attendances
1805 where person_id = p_person_id
1806 and sickness_start_date is not null
1807 and sickness_start_date > p_sickness_start_date
1808 and (p_start_date is null or
1809 sickness_start_date < p_start_date)
1810 order by sickness_start_date;
1811 begin
1812 if (p_sickness_start_date is null or p_sickness_end_date is null) then
1813 PIW_end := null;
1814 else
1815 if ssp_ssp_pkg.absence_is_a_PIW(p_person_id => p_person_id,
1816 p_sickness_start_date => p_sickness_start_date,
1817 p_sickness_end_date => p_sickness_end_date) then
1818 PIW_end := p_sickness_end_date;
1819 --
1820 get_SSP_element (p_sickness_start_date);
1821 --
1822 l_age := get_age_at_PIW(p_person_id, l_01_October_06);
1823 --
1824 if (l_age < 16) and
1825 p_sickness_start_date < l_01_October_06 then
1826 l_limit_date := l_01_October_06;
1827 end if;
1828 --
1829 --
1830 for next in PIW_series(l_limit_date) LOOP
1831 -- if the next sickness period links to the current one
1832 -- and the next sickness period is a PIW
1833 if (next.sickness_start_date - PIW_end) <= g_SSP_legislation.linking_period_days and
1834 ssp_ssp_pkg.absence_is_a_PIW (p_person_id => p_person_id,
1835 p_sickness_start_date => next.sickness_start_date,
1836 p_sickness_end_date => next.sickness_end_date)then
1837 --
1838 -- Increment the end date to that of the next sickness period
1839 --
1840 if check_linked_absence(next.absence_attendance_id,
1841 l_s_date, l_e_date) then
1842 PIW_end := l_e_date;
1843 exit;
1844 end if;
1845 PIW_end := next.sickness_end_date;
1846 end if;
1847 end loop;
1848 end if;
1849 end if;
1850 --
1851 return PIW_end;
1852 --
1853 end linked_PIW_end_date;
1854 --------------------------------------------------------------------------------
1855 --
1856 -- Overload function with absence_attendance_id
1857 function linked_PIW_end_date(p_person_id in number,
1858 p_sickness_start_date in date,
1859 p_sickness_end_date in date,
1860 p_absence_attendance_id number) return date is
1861 PIW_end date := null;
1862 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
1863 l_limit_date date := null;
1864 l_age number;
1865 l_s_date date;
1866 l_e_date date;
1867 --
1868 -- Get all sicknesses for the person which follow the parameter dates
1869 cursor PIW_series(p_start_date date) is
1870 select sickness_start_date,
1871 sickness_end_date,
1872 absence_attendance_id
1873 from per_absence_attendances
1874 where person_id = p_person_id
1875 and sickness_start_date is not null
1876 and sickness_start_date > p_sickness_start_date
1877 and (p_start_date is null or
1878 sickness_start_date < p_start_date)
1879 order by sickness_start_date;
1880 begin
1881 if (p_sickness_start_date is null or p_sickness_end_date is null) then
1882 PIW_end := null;
1883 else
1884 if ssp_ssp_pkg.absence_is_a_PIW(p_person_id => p_person_id,
1885 p_sickness_start_date => p_sickness_start_date,
1886 p_sickness_end_date => p_sickness_end_date,
1887 p_absence_attendance_id => p_absence_attendance_id) then
1888 PIW_end := p_sickness_end_date;
1889 --
1890 get_SSP_element (p_sickness_start_date);
1891 --
1892 l_age := get_age_at_PIW(p_person_id, l_01_October_06);
1893 --
1894 if (l_age < 16) and
1895 p_sickness_start_date < l_01_October_06 then
1896 l_limit_date := l_01_October_06;
1897 end if;
1898 --
1899 --
1900 for next in PIW_series(l_limit_date) LOOP
1901 -- if the next sickness period links to the current one
1902 -- and the next sickness period is a PIW
1903 if (next.sickness_start_date - PIW_end) <= g_SSP_legislation.linking_period_days and
1904 ssp_ssp_pkg.absence_is_a_PIW (p_person_id => p_person_id,
1905 p_sickness_start_date => next.sickness_start_date,
1906 p_sickness_end_date => next.sickness_end_date,
1907 p_absence_attendance_id => next.absence_attendance_id)then
1908 --
1909 -- Increment the end date to that of the next sickness period
1910 --
1911 if check_linked_absence(next.absence_attendance_id,
1912 l_s_date, l_e_date) then
1913 PIW_end := l_e_date;
1914 exit;
1915 end if;
1916 PIW_end := next.sickness_end_date;
1917 end if;
1918 end loop;
1919 end if;
1920 end if;
1921 --
1922 return PIW_end;
1923 --
1924 end linked_PIW_end_date;
1925 --------------------------------------------------------------------------------
1926 function qualifying_days_in_period
1927 --
1928 -- Returns the number of SSP qualifying days in a specified period.
1929 --
1930 (
1931 p_period_from in date,
1932 p_period_to in date,
1933 p_person_id in number,
1934 p_business_group_id in number,
1935 p_processing_level in number default 0
1936 )
1937 return integer is
1938 --
1939 l_person_purpose_usage_id number := NULL;
1940 l_bg_purpose_usage_id number := NULL;
1941 l_purpose_usage_id number;
1942 l_qualifying_days integer := 0;
1943 l_person_primary_key_value number := NULL;
1944 l_bg_primary_key_value number := NULL;
1945 l_primary_key_value number;
1946 l_dummy_start_date date;
1947 l_dummy_end_date date;
1948 l_proc varchar2 (72) := g_package||'qualifying_days_in_period';
1949 l_first_absence boolean;
1950 l_save_end_date date;
1951 --
1952 no_SSP_pattern exception;
1953 invalid_SSP_pattern exception;
1954 --
1955 cursor csr_qualifying_pattern is
1956 --
1957 -- 563202 - by concatanating null to purpose_usage_id in the where clause the
1958 -- use of a better index is forced.
1959 -- Returns those patterns that exist at some stage within the absence
1960 -- It will be person or BG pattern depending on the variables passed in
1961 --
1962 select start_date
1963 , end_date
1964 from hr_calendar_usages
1965 where purpose_usage_id||null = l_purpose_usage_id
1966 and primary_key_value = l_primary_key_value
1967 and end_date >= p_period_from
1968 and start_date <= p_period_to;
1969 --
1970 --6658285 begin
1971 Type csr_qua_pattern is record( start_date date,end_date date);
1972 Type csr_qua_pat_tab is table of csr_qua_pattern index by binary_integer;
1973 csr_qualifying_pattern_PLtable csr_qua_pat_tab;
1974 cont number:=0;
1975 --6658285 end
1976 procedure check_parameters is
1977 --
1978 all_parameters_valid constant boolean := (p_period_from is not null
1979 and p_period_to is not null
1980 and p_period_from <= p_period_to
1981 and p_period_from = trunc(p_period_from)
1982 and p_period_to = trunc (p_period_to)
1983 and p_person_id is not null
1984 and p_business_group_id is not null);
1985 --
1986 begin
1987 --
1988 hr_utility.trace(' p_period_from: '||to_char(p_period_from));
1989 hr_utility.trace(' p_period_to: '||to_char(p_period_to));
1990 hr_utility.trace(' p_person_id: '||to_char(p_person_id));
1991 hr_utility.trace(' p_business_group_id: '||to_char(p_business_group_id));
1992 --
1993 hr_general.assert_condition (all_parameters_valid);
1994 --
1995 end check_parameters;
1996 --
1997 begin
1998 --
1999 hr_utility.set_location('Entering:'||l_proc,1);
2000 --
2001 check_parameters;
2002 --
2003 -- Look for a personal SSP qualifying pattern.
2004 --
2005 l_primary_key_value := p_person_id;
2006 l_person_primary_key_value := l_primary_key_value;
2007 l_purpose_usage_id := hr_calendar_pkg.purpose_usage_id ('PERSON',
2008 'QUALIFYING PATTERN');
2009 l_person_purpose_usage_id := l_purpose_usage_id;
2010 --
2011 l_first_absence := TRUE;
2012 --
2013 --6658285 begin
2014 for I in csr_qualifying_pattern loop
2015 cont := cont+1;
2016 csr_qualifying_pattern_PLtable(cont).start_date := I.start_date;
2017 csr_qualifying_pattern_PLtable(cont).end_date := I.end_date;
2018 end loop;
2019 --for pattern in csr_qualifying_pattern loop
2020 for pattern in 1..csr_qualifying_pattern_PLtable.count loop
2021 --6658285 end
2022 if l_first_absence
2023 then
2024 /*6658285 Begin
2025 if pattern.start_date > p_period_from
2026 then
2027 close csr_qualifying_pattern; */
2028 if csr_qualifying_pattern_PLtable(pattern).start_date > p_period_from
2029 then
2030 --6658285 end
2031 l_primary_key_value := p_business_group_id;
2032 l_bg_primary_key_value := l_primary_key_value;
2033 l_purpose_usage_id := hr_calendar_pkg.purpose_usage_id(
2034 'ORGANIZATION',
2035 'QUALIFYING PATTERN');
2036 l_bg_purpose_usage_id := l_purpose_usage_id;
2037 --
2038 open csr_qualifying_pattern;
2039 fetch csr_qualifying_pattern into l_dummy_start_date, l_dummy_end_date;
2040 --
2041 if csr_qualifying_pattern%notfound
2042 then
2043 -- there was no qualifying pattern for the bg
2044 raise no_SSP_pattern;
2045 end if;
2046 --
2047 close csr_qualifying_pattern;
2048 --
2049 /*6658285 Begin
2050 elsif pattern.end_date < p_period_to
2051 then
2052 l_save_end_date := pattern.end_date;*/
2053 elsif csr_qualifying_pattern_PLtable(pattern).end_date < p_period_to
2054 then
2055 l_save_end_date := csr_qualifying_pattern_PLtable(pattern).end_date;
2056 --6658285 end
2057 l_first_absence := FALSE;
2058 end if;
2059 else -- not l_first_absence
2060 /*6658285 Begin
2061 if pattern.start_date > l_save_end_date + 1
2062 then
2063 close csr_qualifying_pattern;
2064 */
2065 if csr_qualifying_pattern_PLtable(pattern).start_date > l_save_end_date + 1
2066 then
2067 --6658285 end
2068 l_primary_key_value := p_business_group_id;
2069 l_bg_primary_key_value := l_primary_key_value;
2070 l_purpose_usage_id :=hr_calendar_pkg.purpose_usage_id(
2071 'ORGANIZATION',
2072 'QUALIFYING PATTERN');
2073 l_bg_purpose_usage_id := l_purpose_usage_id;
2074 --
2075 open csr_qualifying_pattern;
2076 fetch csr_qualifying_pattern into l_dummy_start_date, l_dummy_end_date;
2077 if csr_qualifying_pattern%notfound
2078 then
2079 -- there was no qualifying pattern for the bg
2080 raise no_SSP_pattern;
2081 end if;
2082 close csr_qualifying_pattern;
2083 --
2084 /*6658285 Begin
2085 elsif pattern.end_date < p_period_to
2086 then
2087 l_save_end_date := pattern.end_date; */
2088 elsif csr_qualifying_pattern_PLtable(pattern).end_date < p_period_to
2089 then
2090 l_save_end_date := csr_qualifying_pattern_PLtable(pattern).end_date;
2091 --6658285 end
2092 end if;
2093 --
2094 l_first_absence := FALSE;
2095 end if;
2096 --
2097 l_first_absence := FALSE;
2098 --
2099 /*6658285 Begin commenting the fix done for bug 550269
2100 -- Fix for Bug 550269
2101 if not(csr_qualifying_pattern%ISOPEN)
2102 then
2103 open csr_qualifying_pattern;
2104 end if;
2105 --
2106 6658285 end*/
2107 end loop;
2108 --
2109 if l_first_absence
2110 then
2111 l_person_primary_key_value := null;
2112 l_person_purpose_usage_id := null;
2113 l_primary_key_value:= p_business_group_id;
2114 l_bg_primary_key_value := l_primary_key_value;
2115 l_purpose_usage_id := hr_calendar_pkg.purpose_usage_id(
2116 'ORGANIZATION',
2117 'QUALIFYING PATTERN');
2118 l_bg_purpose_usage_id := l_purpose_usage_id;
2119 --
2120 open csr_qualifying_pattern;
2121 fetch csr_qualifying_pattern into l_dummy_start_date, l_dummy_end_date;
2122 --
2123 if csr_qualifying_pattern%notfound
2124 then
2125 raise no_SSP_pattern;
2126 end if;
2127 close csr_qualifying_pattern;
2128 end if;
2129 --
2130 -- Having found the purpose usage, determine the number of qualifying days
2131 -- in the period according to the appropriate calendar
2132 --
2133 hr_utility.trace('PERSON PATTERN USAGE ID: '||l_person_purpose_usage_id);
2134 hr_utility.trace('PERSON PRIMARY KEY VAL: '||l_person_primary_key_value);
2135 hr_utility.trace('BG PATTERN USAGE ID: '||l_bg_purpose_usage_id);
2136 hr_utility.trace('BG PRIMARY KEY VALUE: '||l_bg_primary_key_value);
2137 hr_utility.trace('PERIOD FROM/TO: '||p_period_from||' -> '||p_period_to);
2138 --
2139 -- call new overloaded version of hr_calendar_pkg.total_availability
2140 --
2141 l_qualifying_days := hr_calendar_pkg.total_availability (
2142 p_availability => 'QUALIFYING',
2143 p_person_purpose_usage_id => l_person_purpose_usage_id,
2144 p_person_primary_key_value => l_person_primary_key_value,
2145 p_bg_purpose_usage_id => l_bg_purpose_usage_id,
2146 p_bg_primary_key_value => l_bg_primary_key_value,
2147 p_period_from => p_period_from,
2148 p_period_to => p_period_to + 1,
2149 p_processing_level => p_processing_level);
2150 --
2151 hr_utility.set_location('Leaving :'||l_proc||
2152 '. Qual days: '||to_char(l_qualifying_days),100);
2153 --
2154 return l_qualifying_days;
2155 --
2156 exception
2157 --
2158 when no_SSP_pattern then
2159 hr_utility.set_location('Leaving :'||l_proc||', Error',999);
2160 fnd_message.set_name ('SSP','SSP_35048_NO_SSP_QUAL_PATTERN');
2161 fnd_message.raise_error;
2162 --
2163 end qualifying_days_in_period;
2164 --
2165 --------------------------------------------------------------------------------
2166 function SSP_is_installed return boolean is
2167 --
2168 -- Checks that SSP is installed before SSP functionality is performed.
2169 -- This code was copied and modified from hrapiapi.pkb
2170 --
2171 l_pa_installed fnd_product_installations.status%TYPE;
2172 l_industry fnd_product_installations.industry%TYPE;
2173 l_pa_appid fnd_product_installations.application_id%TYPE;
2174 --
2175 l_SSP_installed boolean := FALSE;
2176 l_proc varchar2 (72) := g_package||'SSP_is_installed';
2177 --
2178 begin
2179 --
2180 hr_utility.set_location('Entering:'||l_proc,1);
2181 --
2182 if g_SSP_is_installed is null
2183 then
2184 -- We need to determine if SSP is installed.
2185 --
2186 begin
2187
2188 select application_id
2189 into l_pa_appid
2190 from fnd_application
2191 where upper(application_short_name) = upper('SSP');
2192
2193 if (fnd_installation.get(appl_id => l_pa_appid,
2194 dep_appl_id => l_pa_appid,
2195 status => l_pa_installed,
2196 industry => l_industry))
2197 then
2198 --
2199 -- Check to see if status = 'I'
2200 --
2201 if (l_pa_installed = 'I') then
2202 l_SSP_installed := TRUE;
2203 else
2204 l_SSP_installed := FALSE;
2205 end if;
2206 else
2207 l_SSP_installed := FALSE;
2208
2209 end if;
2210 --
2211 g_SSP_is_installed := l_SSP_installed;
2212
2213 exception
2214
2215 when too_many_rows then
2216 hr_utility.trace('Error: more than 1 row on FND_APPLICATION table for SSP');
2217
2218 when others then
2219 raise;
2220
2221 end;
2222
2223 end if;
2224 --
2225 if g_SSP_is_installed
2226 then
2227 hr_utility.trace('SSP is installed');
2228 else
2229 hr_utility.trace('SSP is NOT installed');
2230 end if;
2231 --
2232 hr_utility.set_location('Leaving :'||l_proc,100);
2233 --
2234 return g_SSP_is_installed;
2235 --
2236 end SSP_is_installed;
2237 --------------------------------------------------------------------------------
2238 --------------------------------------------------------------------------------
2239 function ENTITLED_TO_SSP(p_absence per_absence_attendances%rowtype)
2240 --
2241 -- See header for description of this function.
2242 --
2243 return boolean is
2244 --
2245 l_proc varchar2(72) := g_package||'entitled_to_ssp';
2246 last_entitled_day date := hr_general.end_of_time;
2247 max_PIW_end_date date := null;
2248 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
2249 --
2250 no_prima_facia_entitlement exception;
2251 employee_too_old exception;
2252 earnings_too_low exception;
2253 /*BUG 2984577 Added exception*/
2254 evidence_not_available exception;
2255
2256 --Bug Fix 8356706 Begin
2257 l_saturday varchar2(100) := rtrim(to_char(to_date('06/01/2001','DD/MM/YYYY'),'DAY'));
2258 l_sunday varchar2(100) := rtrim(to_char(to_date('07/01/2001','DD/MM/YYYY'),'DAY'));
2259 --Bug Fix 8356706 End
2260
2261 -- System-created stoppages for the PIW which have not been overridden
2262 cursor csr_old_stoppages is
2263 select stp.*
2264 from ssp_stoppages STP
2265 where stp.absence_attendance_id = g_PIW_id
2266 and ((stp.override_stoppage <> 'Y' and stp.user_entered <> 'Y')
2267 or
2268 (stp.withhold_from > PIW_end_date));
2269 --
2270 /*--------------------------------------*/
2271 /* Create a stoppage of payment for SSP */
2272 /*--------------------------------------*/
2273 procedure create_stoppage(p_withhold_from in date,
2274 p_withhold_to in date default null,
2275 p_reason in varchar2,
2276 p_overridden out nocopy boolean) is
2277 l_dummy number;
2278 l_reason_id number;
2279 l_proc varchar2 (72) := g_package||'create_stoppage';
2280
2281 procedure check_parameters is
2282 all_parameters_valid constant boolean :=
2283 (p_withhold_from is not null
2284 and p_withhold_from = trunc (p_withhold_from)
2285 and p_withhold_to = trunc (p_withhold_to)
2286 and p_withhold_from <= p_withhold_to
2287 and p_reason is not null);
2288 begin
2289 hr_utility.trace(' p_reason: ' || p_reason);
2290 hr_utility.trace(' withhold_from/to: ' ||
2291 to_char(p_withhold_from)||', '||to_char(p_withhold_to));
2292 hr_general.assert_condition (all_parameters_valid);
2293 end check_parameters;
2294 --
2295 begin
2296 hr_utility.set_location('Entering:'||l_proc,1);
2297 --
2298 check_parameters;
2299 --
2300 l_reason_id := ssp_smp_support_pkg.withholding_reason_id(
2301 g_SSP_legislation.element_type_id,p_reason);
2302 --
2303 if not ssp_smp_support_pkg.stoppage_overridden(p_absence_attendance_id => g_PIW_id,
2304 p_reason_id => l_reason_id) then
2305 -- the withholding reason is not overridden for this PIW
2306 --
2307 -- Create a stoppage for the PIW
2308 --
2309 ssp_stp_ins.ins (p_withhold_from => p_withhold_from,
2310 p_withhold_to => p_withhold_to,
2311 p_stoppage_id => l_dummy,
2312 p_object_version_number => l_dummy,
2313 p_absence_attendance_id => g_PIW_id,
2314 p_user_entered => 'N',
2315 p_reason_id => l_reason_id);
2316 --
2317 p_overridden := FALSE;
2318 else
2319 --
2320 -- Inform the calling procedure that the stoppage could not be
2321 -- created because it has been overridden by the user.
2322 --
2323 p_overridden := TRUE;
2324 end if;
2325 --
2326 hr_utility.set_location('Leaving :'||l_proc,100);
2327 --
2328 end create_stoppage;
2329 --
2330
2331 /*---------------------------------------------------*/
2332 /* Check that the absentee is not too old to qualify */
2333 /* for SSP. The date on which age is measured is */
2334 /* the start of the linked PIW. */
2335 /*---------------------------------------------------*/
2336 procedure check_age is
2337 l_proc varchar2(72) := g_package||'check_age';
2338 l_stoppage_overridden boolean := FALSE;
2339 age_at_PIW_start_date number := floor (months_between (PIW_start_date,
2340 absentee.date_of_birth) / 12);
2341 l_end_date date;
2342
2343 cursor get_end_date is
2344 select nvl(sickness_end_date, l_01_October_06 - 1)
2345 from per_absence_attendances
2346 where ((sickness_end_date is null and sickness_start_date < l_01_October_06)
2347 or
2348 sickness_end_date < l_01_October_06)
2349 and person_id = p_absence.person_id
2350 and sickness_start_date is not null
2351 order by sickness_end_date DESC;
2352 begin
2353 hr_utility.set_location('Entering:'||l_proc,1);
2354 --
2355 hr_utility.trace('Age at PIW start date: '||to_char(Age_at_PIW_start_date));
2356 hr_utility.trace('g_SSP_legislation.maximum_age: '||to_char(g_SSP_legislation.maximum_age));
2357 --
2358 -- Calculate the absentee's age as at the PIW start date
2359 --
2360 if age_at_PIW_start_date >= g_SSP_legislation.maximum_age then
2361 --
2362 -- Stop SSP payment because absentee is too old
2363 --
2364 open get_end_date;
2365 fetch get_end_date into l_end_date;
2366 close get_end_date;
2367 hr_utility.trace(l_proc||'l_end_date: '||l_end_date);
2368 hr_utility.trace(l_proc||'PIW_end_date: '||PIW_end_date);
2369
2370 create_stoppage(p_withhold_from => PIW_start_date,
2371 p_withhold_to => least(PIW_end_date,l_end_date),
2372 p_reason => 'Employee too old',
2373 p_overridden => l_stoppage_overridden);
2374 --
2375 if not l_stoppage_overridden and PIW_end_date < l_01_October_06 then
2376 raise employee_too_old;
2377 end if;
2378 end if;
2379 --
2380 hr_utility.set_location('Leaving :'||l_proc,100);
2381 --
2382 end check_age;
2383 --
2384 /*--------------------------------------------------*/
2385 /* Create a stoppage of SSP from the date following */
2386 /* the date of death. */
2387 /*--------------------------------------------------*/
2388 procedure check_death is
2389 l_proc varchar2(72) := g_package||'check_death';
2390 l_stoppage_overridden boolean := FALSE;
2391 begin
2392 --
2393 hr_utility.set_location('Entering:'||l_proc,1);
2394 --
2395 -- Bug 2984458 to display 'Employee Died' when the employee is
2396 -- deceased
2397 if absentee.actual_termination_date is not null and
2398 absentee.leaving_reason='D' then
2399 create_stoppage (p_withhold_from => absentee.actual_termination_date +1,
2400 p_reason => 'Employee died',
2401 p_overridden => l_stoppage_overridden);
2402 end if;
2403 --
2404 hr_utility.set_location('Leaving :'||l_proc,100);
2405 --
2406 end check_death;
2407 --
2408 /*------------------------------------------------*/
2409 /* Return the last day before the first permanent */
2410 /* stoppage date to affect the PIW */
2411 /*------------------------------------------------*/
2412 procedure get_last_entitled_day is
2413 l_proc varchar2 (72) := g_package||'get_last_entitled_day';
2414 --
2415 -- Get the first permanent stoppage date to affect the
2416 -- PIW. Return the day before the stoppage is
2417 -- effective because that is the last day of payment.
2418 --
2419 cursor csr_last_entitled_day is
2420 select nvl (min (withhold_from),hr_general.end_of_time) -1
2421 from ssp_stoppages
2422 where absence_attendance_id = g_PIW_id
2423 and override_stoppage <> 'Y'
2424 and withhold_to is null;
2425 --
2426 begin
2427 --
2428 hr_utility.set_location('Entering:'||l_proc,1);
2429 --
2430 open csr_last_entitled_day;
2431 fetch csr_last_entitled_day into last_entitled_day;
2432 close csr_last_entitled_day;
2433 --
2434 -- The SSP stops with either the first stoppage, or the end of
2435 -- the employment, whichever is sooner.
2436 --
2437 last_entitled_day := least (last_entitled_day,max_PIW_end_date -1,
2438 absentee.actual_termination_date);
2439 --
2440 hr_utility.set_location('Leaving :'||l_proc,100);
2441 --
2442 end get_last_entitled_day;
2443 --
2444 /*----------------------------------------------------------------*/
2445 /* Check that the number of waiting days specified by legislation */
2446 /* have been served within the PIW. Also check that the number of */
2447 /* weeks of SSP paid is within the legislative limit and that the */
2448 /* PIW is within its legislative maximum length. */
2449 /*----------------------------------------------------------------*/
2450 procedure do_PIW_calculations is
2451 l_proc varchar2(72) := g_package||'do_PIW_calculations';
2452 l_pregnancy_related_illness varchar2(30);
2453 weeks_remaining number := g_SSP_legislation.maximum_SSP_period;
2454 waiting_days_left number := g_SSP_legislation.waiting_days;
2455 start_disqualifying_period date;
2456 end_disqualifying_period date;
2457 start_pregnancy_illness date;
2458 end_pregnancy_illness date;
2459 first_sunday_of_sickness date;
2460 cal_start_date date;
2461 cal_end_date date;
2462 rate_start_date date;
2463 rate_end_date date;
2464 l_max_absence_start_date date;
2465 l_max_absence_end_date date;
2466 l_sickness_start_date date;
2467 l_sickness_end_date date;
2468 l_min_withheld_from date;
2469 l_max_withheld_to date;
2470 l_PIW_end_date date := null;
2471 stoppage_date date := hr_general.end_of_time;
2472 min_cal_start_date date := hr_general.end_of_time;
2473 max_cal_end_date date := hr_general.start_of_time;
2474 l_nos_absences number;
2475 l_business_group_id number;
2476 l_absence_attendance_id number;
2477 l_nos_stoppages number;
2478 SSP_rate_figure number;
2479 l_age number;
2480 waiting_days_this_period number := 0;
2481 total_SSP_weeks number := 0;
2482 days_remaining number := weeks_remaining * 7;
2483 daily_rate number(9,4) := null;
2484 N integer := 0;
2485 maximum_SSP_paid exception;
2486 PIW_max_length_reached exception;
2487 stoppage_invoked exception;
2488 l_stoppage_overridden boolean := FALSE;
2489 l_SMP_element ssp_SMP_pkg.csr_SMP_element_details%rowtype;
2490 --
2491 type stoppage_table_type is record (t_withheld_from date_table,
2492 t_withheld_to date_table);
2493 --
2494 stoppage_table stoppage_table_type;
2495 empty_stoppage_table stoppage_table_type;
2496 --
2497 type absence_table_type is record (
2498 t_sickness_start_date date_table,
2499 t_sickness_end_date date_table,
2500 t_business_group_id number_table,
2501 t_absence_attendance_id number_table,
2502 t_pregnancy_related_illness varchar_table,
2503 t_linked_absence_id number_table);
2504 --
2505 absence_table absence_table_type;
2506 empty_absence_table absence_table_type;
2507 --
2508 -- Return rows if the period in question is covered by stoppages
2509 cursor csr_stoppages(p_effective_start_date in date,
2510 p_effective_end_date in date) is
2511 select withhold_from, withhold_to
2512 from ssp_stoppages
2513 where absence_attendance_id = g_PIW_id
2514 and override_stoppage = 'N'
2515 and withhold_to is not null
2516 and ((p_effective_start_date <= withhold_from and
2517 p_effective_end_date >= nvl(withhold_to,hr_general.end_of_time)
2518 )
2519 or
2520 (p_effective_end_date >= withhold_from and
2521 p_effective_start_date <= nvl(withhold_to,hr_general.end_of_time)
2522 ))
2523 union all
2524 select withhold_from, withhold_to
2525 from ssp_stoppages ss,
2526 per_absence_attendances paa
2527 where paa.linked_absence_id = g_PIW_id
2528 and paa.absence_attendance_id = ss.absence_attendance_id
2529 and override_stoppage = 'N'
2530 and withhold_to is not null
2531 and ((p_effective_start_date <= withhold_from and
2532 p_effective_end_date >= nvl(withhold_to,hr_general.end_of_time)
2533 )
2534 or
2535 (p_effective_end_date >= withhold_from and
2536 p_effective_start_date <= nvl(withhold_to,hr_general.end_of_time)
2537 ));
2538 --
2539 function SSP_rate (p_effective_date date) return number is
2540 --
2541 -- Get the SSP rate as at a given effective date.
2542 cursor csr_rate is
2543 select piv.default_value,
2544 piv.effective_start_date,
2545 piv.effective_end_date
2546 from pay_input_values_f PIV,
2547 pay_element_types_f ELT
2548 where elt.element_type_id = piv.element_type_id
2549 and elt.element_type_id = g_SSP_legislation.element_type_id
2550 and p_effective_date between piv.effective_start_date and piv.effective_end_date
2551 and p_effective_date between elt.effective_start_date and elt.effective_end_date
2552 and piv.input_value_id = g_SSP_legislation.rate_id;
2553 --
2554 l_proc varchar2 (72) := g_package||'SSP_rate';
2555 l_rate number;
2556
2557 cannot_get_SSP_rate exception;
2558 --
2559 procedure check_parameters is
2560 all_parameters_valid constant boolean
2561 :=(p_effective_date is not null and
2562 p_effective_date = trunc (p_effective_date));
2563 begin
2564 hr_utility.trace (l_proc||' p_effective_date = '||to_char (p_effective_date));
2565 --
2566 hr_general.assert_condition (all_parameters_valid);
2567 --
2568 end check_parameters;
2569 --
2570 begin
2571 hr_utility.set_location('Entering:'||l_proc,1);
2572 check_parameters;
2573 if rate_start_date is null or
2574 p_effective_date NOT between rate_start_date and rate_end_date then
2575 --
2576 -- The rate already retrieved is not the one we want so
2577 -- get the right one from the database.
2578 --
2579 open csr_rate;
2580 fetch csr_rate into SSP_rate_figure,
2581 rate_start_date, rate_end_date;
2582 close csr_rate;
2583 end if;
2584 --
2585 l_rate := SSP_rate_figure;
2586 --
2587 if l_rate is null then
2588 raise cannot_get_SSP_rate;
2589 end if;
2590 --
2591 hr_utility.set_location('Leaving :'||l_proc,100);
2592 --
2593 return l_rate;
2594 --
2595 exception
2596 when cannot_get_SSP_rate then
2597 hr_utility.set_location('Leaving :'||l_proc||', Error',999);
2598 fnd_message.set_name ('SSP','SSP_35079_NO_SSP_RATE');
2599 fnd_message.set_token ('EFFECTIVE_DATE',p_effective_date);
2600 fnd_message.raise_error;
2601 end SSP_rate;
2602 --
2603 /*--------------------------------------------------------------*/
2604 /* Calculate number of temporary stoppage days within a period. */
2605 /*--------------------------------------------------------------*/
2606 function stopped_days(p_start_date in date,
2607 p_end_date in date,
2608 p_PIW_id in number) return number is
2609 l_proc varchar2 (72) := g_package||'stopped_days';
2610 l_stopped_days_in_period number := 0;
2611 l_this_day date := p_start_date;
2612 l_stoppage_overridden boolean := FALSE;
2613 l_stoppage_found boolean;
2614 --
2615 procedure check_parameters is
2616 all_parameters_valid constant boolean :=
2617 (p_start_date is not null and
2618 p_end_date is not null and
2619 p_PIW_id is not null and
2620 p_start_date = trunc(p_start_date) and
2621 p_end_date = trunc(p_end_date) and
2622 p_start_date <= p_end_date);
2623 begin
2624 hr_utility.trace (' p_start_date = '||to_char (p_start_date));
2625 hr_utility.trace (' p_end_date = '||to_char (p_end_date));
2626 hr_utility.trace (' p_PIW_id = '||to_char (p_PIW_id));
2627 hr_general.assert_condition (all_parameters_valid);
2628 end check_parameters;
2629 begin
2630 hr_utility.set_location('Entering:'||l_proc,1);
2631 --
2632 check_parameters;
2633 --
2634 -- moved inside loop for bug 886707
2635 -- l_stoppage_found := FALSE;
2636 --
2637 -- Cycle through the days of the period passed in, checking
2638 -- each day for a temporary stoppage covering a qualifying day.
2639 --
2640 while l_this_day <= p_end_date loop
2641 -- 886707: Added initialisation of l_stoppage_found here so
2642 -- so that it is reset at every loop.
2643 l_stoppage_found := FALSE;
2644 --
2645 if 1 = qualifying_days_in_period(l_this_day, l_this_day,
2646 p_absence.person_id,
2647 p_absence.business_group_id,
2648 p_processing_level => 3)then
2649 --
2650 -- The current day is a qualifying day, so
2651 -- check for a stoppage covering this day.
2652 --
2653 for each_stoppage in 1..l_nos_stoppages loop
2654 if l_this_day
2655 between stoppage_table.t_withheld_from(each_stoppage)
2656 and stoppage_table.t_withheld_to(each_stoppage) then
2657 l_stoppage_found := TRUE;
2658 l_stopped_days_in_period :=l_stopped_days_in_period + 1;
2659 end if;
2660 end loop;
2661 --
2662 if not l_stoppage_found and waiting_days_left > 0 then
2663 --
2664 -- This day is not covered by a stoppage and there are
2665 -- waiting days to create.
2666 --
2667 create_stoppage(p_withhold_from => l_this_day,
2668 p_withhold_to => l_this_day,
2669 p_reason => 'Waiting day',
2670 p_overridden => l_stoppage_overridden);
2671 --
2672 if not l_stoppage_overridden then
2673 -- the waiting day stoppage is not user-overridden
2674 --
2675 waiting_days_left := waiting_days_left - 1;
2676 waiting_days_this_period :=waiting_days_this_period+1;
2677 else
2678 waiting_days_left := 0;
2679 end if;
2680 end if;
2681 end if;
2682 --
2683 l_this_day := l_this_day + 1;
2684 end loop;
2685 --
2686 hr_utility.trace('Stopped Days in Period:'||
2687 to_char(l_stopped_days_in_period));
2688 hr_utility.set_location('Leaving :'||l_proc,100);
2689 --
2690 return l_stopped_days_in_period;
2691 --
2692 end stopped_days;
2693 --
2694 procedure check_disqualifying_period(p_sickness_start_date date,
2695 p_sickness_end_date date,
2696 p_pregnancy_related_illness varchar2) is
2697 -- Select the maternity records for the person.
2698 --
2699 cursor maternity_details is
2700 select maternity_id,
2701 object_version_number,
2702 MPP_start_date,
2703 due_date, -- Need due_date to decide on value of sickness_trigger_weeks
2704 ssp_smp_pkg.expected_week_of_confinement(due_date) EWC
2705 from ssp_maternities
2706 where person_id = p_absence.person_id
2707 and nvl(leave_type,'MA') = 'MA';
2708
2709 l_proc varchar2 (72) := g_package||'check_disqualifying_period';
2710 l_stoppage_overridden boolean := FALSE;
2711 sickness_trigger_weeks integer;
2712 --
2713 procedure check_parameters is
2714 all_parameters_valid constant boolean :=
2715 (p_sickness_start_date is not null and
2716 p_sickness_start_date <= p_sickness_end_date and
2717 p_sickness_start_date = trunc(p_sickness_start_date) and
2718 p_sickness_end_date = trunc(p_sickness_end_date) and
2719 p_pregnancy_related_illness is not null and
2720 p_pregnancy_related_illness in ('Y','N'));
2721 begin
2722 hr_utility.trace(l_proc||' p_sickness_start_date = '
2723 ||to_char (p_sickness_start_date));
2724 hr_utility.trace(l_proc||' p_sickness_end_date = '
2725 ||to_char (p_sickness_end_date));
2726 hr_utility.trace(l_proc||' p_pregnancy_related_illness = '
2727 ||p_pregnancy_related_illness);
2728 hr_general.assert_condition (all_parameters_valid);
2729 end check_parameters;
2730 begin
2731 hr_utility.set_location('Entering:'||l_proc,1);
2732 --
2733 check_parameters;
2734 --
2735 for maternity in maternity_details loop
2736 if maternity.due_date >=
2737 fnd_date.canonical_to_date('2003/04/06 00:00:00') then
2738 sickness_trigger_weeks := 28;
2739 else
2740 sickness_trigger_weeks := 42;
2741 end if;
2742 --
2743 -- the illness is pregnancy-related
2744 -- and the sickness ends sickness trigger weeks
2745 -- (six weeks before 06-APR-2003, four weeks after)
2746 -- before the EWC or later
2747 -- and the sickness starts before the EWC
2748 if p_pregnancy_related_illness = 'Y' and
2749 (maternity.EWC - sickness_trigger_weeks) <= p_sickness_end_date and
2750 maternity.EWC >= p_sickness_start_date then
2751 --
2752 hr_utility.trace(l_proc||'Condition 1 true');
2753 --
2754 -- the illness starts before sickness trigger weeks
2755 -- (6 weeks before 06-APR-2003, four weeks after)
2756 -- prior to the EWC
2757 if (maternity.EWC - sickness_trigger_weeks) >=
2758 p_sickness_start_date then
2759 --
2760 hr_utility.trace(l_proc||'Condition 2 true');
2761 --
2762 -- there is no recored start_date OR
2763 -- the start date is later than
2764 -- the fourth or sixth week prior to the EWC
2765 -- depending on whether the due date of the
2766 -- maternity is on or after 06-APR-2003
2767 if maternity.MPP_start_date is null or
2768 maternity.MPP_start_date >
2769 (maternity.EWC - sickness_trigger_weeks) then
2770 --
2771 -- force the MPP to start on the Sunday of the
2772 -- sixth week prior to the EWC
2773 if maternity.due_date <
2774 fnd_date.canonical_to_date('2003/04/06 00:00:00') then
2775 --
2776 hr_utility.trace(l_proc||'Condition 3 true');
2777 --
2778 if rtrim (to_char (maternity.EWC, 'DAY')) = l_sunday then
2779 hr_utility.trace(l_proc||'Condition 4 true');
2780 maternity.MPP_start_date:=
2781 (maternity.EWC - sickness_trigger_weeks);
2782 else
2783 --
2784 hr_utility.trace(l_proc||'Condition 4 untrue');
2785 --
2786 maternity.MPP_start_date :=
2787 next_day((maternity.EWC - sickness_trigger_weeks), l_sunday);
2788 end if;
2789 --
2790 else
2791 --
2792 -- Maternity due date is on or after 06-APR-2003,
2793 -- therefore start MPP on the date 4 weeks before
2794 -- EWC regardless of whether it is a Sunday
2795 --
2796 -- Bug No. 2620894: Changed the code so that MPP start date
2797 -- is the next day after first working day
2798 -- of (EWC - sickness_trigger_weeks) week.
2799 if rtrim(to_char((maternity.EWC - sickness_trigger_weeks),'DAY')) = l_sunday then
2800 maternity.MPP_start_date := (maternity.EWC - sickness_trigger_weeks) + 2;
2801 elsif rtrim(to_char ((maternity.EWC - sickness_trigger_weeks),'DAY')) = l_saturday
2802 then
2803 maternity.MPP_start_date := (maternity.EWC - sickness_trigger_weeks) + 3;
2804 else
2805 maternity.MPP_start_date := (maternity.EWC - sickness_trigger_weeks) + 1;
2806 end if;
2807 end if;
2808 --
2809 hr_utility.trace(l_proc||'About to update MPP Start Date');
2810 ssp_mat_upd.upd(p_maternity_id => maternity.maternity_id,
2811 p_MPP_start_date => maternity.MPP_start_date,
2812 p_object_version_number => maternity.object_version_number);
2813 hr_utility.trace(l_proc||'Back from updating MPP Start Date');
2814 end if;
2815 else
2816 if maternity.due_date < fnd_date.canonical_to_date('2003/04/06 00:00:00') then
2817 --
2818 -- Start the MPP on the first Sunday of the sickness
2819 -- as due date before 06-APR-2003
2820 --
2821 hr_utility.trace(l_proc||'Condition 2 untrue');
2822 if rtrim(to_char (p_sickness_start_date,'DAY')) = l_sunday then
2823 hr_utility.trace(l_proc||'Condition 5 true');
2824 first_sunday_of_sickness := p_sickness_start_date;
2825 else
2826 hr_utility.trace(l_proc||'Condition 5 untrue');
2827 first_sunday_of_sickness := next_day(p_sickness_start_date,l_sunday);
2828 end if;
2829 --
2830 -- there is no recorded MPP start date or
2831 -- the MPP start date is later than the first Sunday
2832 if (maternity.MPP_start_date is null or
2833 maternity.MPP_start_date > first_sunday_of_sickness) then
2834 --
2835 hr_utility.trace(l_proc||'Condition 6 true');
2836 --
2837 -- Update the recorded MPP start date.
2838 --
2839 maternity.MPP_start_date := first_sunday_of_sickness;
2840 --
2841 hr_utility.trace(l_proc||'About to update MPP Start Date');
2842 ssp_mat_upd.upd (p_maternity_id => maternity.maternity_id,
2843 p_MPP_start_date => maternity.MPP_start_date,
2844 p_object_version_number=> maternity.object_version_number);
2845 hr_utility.trace(l_proc||'Back from updating MPP Start Date');
2846 end if;
2847 else
2848 --
2849 -- Due date after 06-APR-2003, therefore MPP starts
2850 -- on sickness start date, regardless of whether
2851 -- it is a Sunday
2852 --
2853 -- there is no recorded MPP start date
2854 -- or the MPP_start_date is later than the
2855 -- sickness start date
2856 if (maternity.MPP_start_date is null or
2857 maternity.MPP_start_date > p_sickness_start_date) then
2858 --
2859 -- Bug No. 2620894: Changed the code so that MPP start date
2860 -- is the next day after first working day of p_sickness_start_date.
2861 if rtrim(to_char (p_sickness_start_date,'DAY')) = l_sunday then
2862 maternity.MPP_start_date := p_sickness_start_date + 2;
2863 elsif rtrim(to_char (p_sickness_start_date,'DAY')) = l_saturday then
2864 maternity.MPP_start_date := p_sickness_start_date + 3;
2865 else
2866 maternity.MPP_start_date:= p_sickness_start_date + 1;
2867 end if;
2868 --
2869 hr_utility.trace(l_proc||'About to update MPP Start Date');
2870 ssp_mat_upd.upd (p_maternity_id => maternity.maternity_id,
2871 p_MPP_start_date => maternity.MPP_start_date,
2872 p_object_version_number => maternity.object_version_number);
2873 hr_utility.trace(l_proc||'Back from updating MPP Start Date');
2874 end if;
2875 end if;
2876 end if;
2877 end if;
2878 --
2879 start_disqualifying_period := maternity.MPP_start_date;
2880 --
2881 if start_disqualifying_period is not null then
2882 hr_utility.trace(l_proc||'Condition 7 true');
2883 begin
2884 --
2885 -- The disqualifying period lasts for the period of time
2886 -- allowed by legislation for the Maternity Pay Period
2887 -- (the figure is expressed in weeks so must be converted
2888 -- to days before deriving end date).
2889 --
2890 end_disqualifying_period := start_disqualifying_period
2891 + (l_SMP_element.Maximum_MPP * 7) -1;
2892 hr_utility.trace('start_disqualifying_period : '||
2893 fnd_date.date_to_canonical(start_disqualifying_period));
2894 hr_utility.trace('end_disqualifying_period : '||
2895 fnd_date.date_to_canonical(end_disqualifying_period));
2896 --
2897 exception
2898 when attempt_to_add_to_end_of_time then
2899 --
2900 -- Handle the case where the end date would exceed the
2901 -- maximum date that Oracle can deal with.
2902 --
2903 end_disqualifying_period := hr_general.end_of_time;
2904 --
2905 end;
2906 --
2907 -- the previously calculated last entitlement day is
2908 -- not already the day before the start of the
2909 -- disqualifying period (because we have already been
2910 -- round this loop and created a stoppage before)
2911 -- and the disqualifying period overlaps with the PIW
2912 if (last_entitled_day <> start_disqualifying_period - 1 and
2913 start_disqualifying_period <= PIW_end_date and
2914 end_disqualifying_period >= PIW_start_date) then
2915 create_stoppage(p_withhold_from => start_disqualifying_period,
2916 p_reason => 'Woman in disqualifying period',
2917 p_overridden => l_stoppage_overridden);
2918 --
2919 -- the previously calculated last entitlement day is
2920 -- later than the day before the start of the
2921 -- disqualifying period
2922 -- and the withholding reason is not overridden
2923 if (last_entitled_day > start_disqualifying_period -1 and
2924 not l_stoppage_overridden) then
2925 last_entitled_day := start_disqualifying_period -1;
2926 end if;
2927 end if;
2928 end if;
2929 end loop;
2930 --
2931 hr_utility.set_location('Leaving :'||l_proc,100);
2932 --
2933 end check_disqualifying_period;
2934 --
2935 procedure check_SSP1L is
2936 l_proc varchar2 (72) := g_package||'check_SSP1L';
2937 begin
2938 --
2939 hr_utility.set_location('Entering:'||l_proc,1);
2940 --
2941 -- take prior employment SSP into account in total liability.
2942 if (PIW_start_date - absentee.prior_employment_SSP_paid_to)
2943 <= g_SSP_legislation.linking_period_days then
2944 --
2945 hr_utility.trace('There is prior employment SSP');
2946 --
2947 total_SSP_weeks := absentee.prior_employment_SSP_weeks;
2948 end if;
2949 --
2950 hr_utility.set_location('Leaving :'||l_proc,100);
2951 --
2952 end check_SSP1L;
2953 --
2954 function check_emp_too_old(p_start date,
2955 p_end date) return boolean is
2956 l_temp number;
2957 l_found boolean;
2958
2959 cursor csr_old_stp is
2960 select 1
2961 from ssp_stoppages stp,
2962 ssp_withholding_reasons rea
2963 where stp.absence_attendance_id = g_PIW_id
2964 and stp.withhold_from <= p_start
2965 and stp.withhold_to >= p_end
2966 and stp.reason_id = rea.reason_id
2967 and rea.reason = 'Employee too old';
2968 begin
2969 l_found := false;
2970 if l_age >= 65 then
2971 open csr_old_stp;
2972 fetch csr_old_stp into l_temp;
2973 if csr_old_stp%found then
2974 l_found := true;
2975 end if;
2976 close csr_old_stp;
2977 end if;
2978 return l_found;
2979 end check_emp_too_old;
2980 --
2981 begin
2982 -- Start of do_PIW_calculations
2983 hr_utility.set_location ('Entering:'||l_proc,1);
2984 --
2985 open ssp_SMP_pkg.csr_SMP_element_details(p_effective_date => PIW_start_date);
2986 fetch ssp_SMP_pkg.csr_SMP_element_details into l_SMP_element;
2987 close ssp_SMP_pkg.csr_SMP_element_details;
2988 --
2989 start_disqualifying_period := null;
2990 end_disqualifying_period := null;
2991 --
2992 check_SSP1L;
2993 --
2994 l_age := get_age_at_PIW(p_absence.person_id,l_01_October_06);
2995 --
2996 SSP_rate_figure := SSP_rate (PIW_start_date);
2997 --
2998 l_nos_absences := 0;
2999 absence_table := empty_absence_table;
3000 l_max_absence_end_date := hr_general.start_of_time;
3001 --
3002 for each_abs_tab in PIW loop
3003 l_max_absence_start_date := each_abs_tab.sickness_start_date;
3004 l_max_absence_end_date := each_abs_tab.sickness_end_date;
3005 l_nos_absences := l_nos_absences + 1;
3006 --
3007 hr_utility.trace('PIWl: dates: ' || to_char(l_max_absence_start_date)
3008 || ' -> ' || to_char(l_max_absence_end_date));
3009 --
3010 absence_table.t_sickness_start_date(l_nos_absences) :=
3011 each_abs_tab.sickness_start_date;
3012 absence_table.t_sickness_end_date(l_nos_absences) :=
3013 each_abs_tab.sickness_end_date;
3014 absence_table.t_business_group_id(l_nos_absences) :=
3015 each_abs_tab.business_group_id;
3016 absence_table.t_absence_attendance_id(l_nos_absences) :=
3017 each_abs_tab.absence_attendance_id;
3018 absence_table.t_pregnancy_related_illness(l_nos_absences) :=
3019 each_abs_tab.pregnancy_related_illness;
3020 end loop;
3021 --
3022 for each_absence in 1..l_nos_absences loop
3023 l_sickness_start_date :=
3024 absence_table.t_sickness_start_date(each_absence);
3025 l_sickness_end_date :=
3026 absence_table.t_sickness_end_date(each_absence);
3027 l_business_group_id :=
3028 absence_table.t_business_group_id(each_absence);
3029 l_absence_attendance_id :=
3030 absence_table.t_absence_attendance_id(each_absence);
3031 l_pregnancy_related_illness :=
3032 absence_table.t_pregnancy_related_illness(each_absence);
3033 --
3034 hr_utility.trace('In PIW Loop');
3035 hr_utility.trace(' for sickness dated: ' ||
3036 to_char(l_sickness_start_date) || ' -> ' ||
3037 to_char(l_sickness_end_date));
3038 --
3039 if ssp_ssp_pkg.absence_is_a_PIW (p_person_id => p_absence.person_id,
3040 p_sickness_start_date => l_sickness_start_date,
3041 p_sickness_end_date => l_sickness_end_date,
3042 p_absence_attendance_id => l_absence_attendance_id) then
3043 --
3044 -- Check for a disqualifying period from SSP because of maternity
3045 --
3046 check_disqualifying_period(p_sickness_start_date => l_sickness_start_date,
3047 p_sickness_end_date => l_sickness_end_date,
3048 p_pregnancy_related_illness => l_pregnancy_related_illness);
3049 --
3050 <<THIS_WEEK>>
3051 --
3052 -- Calculate weekly figures for SSP, accumulating the totals as we
3053 -- go so that we can find the amounts of liability both within each
3054 -- week and over all.
3055 --
3056 declare
3057 -- Bug 441738
3058 -- start_date date := next_day (each_absence.sickness_start_date,
3059 -- l_sunday) - 7;
3060 --
3061 -- Bug 502108 - start_date/end_date initialisation moved after begin.
3062 --
3063 start_date date;
3064 end_date date;
3065 SSP_rate_figure number;
3066 qualifying_days number;
3067 gross_SSP_days_due number;
3068 SSP_days_due number;
3069 withheld_days number;
3070 SSP_week_fraction number;
3071 begin
3072 start_date := l_sickness_start_date;
3073 SSP_rate_figure := SSP_rate(start_date);
3074 --
3075 -- Bug 593097 - force the end_date to be the next Saturday,
3076 -- after the Sunday before the sickness_start_date, rather
3077 -- than the Saturday after the sickness_start_date, which
3078 -- causes an error if the sickness_start_date is itself a
3079 -- Saturday.
3080 end_date := least(next_day(next_day(l_sickness_start_date,l_sunday) -7, l_saturday),
3081 nvl (rate_end_date, hr_general.end_of_time),last_entitled_day);
3082 --
3083 if start_date > last_entitled_day then
3084 -- There is a stoppage which prevents the entry creation
3085 --
3086 if start_date > max_PIW_end_date then
3087 raise PIW_max_length_reached;
3088 else
3089 raise stoppage_invoked;
3090 end if;
3091 end if;
3092 --
3093 -- Bug 504386 - Call qualifying_days_in_period for the whole sickness absence,
3094 -- so that the pl/sql table normal_pattern in hr_calendar_pkg only need be
3095 -- populated once.
3096 --
3097 -- Bug 655707 - Calling qualifying_days_in_period with PIW start/end dates, thus
3098 -- if there is more than absence then the calendar doesn't have to be rederived.
3099 --
3100 -- Bug 589806 - If an open ended absence is entered then
3101 -- each_absence.sickness_end_date is defaulted to the 'end_of_time'. Hence
3102 -- performance is terrible. Now, if the is sickness_end_date is the end_of_time
3103 -- then 203 days are added to the sickness_start_date. 203 days will allow the
3104 -- pl/sql table normal_pattern in hr_calendar_pkg to be populated with the
3105 -- dates to cover the whole open ended absence.
3106 --
3107 -- Bug 655707 - Changed 203 to be Max SSP period, unless this is null, so that
3108 -- this is not legislation specific.
3109 --
3110 cal_end_date := l_max_absence_end_date;
3111 --
3112 if cal_end_date is null or cal_end_date = hr_general.end_of_time then
3113 cal_end_date := l_max_absence_start_date +
3114 ((nvl(g_SSP_legislation.MAXIMUM_SSP_PERIOD,28) + 1) * 7);
3115 else
3116 cal_end_date := ssp_smp_support_pkg.end_of_week(l_max_absence_end_date);
3117 end if;
3118 --
3119 hr_utility.trace('Calendar end date: '||to_char(cal_end_date));
3120 cal_start_date := ssp_smp_support_pkg.start_of_week(nvl(PIW_start_date, start_date));
3121 --
3122 if cal_end_date > max_cal_end_date or
3123 cal_start_date < min_cal_start_date then
3124 all_pat_calendar_days := qualifying_days_in_period(
3125 cal_start_date, cal_end_date,
3126 p_absence.person_id,
3127 p_absence.business_group_id,
3128 p_processing_level => 1);
3129 --
3130 max_cal_end_date := cal_end_date;
3131 min_cal_start_date := cal_start_date;
3132 end if;
3133 --
3134 -- Bug 655707 - build a PL/SQL table of stoppages only once for
3135 -- each absence, so we don't have to keep calling
3136 -- csr_stoppages cursor for every single day of each
3137 -- absence. Also, if no stoppages are found for the
3138 -- whole absence then we do not have to keep calling
3139 -- qualifying_days_in_period so many times.
3140 --
3141 stoppage_table := empty_stoppage_table;
3142 l_nos_stoppages := 0;
3143 l_min_withheld_from := hr_general.end_of_time;
3144 l_max_withheld_to := hr_general.start_of_time;
3145 --
3146 for each_stoppage in csr_stoppages(PIW_start_date, cal_end_date)
3147 loop
3148 l_nos_stoppages := l_nos_stoppages + 1;
3149 stoppage_table.t_withheld_from(l_nos_stoppages):=
3150 each_stoppage.withhold_from;
3151 stoppage_table.t_withheld_to(l_nos_stoppages):=
3152 each_stoppage.withhold_to;
3153 --
3154 if each_stoppage.withhold_from < l_min_withheld_from
3155 then
3156 l_min_withheld_from := each_stoppage.withhold_from;
3157 end if;
3158 --
3159 if each_stoppage.withhold_to > l_max_withheld_to
3160 then
3161 l_max_withheld_to := each_stoppage.withhold_to;
3162 end if;
3163 end loop;
3164 --
3165 hr_utility.trace('No of stoppages between ' ||
3166 to_char(l_min_withheld_from) ||
3167 ' and ' || to_char(l_max_withheld_to) ||
3168 ': ' || to_char(l_nos_stoppages));
3169 --
3170 -- Cycle through each week of the absence until the end of the
3171 -- sickness.
3172 --
3173 -- Bug 555505 - made start_date <= rather than < each_ab.. so that
3174 -- a one day absence will be accounted for.
3175 --
3176 -- Bug 5444012 - check for total day left
3177 days_remaining := g_SSP_legislation.maximum_SSP_period * 7;
3178 days_remaining := greatest(0, days_remaining - (total_SSP_weeks * 7));
3179 --
3180 while start_date <= l_sickness_end_date loop
3181 N := N + 1;
3182 --
3183 -- Find number of qualifying days in the current calendar week.
3184 --
3185 hr_utility.trace('Finding qualifying days in current week...');
3186 qualifying_days := greatest (1,qualifying_days_in_period(
3187 ssp_smp_support_pkg.start_of_week(start_date),
3188 ssp_smp_support_pkg.end_of_week(start_date),
3189 p_absence.person_id,
3190 p_absence.business_group_id,
3191 p_processing_level => 2));
3192 --
3193 if weeks_remaining <= 1 then
3194 --
3195 -- We are in the final week of the employer's SSP liability.
3196 -- We must work out how many days of liability remain.
3197 --
3198 days_remaining := ceil(weeks_remaining /
3199 ---------------------------------------
3200 standard_week_fraction (qualifying_days));
3201 --
3202 -- Now drag the end date back to the date on which
3203 -- SSP ceases to be payable.
3204 --
3205 while qualifying_days_in_period(start_date,
3206 end_date,
3207 p_absence.person_id,
3208 p_absence.business_group_id,
3209 p_processing_level => 2) > days_remaining loop
3210 end_date := end_date -1;
3211 end loop;
3212 --
3213 end if;
3214 --
3215 -- Calculate the number of qualifying days the person was sick.
3216 --
3217 -- Calculate the absent qualifying days.
3218 --
3219 -- The gross number of SSP days due is the number of qualifying
3220 -- days in the period of absence being examined.
3221 --
3222 gross_SSP_days_due :=
3223 qualifying_days_in_period(
3224 greatest (start_date,
3225 l_sickness_start_date),
3226 least (end_date,
3227 l_sickness_end_date),
3228 p_absence.person_id,
3229 p_absence.business_group_id,
3230 p_processing_level => 2);
3231 --
3232 -- Calculate how many of the qualifying days were covered by a
3233 -- waiting day or temporary stoppage. NB withheld_days do not
3234 -- include waiting days but the calculation of waiting days is
3235 -- done within the stopped_days function and stored in a
3236 -- variable.
3237 --
3238 perf_start_date := greatest(start_date, l_sickness_start_date);
3239 perf_end_date := least(end_date, l_sickness_end_date);
3240 waiting_days_this_period := 0;
3241 --
3242 if (l_nos_stoppages > 0 and
3243 perf_start_date <= l_max_withheld_to and
3244 perf_end_date >= l_min_withheld_from)
3245 or waiting_days_left > 0
3246 then
3247 withheld_days := stopped_days(perf_start_date,
3248 perf_end_date,
3249 p_absence.person_id);
3250 else
3251 withheld_days := 0;
3252 end if;
3253 --
3254 SSP_days_due := gross_SSP_days_due - withheld_days;
3255 --
3256 -- Calculate the fraction of an SSP week which this week's absence
3257 -- constitutes
3258 --
3259 if SSP_days_due >= days_remaining then
3260 --
3261 -- We must have done the final week calculations and found that
3262 -- the absentee was sick for as long or longer than the period
3263 -- for which SSP is payable. Make this week's fraction equal
3264 -- the weeks remaining so that we come to exactly the correct
3265 -- total_SSP_weeks figure.
3266 --
3267 SSP_week_fraction := g_SSP_legislation.maximum_SSP_period - total_SSP_weeks;
3268 else
3269 SSP_week_fraction := (SSP_days_due - waiting_days_this_period) /
3270 -----------------------------------------
3271 qualifying_days;
3272 end if;
3273 --
3274 -- Find the daily rate by dividing the weekly SSP rate by the
3275 -- number of qualifying days in the calendar week.
3276 --
3277 daily_rate := SSP_rate (this_week.start_date)/
3278 --------------------------------
3279 qualifying_days;
3280 --
3281 -- Determine which payroll period to put the new entry in
3282 --
3283 -- Initialise in/out parameters to get_entry_details procedure
3284 --
3285 new_entry.assignment_id (N) := null;
3286 new_entry.element_link_id (N) := null;
3287 --
3288 ssp_smp_support_pkg.get_entry_details(p_date_earned => this_week.start_date,
3289 /*p_date_earned => this_week.end_date,*/
3290 p_last_process_date => absentee.last_standard_process_date,
3291 p_person_id => p_absence.person_id,
3292 p_element_type_id => g_SSP_legislation.element_type_id,
3293 p_assignment_id => new_entry.assignment_id (N),
3294 p_element_link_id => new_entry.element_link_id (N),
3295 p_effective_start_date => new_entry.effective_start_date (N),
3296 p_effective_end_date => new_entry.effective_end_date (N));
3297 --
3298 -- Store this week's figures in the hypothetical entry
3299 --
3300 new_entry.date_from(N) := greatest (this_week.start_date,l_sickness_start_date);
3301 new_entry.date_to(N) := least (this_week.end_date,l_sickness_end_date);
3302 new_entry.qualifying_days(N) := this_week.gross_SSP_days_due;
3303 new_entry.SSP_weeks(N) := round (this_week.SSP_week_fraction,3);
3304 new_entry.SSP_days_due(N) := this_week.gross_SSP_days_due - waiting_days_this_period;
3305 new_entry.withheld_days(N) := this_week.withheld_days;
3306 new_entry.rate(N) := SSP_rate (this_week.start_date);
3307 new_entry.amount(N) := round (((SSP_days_due - waiting_days_this_period)
3308 * daily_rate)+0.004,2);
3309 new_entry.dealt_with(N) := 'FALSE';
3310 --
3311 if check_emp_too_old(l_sickness_start_date, l_sickness_end_date) then
3312 total_SSP_weeks := total_SSP_weeks + (this_week.withheld_days/qualifying_days);
3313 end if;
3314 --
3315 -- Increment the total of SSP weeks by this week's figures.
3316 --
3317 total_SSP_weeks := total_SSP_weeks + SSP_week_fraction;
3318 weeks_remaining := g_SSP_legislation.maximum_SSP_period - total_SSP_weeks;
3319 --
3320 -------------------------------------------------
3321 -- Trace the calculations for debugging purposes
3322 begin
3323 hr_utility.trace ('----------------------------');
3324 hr_utility.trace (l_proc||'Entry number ' ||to_char (N));
3325 hr_utility.trace (l_proc||' Payroll period '||to_char (new_entry.effective_start_date (N)) ||' to '
3326 ||to_char (new_entry.effective_end_date (N)));
3327 hr_utility.trace (l_proc||' from = '||to_char (new_entry.date_from (N))||' to = ' ||to_char ( new_entry.date_to (N)));
3328 hr_utility.trace (l_proc||' qualifying_days = '||to_char (new_entry.qualifying_days (N)));
3329 hr_utility.trace (l_proc||' SSP_weeks = '||to_char (new_entry.SSP_weeks (N)));
3330 hr_utility.trace (l_proc||' SSP_days_due = '||to_char (new_entry.SSP_days_due (N)));
3331 hr_utility.trace (l_proc||' withheld_days = '||to_char (new_entry.withheld_days (N)));
3332 hr_utility.trace (l_proc||' rate = '||to_char (new_entry.rate (N)));
3333 hr_utility.trace (l_proc||' amount ' || to_char (daily_rate)
3334 ||' ( ' || to_char (new_entry.SSP_days_due (N))
3335 ||' - ' || to_char (new_entry.withheld_days (N))
3336 ||') = '|| to_char (new_entry.amount (N)));
3337 hr_utility.trace (l_proc||' Total SSP weeks = '||to_char (total_ssp_weeks));
3338 hr_utility.trace (l_proc||' weeks remaining = '||to_char (weeks_remaining));
3339 hr_utility.trace (l_proc||' waiting_days_left = '||to_char (waiting_days_left));
3340 hr_utility.trace (l_proc||' waiting_days_this_period = '||to_char (waiting_days_this_period));
3341 hr_utility.trace (l_proc||' Element_link_id = '||to_char (new_entry.element_link_id (N)));
3342 hr_utility.trace (l_proc||' Assignment_id = '||to_char (new_entry.assignment_id (N)));
3343 hr_utility.trace ('----------------------------');
3344 exception
3345 when not_logged_on or program_error or storage_error then
3346 -- a serious error must be indicated.
3347 raise;
3348 when others then
3349 -- Do not let minor errors in debugging code stop the process
3350 null;
3351 end;
3352 hr_utility.trace ('Weeks remaining:'||to_char(weeks_remaining));
3353 hr_utility.trace (' end date :'||to_char(end_date));
3354 hr_utility.trace (' last ent day :'||to_char(last_entitled_day));
3355 --
3356 --if weeks_remaining <= 0 then --old line
3357 if weeks_remaining <= 0.00000000000000000000000000000000000001 then --line added for bug 6860926
3358 raise maximum_SSP_paid;
3359 end if;
3360 --
3361 if end_date = last_entitled_day then
3362 -- Stop processing SSP if we have reached the date when a
3363 -- stoppage precludes any further payment.
3364 --
3365 -- bug 2984845 - check if entitlement has ended due to
3366 -- max PIW length being reached
3367 -- the original check will never work as
3368 -- end_date will never equal max_piw_end_date
3369 -- so check if max PIW end date between start and end
3370 -- dates of current sickness
3371 -- IF end_date = max_piw_end_date
3372 --
3373 -- Bug 2984458 Added condition to check if max_piw_end_date
3374 -- is less than Actual Termination Date to raise the exception
3375 if ((max_piw_end_date between l_sickness_start_date and l_sickness_end_date) and
3376 (max_piw_end_date < absentee.actual_termination_date)) then
3377 raise piw_max_length_reached;
3378 else
3379 raise stoppage_invoked;
3380 end if;
3381 end if;
3382 --
3383 -- Move on to the next week of absence.
3384 --
3385 if rate_end_date between start_date and end_date then
3386 --
3387 -- The SSP rate changes during this week so we move on to
3388 -- the latter part of the week for the new rate.
3389 --
3390 start_date := rate_end_date + 1;
3391 --
3392 -- The end of the next period to be examined is the lesser of
3393 -- the end of the week and the first permanent stoppage date.
3394 --
3395 end_date := least (ssp_smp_support_pkg.end_of_week (start_date),
3396 last_entitled_day);
3397 --
3398 else
3399 --
3400 -- There is no rate change during the current week, but there
3401 -- may be one next week so move the dates to the beginning
3402 -- of next week and the greater of the rate end date and the
3403 -- calendar week end date and the withholding date.
3404 --
3405 start_date := next_day (start_date, l_sunday);
3406 end_date := least (next_day (start_date,l_saturday),
3407 nvl (rate_end_date,hr_general.end_of_time),
3408 nvl (last_entitled_day,hr_general.end_of_time));
3409 end if;
3410 --
3411 end loop;
3412 end;
3413 end if;
3414 end loop;
3415 --
3416 hr_utility.set_location('Leaving :'||l_proc,100);
3417 --
3418 exception
3419 when stoppage_invoked then
3420 --
3421 -- Stop processing SSP as we have reached the end of the entitlement.
3422 --
3423 null;
3424 --
3425 when maximum_SSP_paid then
3426 create_stoppage(p_withhold_from => new_entry.date_to (N) + 1,
3427 p_reason => 'Maximum weeks SSP paid',
3428 p_overridden => l_stoppage_overridden);
3429 --
3430 when PIW_max_length_reached then
3431 create_stoppage(p_withhold_from => max_PIW_end_date,
3432 p_reason => 'PIW lasted maximum time',
3433 p_overridden => l_stoppage_overridden);
3434 --
3435 when zero_divide then
3436 --
3437 -- One of the calculations must have gone wrong
3438 --
3439 fnd_message.set_name ('PAY','HR_6153_ALL_PROCEDURE_FAIL');
3440 fnd_message.set_token ('PROCEDURE',l_proc);
3441 fnd_message.set_token ('STEP','1');
3442 fnd_message.raise_error;
3443 --
3444 end do_PIW_calculations;
3445 --
3446 /*-------------------------------------------------------*/
3447 /* Check that the person earns enough to qualify for SSP */
3448 /*-------------------------------------------------------*/
3449 procedure check_average_earnings is
3450 --
3451 -- Get the defined average earnings
3452 --
3453 cursor csr_average_earnings is
3454 select average_earnings_amount
3455 from ssp_earnings_calculations
3456 where person_id = p_absence.person_id
3457 and effective_date = PIW_start_date;
3458 --
3459 l_proc varchar2(72):= g_package||'check_average_earnings';
3460 l_average_earnings number := null;
3461 l_dummy number;
3462 l_dummy2 number; -- nocopy fix, placeholder variable
3463 l_payment_periods number := null; --DFoster 1304683
3464 l_absence_category varchar2(30) := 'S'; --DFoster
3465 l_user_entered varchar2(30); --DFoster 1304683
3466 l_reason_for_no_earnings varchar2 (80);
3467 l_stoppage_overridden boolean := FALSE;
3468 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
3469 l_PIW_date date;
3470 begin
3471 hr_utility.set_location('Entering:'||l_proc,1);
3472 --
3473 -- Look on the table for previously-calculated earnings figure
3474 --
3475 open csr_average_earnings;
3476 fetch csr_average_earnings into l_average_earnings;
3477 --
3478 -- No average earnings are recorded
3479 if csr_average_earnings%notfound then
3480 --
3481 -- Calculate and save the average earnings.
3482 --
3483 ssp_ern_ins.ins(p_earnings_calculations_id => l_dummy,
3484 p_object_version_number => l_dummy2,
3485 p_person_id => p_absence.person_id,
3486 p_effective_date => PIW_start_date,
3487 p_average_earnings_amount => l_average_earnings,
3488 p_user_entered => l_user_entered, --1304683
3489 p_absence_category => l_absence_category, --1304683
3490 p_payment_periods => l_payment_periods); --1304683
3491 --
3492 end if;
3493 --
3494 close csr_average_earnings;
3495 --
3496 if l_average_earnings = 0 then
3497 --
3498 -- If the average earnings figure returned is zero then we must
3499 -- check that no error message was set. Error messages will be set
3500 -- for system-generated average earnings when the earnings could not
3501 -- be derived for some reason, but to allow this procedure to
3502 -- continue, no error will be raised.
3503 --
3504 l_reason_for_no_earnings :=ssp_smp_support_pkg.average_earnings_error;
3505 --
3506 if l_reason_for_no_earnings is not null then
3507 create_stoppage (p_withhold_from => PIW_start_date,
3508 p_reason => l_reason_for_no_earnings,
3509 p_overridden => l_stoppage_overridden);
3510 --
3511 if not l_stoppage_overridden then
3512 raise earnings_too_low;
3513 end if;
3514 end if;
3515 end if;
3516 --
3517 -- the average earnings are lower than the NI Lower Earnings Limit
3518 if l_average_earnings < ssp_smp_support_pkg.NI_Lower_Earnings_Limit(PIW_start_date) then
3519 --
3520 -- The person does not earn enough to qualify for SSP
3521 --
3522 create_stoppage (p_withhold_from => PIW_start_date,
3523 p_reason => 'Earnings too low',
3524 p_overridden => l_stoppage_overridden);
3525 --
3526 if not l_stoppage_overridden then
3527 raise earnings_too_low;
3528 end if;
3529 end if;
3530 --
3531 hr_utility.set_location('Leaving :'||l_proc,100);
3532 --
3533 end check_average_earnings;
3534 --
3535 /*----------------------------------------*/
3536 /* Check for medical evidence of sickness */
3537 /*----------------------------------------*/
3538 procedure check_evidence is
3539
3540 --
3541 -- Return a row if evidence exists.
3542 cursor csr_evidence (c_absence_id number) is
3543 select 1
3544 from ssp_medicals
3545 where absence_attendance_id = c_absence_id
3546 and evidence_status = 'CURRENT';
3547 --
3548 -- Returns the setting of the flag which notes the user's
3549 -- requirement for medical evidence
3550 cursor csr_user_requirement (c_business_id number) is
3551 select org_information1 EVIDENCE_REQUIRED
3552 from hr_organization_information
3553 where organization_id = c_business_id
3554 and org_information_context = 'Sickness Control Rules';
3555 --
3556 l_proc varchar2(72):= g_package||'check_evidence';
3557 l_evidence_required varchar2 (30) := 'N';
3558 l_dummy integer (1);
3559 l_stoppage_overridden boolean := FALSE;
3560 --
3561 begin
3562 hr_utility.set_location('Entering:'||l_proc,1);
3563 --
3564 /*BUG 2984577- Added code to handle linked absences.*/
3565 for each_absence in PIW loop
3566 -- Determine whether or not the user requires medical evidence of
3567 -- incapacity to be presented by employees
3568 --
3569 open csr_user_requirement(each_absence.business_group_id);
3570 fetch csr_user_requirement into l_evidence_required;
3571 close csr_user_requirement;
3572 --
3573 -- the user requires medical evidence of incapacity
3574 if l_evidence_required = 'Y' then
3575 --
3576 -- Look for a sick note.
3577 open csr_evidence(each_absence.absence_attendance_id);
3578 fetch csr_evidence into l_dummy;
3579 hr_utility.set_location('Entering:'||l_dummy,5555);
3580 --
3581 -- no medical evidence was found for this absence
3582 if csr_evidence%notfound then
3583 /*BUG 2984577 Added exception */
3584 if each_absence.sickness_end_date = hr_general.end_of_time then
3585 create_stoppage (p_withhold_from => each_absence.sickness_start_date,
3586 p_reason => 'No acceptable evidence in time',
3587 p_overridden => l_stoppage_overridden);
3588 last_entitled_day := least(last_entitled_day,each_absence.sickness_start_date - 1);
3589 else
3590 create_stoppage (p_withhold_from => each_absence.sickness_start_date,
3591 p_withhold_to => each_absence.sickness_end_date,
3592 p_reason => 'No acceptable evidence in time',
3593 p_overridden => l_stoppage_overridden);
3594 end if;
3595 --
3596 end if;
3597 close csr_evidence;
3598 end if;
3599 end loop;
3600 --
3601 hr_utility.set_location('Leaving :'||l_proc,100);
3602 --
3603 end check_evidence;
3604 --
3605 /*--------------------------------------------------------------*/
3606 /* Check that the person's period of service is long enough to */
3607 /* qualify for SSP */
3608 /*--------------------------------------------------------------*/
3609 procedure check_service is
3610 l_stoppage_overridden boolean := FALSE;
3611 l_proc varchar2 (72) := g_package||'check_service';
3612 begin
3613 --
3614 hr_utility.set_location('Entering:'||l_proc,1);
3615 -- the employment is scheduled to end
3616 -- bug 2984458 to avoid displaying 'Contract ends' when
3617 -- employee is deceased
3618 if (absentee.actual_termination_date < hr_general.end_of_time) and
3619 nvl(absentee.leaving_reason,'No Reason') <>'D' then -- Only If termination reason is 'Death' then this stoppage should be not generated.
3620 create_stoppage(p_withhold_from => absentee.actual_termination_date +1,
3621 p_reason => 'Contract ends',
3622 p_overridden => l_stoppage_overridden);
3623 end if;
3624 --
3625 hr_utility.set_location('Leaving :'||l_proc,100);
3626 --
3627 end check_service;
3628 --
3629 /*-----------------------------------------------------------*/
3630 /* Check that if the person has a DSS linking letter and if */
3631 /* so, is the end date after the start date of current PIW ? */
3632 /*-----------------------------------------------------------*/
3633 procedure check_linking_letter is
3634 l_stoppage_overridden boolean := FALSE;
3635 l_proc varchar2(80) := g_package||'check_linking_letter';
3636 --
3637 -- Get current linking letter end date off the person record
3638 cursor csr_link_letter is
3639 select fnd_date.canonical_to_date(ppf.per_information11)
3640 from per_all_people_f ppf
3641 where ppf.person_id = p_absence.person_id
3642 and ppf.per_information_category = 'GB'
3643 and sysdate between ppf.effective_start_date and ppf.effective_end_date;
3644
3645 l_link_letter_end_date date;
3646 --
3647 begin
3648 --
3649 hr_utility.set_location('Entering:'||l_proc,1);
3650 --
3651 open csr_link_letter;
3652 fetch csr_link_letter into l_link_letter_end_date;
3653 close csr_link_letter;
3654
3655 hr_utility.trace('Linking letter end date: '||l_link_letter_end_date);
3656 --
3657 -- check if link letter end date is after start date of current PIW
3658 if l_link_letter_end_date is not null and
3659 l_link_letter_end_date > PIW_start_date then
3660 -- create stoppage from the start of the current PIW to the end
3661 create_stoppage(p_withhold_from => PIW_start_date,
3662 p_withhold_to => PIW_end_date,
3663 p_reason => 'Linking letter',
3664 p_overridden => l_stoppage_overridden);
3665 end if;
3666 --
3667 hr_utility.set_location('Leaving :'||l_proc,100);
3668 --
3669 end check_linking_letter;
3670 --
3671 --
3672 begin
3673 --
3674 -- Start of Entitled_to_SSP
3675 --
3676 hr_utility.set_location('Entering:'||l_proc,1);
3677 --
3678 new_entry := empty_record;
3679 --
3680 -- SSP not installed or the absence is not sick leave
3681 if ((not SSP_is_installed) or p_absence.sickness_start_date is null) then
3682 raise no_prima_facia_entitlement;
3683 else
3684 --
3685 -- Get details of the absentee
3686 --
3687 open csr_person (p_absence.sickness_start_date, p_absence.person_id);
3688 fetch csr_person into absentee;
3689 --
3690 -- the person does not exist or has no current period of service
3691 if csr_person%notfound then
3692 close csr_person;
3693 raise no_prima_facia_entitlement;
3694 end if;
3695 --
3696 close csr_person;
3697 --
3698 -- Calculate the start and end of the linked series of PIWs.
3699 --
3700 PIW_start_date := linked_PIW_start_date (p_absence.person_id,
3701 p_absence.sickness_start_date,
3702 p_absence.sickness_end_date,
3703 p_absence.absence_attendance_id);
3704 --
3705 hr_utility.trace('Piw_start_date ' || to_char(PIW_start_date,'DD-MON-YYYY'));
3706 --
3707 -- The absence passed in is not a PIW
3708 if PIW_start_date is null then
3709 -- Start Bug 418895 fixing
3710 --
3711 -- Set paramenters to delete all the associated entries
3712 --
3713 g_PIW_id := p_absence.absence_attendance_id;
3714 new_entry := empty_record;
3715 PIW_start_date := p_absence.sickness_start_date;
3716 PIW_end_date := hr_general.end_of_time;
3717 --
3718 -- Delete stoppages
3719 --
3720 for obsolete_stoppage in csr_old_stoppages loop
3721 ssp_stp_del.del(p_stoppage_id => obsolete_stoppage.stoppage_id,
3722 p_object_version_number => obsolete_stoppage.object_version_number);
3723 end loop;
3724 -- End Bug 418895 fixing
3725 raise no_prima_facia_entitlement;
3726 end if;
3727 --
3728 PIW_end_date := nvl (linked_PIW_end_date (p_absence.person_id,
3729 p_absence.sickness_start_date,
3730 p_absence.sickness_end_date,
3731 p_absence.absence_attendance_id),
3732 hr_general.end_of_time);
3733 --
3734 hr_utility.trace('Piw_end_date ' || to_char(PIW_end_date,'DD-MON-YYYY'));
3735 --
3736 g_PIW_id := nvl(p_absence.linked_absence_id,p_absence.absence_attendance_id);
3737 --
3738 hr_utility.trace('Piw_id ' || to_char(g_PIW_id));
3739 --
3740 -- Get the legislative parameters for SSP
3741 --
3742 get_SSP_element (p_absence.sickness_start_date);
3743 --
3744 max_PIW_end_date := add_months (PIW_start_date,(12 * g_SSP_legislation.maximum_linked_PIW_years));
3745 --
3746 -- Remove any previously created stoppages (excluding user-entered ones and
3747 -- overridden ones)
3748 --
3749 for obsolete_stoppage in csr_old_stoppages loop
3750 --
3751 -- Delete stoppage
3752 --
3753 ssp_stp_del.del(p_stoppage_id => obsolete_stoppage.stoppage_id,
3754 p_object_version_number => obsolete_stoppage.object_version_number);
3755 end loop;
3756 --
3757 get_last_entitled_day;
3758 --
3759 if last_entitled_day < p_absence.sickness_start_date then
3760 --
3761 -- The PIW is after a permanent stoppage
3762 --
3763 raise no_prima_facia_entitlement;
3764 end if;
3765 --
3766 -- Check entitlement to SSP
3767 --
3768 check_service;
3769 check_age;
3770 check_death;
3771 check_average_earnings;
3772 check_evidence;
3773 check_linking_letter;
3774 --
3775 -- Work out the amounts of SSP due in entries covering approx. one week each.
3776 --
3777 do_PIW_calculations;
3778 --
3779 hr_utility.set_location('Leaving :'||l_proc,100);
3780 --
3781 -- If we have got this far then the person is entitled to SSP
3782 -- (though stoppages may apply).
3783 --
3784 return TRUE;
3785 end if;
3786 exception
3787 when no_prima_facia_entitlement or employee_too_old or
3788 earnings_too_low or evidence_not_available then
3789 hr_utility.set_location('Leaving :'||l_proc||', Exception',999);
3790 --
3791 return FALSE; -- employee not entitled to SSP
3792 --
3793 end entitled_to_SSP;
3794 --------------------------------------------------------------------------------
3795 procedure generate_payments (p_entitled_to_SSP in boolean) is
3796 --
3797 -- Turn SSP entries in the internal data structure into actual element entries.
3798 -- Take account of entries which have already been created for the PIW.
3799 --
3800 cursor csr_existing_entries is
3801 --
3802 -- The entries previously created for this PIW
3803 --
3804 select entry.element_entry_id,
3805 entry.element_link_id,
3806 entry.assignment_id,
3807 entry.effective_start_date,
3808 entry.effective_end_date,
3809 max(decode(inp.name,c_rate_name,
3810 to_number(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom,
3811 g_SSP_correction.input_currency_code)),null)) RATE,
3812 /* Use the SSP_correction's input_currency_code as *
3813 * the SSP_legislation global may not be populated */
3814 -------------------------------------------------------------------------
3815 -- Changes for bug 1020757: --
3816 -- --
3817 -- The changeformat function will return the screen_entry_value in the --
3818 -- external display format. This is not always 'DD-MON-YYYY' so that --
3819 -- should not be hardcoded. Better to use fnd_date.chardate_to_date --
3820 -- which will convert the display format to a date. --
3821 -- This will fix bug 1020757. --
3822 -------------------------------------------------------------------------
3823 /* max(decode(inp.name,c_from_name, */
3824 /* to_date(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom, */
3825 /* g_SSP_correction.input_currency_code),'DD-MON-YYYY'),null)) DATE_FROM, */
3826 /* max(decode(inp.name,c_to_name, */
3827 /* to_date(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom, */
3828 /* g_SSP_correction.input_currency_code),'DD-MON-YYYY'),null)) DATE_TO, */
3829 max(decode(inp.name,c_from_name,
3830 fnd_date.chardate_to_date(hr_chkfmt.changeformat(eev.screen_entry_value,
3831 inp.uom,g_SSP_correction.input_currency_code)),null)) DATE_FROM,
3832 max(decode(inp.name,c_to_name,
3833 fnd_date.chardate_to_date(hr_chkfmt.changeformat(eev.screen_entry_value,
3834 inp.uom,g_SSP_correction.input_currency_code)),null)) DATE_TO,
3835 -- End of Changes for bug 1020757
3836 ------------------------------------------------------------------------
3837 max(decode(inp.name,c_amount_name,
3838 to_number(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom,
3839 g_SSP_correction.input_currency_code)),null)) AMOUNT,
3840 max(decode(inp.name,c_withheld_days_name,
3841 to_number(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom,
3842 g_SSP_correction.input_currency_code)),null)) WITHHELD_DAYS,
3843 max(decode(inp.name,c_SSP_weeks_name,
3844 to_number(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom,
3845 g_SSP_correction.input_currency_code)),null)) SSP_WEEKS,
3846 max(decode(inp.name,c_SSP_days_due_name,
3847 to_number(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom,
3848 g_SSP_correction.input_currency_code)),null)) SSP_DAYS_DUE,
3849 max(decode(inp.name,c_qualifying_days_name,
3850 to_number(hr_chkfmt.changeformat(eev.screen_entry_value,inp.uom,
3851 g_SSP_correction.input_currency_code)),null)) QUALIFYING_DAYS
3852 from pay_input_values_f inp,
3853 pay_element_entry_values_f eev,
3854 pay_element_entries_f ENTRY,
3855 per_all_assignments_f ASGT /* adding this join speeds up the entry query */
3856 where creator_type = c_SSP_creator_type
3857 and creator_id = g_PIW_id
3858 and asgt.person_id = absentee.person_id
3859 and asgt.assignment_id = entry.assignment_id
3860 and entry.effective_start_date between asgt.effective_start_date
3861 and asgt.effective_end_date
3862 and eev.element_entry_id = entry.element_entry_id
3863 and eev.effective_start_date between entry.effective_start_date
3864 and entry.effective_end_date
3865 and eev.input_value_id +0 = inp.input_value_id
3866 and inp.name in (c_rate_name,c_from_name,c_to_name,c_amount_name,
3867 c_withheld_days_name,c_SSP_weeks_name,
3868 c_SSP_days_due_name,c_qualifying_days_name)
3869 and inp.effective_start_date <= eev.effective_end_date
3870 and inp.effective_end_date >= eev.effective_start_date
3871 and not exists (
3872 /* Do not select entries which have already had reversal action *
3873 * taken against them because they are effectively cancelled out */
3874 select 1
3875 from pay_element_entries_f ENTRY2
3876 where entry.element_entry_id = entry2.target_entry_id
3877 and entry.assignment_id = entry2.assignment_id)
3878 and inp.element_type_id <> g_SSP_correction.element_type_id
3879 /* Do not select reversal entries */
3880 group by entry.element_entry_id, entry.element_link_id, entry.assignment_id,
3881 entry.effective_start_date, entry.effective_end_date;
3882 --
3883 l_proc varchar2 (72) := g_package||'generate_payments';
3884 l_invalid_entry boolean;
3885 l_dummy number;
3886 Y integer := 0;
3887 --
3888 begin
3889 --
3890 hr_utility.set_location('Entering:'||l_proc,1);
3891 hr_utility.trace(l_proc||' PIW_START_DATE:'||PIW_start_date);
3892 --
3893 if PIW_start_date is not null
3894 then
3895 -- begin
3896 -- Y:=0;
3897 -- loop
3898 -- Y:=Y+1;
3899 -- hr_utility.trace('NEW ENTRY '||to_char(Y));
3900 -- hr_utility.trace(' Date From: '||to_char(new_entry.date_from(Y)));
3901 -- hr_utility.trace(' Date To : '||to_char(new_entry.date_to(Y)));
3902 -- hr_utility.trace(' Amount : '||to_char(new_entry.amount(Y)));
3903 -- hr_utility.trace(' Days Due : '||to_char(new_entry.ssp_days_due(Y)));
3904 -- hr_utility.trace(' Weeks : '||to_char(new_entry.ssp_weeks(Y)));
3905 -- hr_utility.trace(' Withheld : '||to_char(new_entry.withheld_days(Y)));
3906 -- hr_utility.trace(' Rate : '||to_char(new_entry.rate(Y)));
3907 -- end loop;
3908 -- --
3909 -- exception
3910 -- when no_data_found then
3911 -- null;
3912 -- end;
3913 --
3914 hr_utility.set_location(l_proc,2);
3915 get_SSP_correction_element (PIW_start_date);
3916 hr_utility.set_location(l_proc,3);
3917 --
3918 -- Check each existing SSP entry in turn against all the potential new ones.
3919 --
3920 <<OLD_ENTRIES>>
3921 for old_entry in csr_existing_entries
3922 LOOP
3923 hr_utility.trace(l_proc||'OLD ENTRY');
3924 hr_utility.trace(l_proc||'Ele_entryid: '||to_char(old_entry.element_entry_id));
3925 hr_utility.trace(l_proc||'Ele_link_id: '||to_char(old_entry.element_link_id));
3926 hr_utility.trace(l_proc||'Assgment_id: '||to_char(old_entry.assignment_id));
3927 hr_utility.trace(l_proc||'Eff_star_dt: '||to_char(old_entry.effective_start_date));
3928 hr_utility.trace(l_proc||' Eff_end_dt: '||to_char(old_entry.effective_end_date));
3929 hr_utility.trace(l_proc||' Date From: '||to_char(old_entry.date_from));
3930 hr_utility.trace(l_proc||' Date To : '||to_char(old_entry.date_to));
3931 hr_utility.trace(l_proc||' Amount : '||to_char(old_entry.amount));
3932 hr_utility.trace(l_proc||' Days Due : '||to_char(old_entry.ssp_days_due));
3933 hr_utility.trace(l_proc||' Weeks : '||to_char(old_entry.ssp_weeks));
3934 hr_utility.trace(l_proc||' Withheld : '||to_char(old_entry.withheld_days));
3935 hr_utility.trace(l_proc||' Rate : '||to_char(old_entry.rate));
3936 --
3937 -- See if the existing entry exactly matches one we are going to insert.
3938 -- If it does, then we do not need to change it or insert the new one.
3939 -- If there is no exact match, then we must reverse the existing entry.
3940 --
3941 l_invalid_entry := FALSE;
3942 --
3943 <<FIND_MATCH>>
3944 begin
3945 Y := 0;
3946 --
3947 LOOP
3948 Y := Y + 1;
3949 --
3950 exit when (old_entry.date_from = new_entry.date_from (Y) and
3951 old_entry.date_to = new_entry.date_to (Y) and
3952 old_entry.amount = new_entry.amount (Y) and
3953 old_entry.ssp_days_due = new_entry.ssp_days_due (Y) and
3954 old_entry.ssp_weeks = new_entry.ssp_weeks (Y) and
3955 old_entry.withheld_days = new_entry.withheld_days (Y) and
3956 old_entry.rate = new_entry.rate (Y));
3957 end loop;
3958 --
3959 exception
3960 when no_data_found then
3961 --
3962 -- There was no new entry which exactly matched the old entry.
3963 --
3964 l_invalid_entry := TRUE;
3965 --
3966 end;
3967 --
3968 if not l_invalid_entry then
3969 --
3970 -- The existing entry is OK so leave it alone. Simply mark the new one
3971 -- so that we do not attempt to insert it.
3972 --
3973 new_entry.dealt_with (Y) := 'TRUE';
3974 hr_utility.trace(l_proc||' Inside not l_invalid_entry');
3975 else
3976 --
3977 -- The existing entry has been superseded by a new one.
3978 --
3979 hr_utility.set_location(l_proc,5);
3980 if (ssp_smp_support_pkg.entry_already_processed(old_entry.element_entry_id))
3981 then
3982 --
3983 -- The processed entry must be reversed, its values are superseded.
3984 --
3985 -- Insert an entry for SSP correction element in the next payroll
3986 -- period, with the old entry's amounts reversed in sign so that it
3987 -- will cancel out the old entry.
3988 --
3989 --Changed the last_process_date to FINAL_PROCESS_DATE for debug purpose
3990 hr_utility.set_location(l_proc,6);
3991 ssp_smp_support_pkg.get_entry_details (
3992 p_date_earned => old_entry.date_from,
3993 p_person_id => absentee.person_id,
3994 p_last_process_date => absentee.final_process_date, /*7688727 changed from LSP date to FPD */
3995 p_element_type_id => g_SSP_correction.element_type_id,
3996 p_element_link_id => old_entry.element_link_id,
3997 p_assignment_id => old_entry.assignment_id,
3998 p_effective_start_date => old_entry.effective_start_date,
3999 p_effective_end_date => old_entry.effective_end_date);
4000 --
4001 hr_utility.set_location(l_proc,20);
4002 hr_utility.trace(l_proc||' OLD: Before calling hr_entry_api.insert_element_entry');
4003 hr_utility.trace(l_proc||' old_entry.effective_start_date'||old_entry.effective_start_date);
4004 hr_utility.trace(l_proc||' old_entry.effective_end_date'||old_entry.effective_end_date);
4005 --
4006 hr_entry_api.insert_element_entry (
4007 p_effective_start_date => old_entry.effective_start_date,
4008 p_effective_end_date => old_entry.effective_end_date,
4009 p_element_entry_id => l_dummy,
4010 p_target_entry_id => old_entry.element_entry_id,
4011 p_assignment_id => old_entry.assignment_id,
4012 p_element_link_id => old_entry.element_link_id,
4013 p_creator_type => c_SSP_creator_type,
4014 p_creator_id => g_PIW_id,
4015 p_entry_type => 'E',
4016 p_input_value_id1 => g_SSP_correction.rate_id,
4017 p_input_value_id2 => g_SSP_correction.from_id,
4018 p_input_value_id3 => g_SSP_correction.to_id,
4019 p_input_value_id4 => g_SSP_correction.amount_id,
4020 p_input_value_id5 => g_SSP_correction.withheld_days_id,
4021 p_input_value_id6 => g_SSP_correction.SSP_weeks_id,
4022 p_input_value_id7 => g_SSP_correction.SSP_days_due_id,
4023 p_input_value_id8 => g_SSP_correction.qualifying_days_id,
4024 p_entry_value1 => old_entry.rate,
4025 -- The following two lines will implicitly convert the dates
4026 -- to varchar values. This will use the default format (NLS
4027 -- setting) for a date which is what the date_from and
4028 -- data_to UoM is set to in 11i (=Date).
4029 p_entry_value2 => old_entry.date_from,
4030 p_entry_value3 => old_entry.date_to,
4031 p_entry_value4 => old_entry.amount * -1,
4032 p_entry_value5 => old_entry.withheld_days * -1,
4033 p_entry_value6 => old_entry.SSP_weeks * -1,
4034 p_entry_value7 => old_entry.SSP_days_due * -1,
4035 p_entry_value8 => old_entry.qualifying_days * -1);
4036 --
4037 hr_utility.set_location(l_proc,25);
4038 else
4039 --
4040 -- Delete the unprocessed, invalid entry
4041 --
4042 hr_utility.set_location (l_proc,30);
4043 --
4044 hr_entry_api.delete_element_entry (
4045 p_dt_delete_mode => 'ZAP',
4046 p_session_date => old_entry.effective_start_date,
4047 p_element_entry_id => old_entry.element_entry_id);
4048 --
4049 hr_utility.set_location (l_proc,35);
4050 end if;
4051 end if;
4052 end loop;
4053 --
4054 if p_entitled_to_SSP then
4055 --
4056 -- The person is entitled to SSP so we can create new entries for him.
4057 --
4058 <<INSERT_NEW_ENTRIES>>
4059 --
4060 -- Now go through the new entries, inserting any which are not marked as
4061 -- having been dealt with already.
4062 --
4063 hr_utility.set_location (l_proc,4);
4064 --
4065 begin
4066 Y := 0;
4067 --
4068 LOOP
4069 Y := Y + 1;
4070 --
4071 if not new_entry.dealt_with (Y) = 'TRUE' and
4072 new_entry.ssp_weeks (Y) > 0 and
4073 (new_entry.withheld_days (Y) < new_entry.SSP_days_due (Y)
4074 or new_entry.SSP_days_due (Y) = 0)
4075 then
4076 --
4077 -- Insert an entry for each week where there is not already a
4078 -- correct, processed entry and where the stoppage days are less
4079 -- than the due days or the due days are zero (because of waiting
4080 -- days) and where the entry is for part or all of an SSP week.
4081 --
4082 hr_utility.set_location(l_proc,40);
4083 hr_utility.trace(l_proc||' NEW: Before calling hr_entry_api.insert_element_entry');
4084 hr_utility.trace(l_proc||' new_entry.effective_start_date('||Y||') :'||new_entry.effective_start_date(Y));
4085 hr_utility.trace(l_proc||' new_entry.effective_end_date('||Y||') :'||new_entry.effective_end_date(Y));
4086 --
4087 hr_entry_api.insert_element_entry (
4088 p_effective_start_date => new_entry.effective_start_date (Y),
4089 p_effective_end_date => new_entry.effective_end_date (Y),
4090 p_element_entry_id => l_dummy,
4091 p_assignment_id => new_entry.assignment_id (Y),
4092 p_element_link_id => new_entry.element_link_id (Y),
4093 p_creator_type => c_SSP_creator_type,
4094 p_creator_id => g_PIW_id,
4095 p_entry_type => 'E',
4096 p_input_value_id1 => g_SSP_legislation.rate_id,
4097 p_input_value_id2 => g_SSP_legislation.from_id,
4098 p_input_value_id3 => g_SSP_legislation.to_id,
4099 p_input_value_id4 => g_SSP_legislation.amount_id,
4100 p_input_value_id5 => g_SSP_legislation.withheld_days_id,
4101 p_input_value_id6 => g_SSP_legislation.SSP_weeks_id,
4102 p_input_value_id7 => g_SSP_legislation.SSP_days_due_id,
4103 p_input_value_id8 => g_SSP_legislation.qualifying_days_id,
4104 p_entry_value1 => new_entry.rate (Y),
4105 -- Fix for bug 1020757:
4106 -- This explicit conversion is not possible anymore since we don't know
4107 -- what the format is going to be. We need to use fnd_date,date_to_chardate
4108 -- p_entry_value2 => to_char(new_entry.date_from(Y),'DD-MON-YYYY'),
4109 -- p_entry_value3 => to_char(new_entry.date_to(Y),'DD-MON-YYYY'),
4110 p_entry_value2 => fnd_date.date_to_chardate(new_entry.date_from(Y)),
4111 p_entry_value3 => fnd_date.date_to_chardate(new_entry.date_to(Y)),
4112 p_entry_value4 => new_entry.amount (Y),
4113 p_entry_value5 => new_entry.withheld_days (Y),
4114 p_entry_value6 => new_entry.SSP_weeks (Y),
4115 p_entry_value7 => new_entry.SSP_days_due (Y),
4116 p_entry_value8 => new_entry.qualifying_days (Y));
4117 --
4118 hr_utility.set_location(l_proc,45);
4119 end if;
4120 end loop;
4121 --
4122 exception
4123 when no_data_found then
4124 --
4125 -- There are no more new entries to be inserted.
4126 --
4127 null;
4128 --
4129 end;
4130 end if;
4131 end if;
4132 --
4133 hr_utility.set_location('Leaving :'||l_proc,100);
4134 --
4135 end generate_payments;
4136 --------------------------------------------------------------------------------
4137 procedure ins_ssp_temp_affected_rows_PIW(p_absence_id in number,
4138 p_deleting in boolean default false) is
4139 --
4140 -- Inserts a row in ssp_temp_affected_rows for the PIW id, if not already there
4141 --
4142 l_proc varchar2 (72) := g_package||'ins_ssp_temp_affected_rows_PIW';
4143 l_deleting_ch varchar2(1);
4144 --
4145 begin
4146 --
4147 hr_utility.set_location('Entering:'||l_proc,1);
4148 if p_deleting then
4149 l_deleting_ch := 'Y';
4150 else
4151 l_deleting_ch := 'N';
4152 end if;
4153 --
4154 if p_absence_id is not null then
4155 hr_utility.trace('inserting record for absence '||to_char(p_absence_id)||
4156 'deleting is '||l_deleting_ch);
4157 --
4158 insert into ssp_temp_affected_rows (PIW_id, p_deleting, locked)
4159 select p_absence_id, l_deleting_ch, userenv('sessionid')
4160 from sys.dual
4161 where not exists
4162 (select null
4163 from ssp_temp_affected_rows t2
4164 where t2.PIW_id = p_absence_id);
4165 end if;
4166 --
4167 hr_utility.set_location('Leaving :'||l_proc,100);
4168 --
4169 end ins_ssp_temp_affected_rows_PIW;
4170 --------------------------------------------------------------------------------
4171 procedure SSP1L_control (
4172 --
4173 -- If prior employment details are updated then we must recalculate SSP
4174 -- This procedure is called from the after update row-level trigger on
4175 -- PER_PERIODS_OF_SERVICE.
4176 --
4177 p_person_id in number,
4178 p_date_start in date
4179 ) is
4180 --
4181 cursor affected_PIW is
4182 --
4183 -- Get any PIW which may have been linked to the prior employment SSP.
4184 --
4185 select nvl (linked_absence_id, absence_attendance_id) PIW_ID
4186 from per_absence_attendances
4187 where sickness_start_date
4188 <= (p_date_start + g_SSP_legislation.linking_period_days)
4189 and person_id = p_person_id;
4190 --
4191 l_proc varchar2 (72) := g_package||'SSP1L_control';
4192 l_PIW_ID number := null;
4193 --
4194 procedure check_parameters is
4195 --
4196 all_parameters_valid constant boolean := (p_person_id is not null
4197 and p_date_start = trunc (p_date_start)
4198 and p_date_start is not null);
4199 --
4200 begin
4201 --
4202 hr_utility.trace (l_proc||' p_person_id: '||to_char(p_person_id));
4203 hr_utility.trace (l_proc||' p_date_start: ' ||to_char(p_date_start));
4204 --
4205 hr_general.assert_condition (all_parameters_valid);
4206 --
4207 end check_parameters;
4208 --
4209 begin
4210 --
4211 hr_utility.set_location('Entering:'||l_proc,1);
4212 --
4213 check_parameters;
4214 --
4215 get_SSP_element (p_date_start);
4216 --
4217 -- Get details of PIW which may be affected by changes in SSP1L details
4218 --
4219 open affected_PIW;
4220 fetch affected_PIW into l_PIW_ID;
4221 close affected_PIW;
4222 --
4223 if l_PIW_ID is not null then
4224 --
4225 -- Store the PIW ID for later use in the recalculate_SSP_and_SMP procedure
4226 --
4227 ins_ssp_temp_affected_rows_PIW (l_PIW_ID, p_deleting => FALSE);
4228 end if;
4229 --
4230 hr_utility.set_location('Leaving :'||l_proc,100);
4231 --
4232 end SSP1L_control;
4233 --------------------------------------------------------------------------------
4234 --
4235 -- If the person dies or the date of birth is modified then we need to
4236 -- recalculate SSP. This procedure is called from the after row-level update
4237 -- trigger of PER_PEOPLE_F.
4238 procedure person_control(p_person_id in number,
4239 p_date_of_death in date,
4240 p_date_of_birth in date) is
4241 --
4242 -- Get any sickness absences which may be affected by the change in age
4243 -- or the death.
4244 cursor affected_PIWs is
4245 select linked_absence_id,
4246 absence_attendance_id,
4247 sickness_start_date,
4248 sickness_end_date
4249 from per_absence_attendances
4250 where person_id = p_person_id
4251 and sickness_start_date is not null;
4252 --
4253 l_proc varchar2(72) := g_package||'person_control';
4254 l_65th_birthday date := add_months(p_date_of_birth, (65 *12));
4255 l_16th_birthday date := add_months(p_date_of_birth, (16 *12));
4256 l_01_October_06 date := to_date('01/10/2006','DD/MM/YYYY');
4257 l_employee_age number:= months_between(l_01_October_06,p_date_of_birth)/12;
4258 --
4259 procedure check_parameters is
4260 all_parameters_valid constant boolean :=
4261 (p_person_id is not null and
4262 p_date_of_death >= p_date_of_birth);
4263 begin
4264 hr_utility.trace (l_proc||' p_person_id = '||to_char (p_person_id));
4265 hr_utility.trace (l_proc||' p_date_of_death = '||to_char (p_date_of_death));
4266 hr_utility.trace (l_proc||' p_date_of_birth = '||to_char (p_date_of_birth));
4267 --
4268 hr_general.assert_condition (all_parameters_valid);
4269 --
4270 end check_parameters;
4271 --
4272 begin
4273 hr_utility.set_location('Entering:'||l_proc,1);
4274 --
4275 check_parameters;
4276 --
4277 for l_absence in affected_PIWs LOOP
4278 if(-- the PIW starts on or after the person's 65th birthday
4279 l_65th_birthday <= linked_PIW_start_date (p_person_id,
4280 l_absence.sickness_start_date,
4281 l_absence.sickness_end_date,
4282 p_date_of_birth)
4283 -- or the PIW start on or before the person's 16th birthday
4284 or
4285 (l_16th_birthday > linked_PIW_start_date (p_person_id,
4286 l_absence.sickness_start_date,
4287 l_absence.sickness_end_date,
4288 p_date_of_birth) and
4289 l_employee_age < 16)
4290 -- or the PIW ends on or after the person's death
4291 or p_date_of_death <= nvl(linked_PIW_end_date(p_person_id,
4292 l_absence.sickness_start_date,
4293 l_absence.sickness_end_date,
4294 p_date_of_birth),
4295 p_date_of_death))
4296 then
4297 if l_employee_age < 16 then
4298 ins_ssp_temp_affected_rows_PIW (l_absence.absence_attendance_id,
4299 p_deleting => FALSE);
4300 else
4301 ins_ssp_temp_affected_rows_PIW (nvl(l_absence.linked_absence_id,
4302 l_absence.absence_attendance_id),
4303 p_deleting => FALSE);
4304 end if;
4305 end if;
4306 end loop;
4307 --
4308 -- Call the ssp_smp_support_pkg.recalculate_ssp_and_smp directly.
4309 ssp_smp_support_pkg.recalculate_ssp_and_smp(p_deleting => FALSE);
4310 --
4311 hr_utility.set_location('Leaving :'||l_proc,100);
4312 --
4313 end person_control;
4314 --------------------------------------------------------------------------------
4315 -- If absence details are updated then we must recalculate SSP.
4316 procedure absence_control(p_absence_attendance_id in number,
4317 p_linked_absence_id in number,
4318 p_person_id in number,
4319 p_sickness_start_date in date,
4320 p_deleting in boolean default FALSE) is
4321 l_proc varchar2 (72) := g_package||'absence_control';
4322 --
4323 procedure check_parameters is
4324 all_parameters_valid constant boolean :=
4325 (p_person_id is not null and
4326 p_absence_attendance_id is not null and
4327 p_deleting is not null and
4328 p_sickness_start_date = trunc (p_sickness_start_date) and
4329 p_absence_attendance_id <> p_linked_absence_id);
4330 begin
4331 --
4332 hr_utility.trace (l_proc||' p_absence_attendance_id = '||to_char (p_absence_attendance_id));
4333 hr_utility.trace (l_proc||' p_linked_absence_id'||to_char (p_linked_absence_id));
4334 hr_utility.trace ('p_person_id'||to_char (p_person_id));
4335 hr_utility.trace ('p_sickness_start_date' ||to_char (p_sickness_start_date));
4336 if p_deleting then
4337 hr_utility.trace (l_proc||' p_deleting is TRUE');
4338 else
4339 hr_utility.trace (l_proc||' p_deleting is FALSE');
4340 end if;
4341 --
4342 hr_general.assert_condition (all_parameters_valid);
4343 --
4344 end check_parameters;
4345 begin
4346 hr_utility.set_location('Entering:'||l_proc,1);
4347 --
4348 check_parameters;
4349 --
4350 if p_deleting then
4351 g_absence_del := 'Y';
4352 else
4353 g_absence_del := 'N';
4354 end if;
4355 --
4356 -- The parent PIW is being deleted. Remove any associated entries.
4357 if p_deleting and p_linked_absence_id is null then
4358 g_PIW_id := p_absence_attendance_id;
4359 new_entry := empty_record;
4360 PIW_start_date := p_sickness_start_date;
4361 --
4362 hr_utility.trace('Deleting parent absence, id '||to_char(g_PIW_id));
4363 --
4364 open csr_person (p_sickness_start_date, p_person_id);
4365 fetch csr_person into absentee;
4366 close csr_person;
4367 --
4368 generate_payments (p_entitled_to_SSP => FALSE);
4369 --
4370 delete ssp_temp_affected_rows
4371 where PIW_id = g_PIW_id;
4372 else
4373 --
4374 -- The PIW series must have been updated or inserted. Recalculate SSP.
4375 ins_ssp_temp_affected_rows_PIW (nvl(p_linked_absence_id,p_absence_attendance_id)
4376 ,p_deleting);
4377 end if;
4378 --
4379 hr_utility.set_location('Leaving :'||l_proc,100);
4380 --
4381 end absence_control;
4382 --------------------------------------------------------------------------------
4383 procedure earnings_control (
4384 --
4385 -- If average earnings are altered then we must recalculate SSP.
4386 --
4387 p_person_id in number,
4388 p_effective_date in date
4389 ) is
4390 --
4391 cursor affected_PIW is
4392 --
4393 -- Find the PIW whose start date is the same as the date of the
4394 -- average earnings calculation.
4395 --
4396 select *
4397 from per_absence_attendances
4398 where sickness_start_date = p_effective_date
4399 and person_id = p_person_id;
4400 --
4401 l_proc varchar2 (72) := g_package||'earnings_control';
4402 --
4403 procedure check_parameters is
4404 --
4405 all_parameters_valid constant boolean := (p_person_id is not null
4406 and p_effective_date is not null
4407 and p_effective_date = trunc (p_effective_date));
4408 --
4409 begin
4410 --
4411 hr_utility.trace (l_proc||' p_person_id = '||to_char (p_person_id));
4412 hr_utility.trace (l_proc||' p_effective_date = '
4413 ||to_char (p_effective_date));
4414 --
4415 hr_general.assert_condition (all_parameters_valid);
4416 --
4417 end check_parameters;
4418 --
4419 begin
4420 --
4421 hr_utility.set_location('Entering:'||l_proc,1);
4422 --
4423 check_parameters;
4424 --
4425 open affected_PIW;
4426 fetch affected_PIW into g_absence;
4427 close affected_PIW;
4428 --
4429 if g_absence.absence_attendance_id is not null
4430 then
4431 hr_utility.set_location (l_proc,10);
4432 --
4433 ins_ssp_temp_affected_rows_PIW (g_absence.absence_attendance_id,
4434 p_deleting => FALSE);
4435 end if;
4436 --
4437 hr_utility.set_location('Leaving :'||l_proc,100);
4438 --
4439 end earnings_control;
4440 --------------------------------------------------------------------------------
4441 procedure stoppage_control (p_absence_id in number) is
4442 --
4443 -- If the user modifies stoppages then we must recalculate the SSP entitlement.
4444 --
4445 l_proc varchar2 (72) := g_package||'stoppage_control';
4446 --
4447 begin
4448 --
4449 hr_utility.set_location('Entering:'||l_proc,1);
4450 --
4451 if p_absence_id is not null
4452 then
4453 ins_ssp_temp_affected_rows_PIW (p_absence_id, p_deleting => FALSE);
4454 end if;
4455 --
4456 hr_utility.set_location('Leaving :'||l_proc,100);
4457 --
4458 end stoppage_control;
4459
4460 --------------------------------------------------------------------------------
4461 procedure medical_control (p_absence_id in number) is
4462 --
4463 -- If the user modifies medical evidence then recalculate the SSP entitlement.
4464 --
4465 l_proc varchar2 (72) := g_package||'medical_control';
4466 --
4467 begin
4468 --
4469 hr_utility.set_location('Entering:'||l_proc,1);
4470 --
4471 if p_absence_id is not null and g_absence_del = 'N'
4472 then
4473 ins_ssp_temp_affected_rows_PIW (p_absence_id, p_deleting => FALSE);
4474 end if;
4475
4476 g_absence_del := 'N';
4477 --
4478 hr_utility.set_location('Leaving :'||l_proc,100);
4479 --
4480 end medical_control;
4481
4482 --------------------------------------------------------------------------------
4483 procedure SSP_control(p_absence_attendance_id in number) is
4484 l_proc varchar2 (72) := g_package||'SSP_control';
4485 --
4486 l_rows_reason number:=0;
4487 --
4488 cursor csr_previous_reason is
4489 select count(*)
4490 from ssp_withholding_reasons swr,
4491 ssp_stoppages stp
4492 where stp.absence_attendance_id = p_absence_attendance_id
4493 and stp.reason_id = swr.reason_id
4494 and upper(swr.reason) = 'RE-HIRED EMPLOYEE,PLEASE CHECK';
4495 --
4496 procedure check_parameters is
4497 all_parameters_valid constant boolean := (p_absence_attendance_id is not null);
4498 begin
4499 hr_utility.trace (l_proc||' p_absence_attendance_id = '||to_char (p_absence_attendance_id));
4500 --
4501 hr_general.assert_condition (all_parameters_valid);
4502 --
4503 end check_parameters;
4504 begin
4505 hr_utility.set_location('Entering:'||l_proc,1);
4506 hr_utility.trace(l_proc||'---------PARAMS------------');
4507 hr_utility.trace(l_proc||'p_absence_attendance_id:'||p_absence_attendance_id);
4508 hr_utility.trace(l_proc||'---------------------------');
4509 --
4510 check_parameters;
4511 hr_utility.set_location(l_proc,2);
4512 --
4513 get_absence_details (p_absence_attendance_id);
4514 --
4515 open csr_previous_reason;
4516 fetch csr_previous_reason into l_rows_reason;
4517 if l_rows_reason > 0 then
4518 hr_utility.set_location(l_proc,3);
4519 ssp_smp_support_pkg.reason_for_no_earnings:='SSP_36076_EMP_REHIRED';
4520 hr_utility.set_location(l_proc,4);
4521 end if;
4522 close csr_previous_reason;
4523 --
4524 hr_utility.set_location(l_proc,5);
4525 generate_payments (entitled_to_SSP (g_absence));
4526 --
4527 hr_utility.set_location('Leaving :'||l_proc,100);
4528 --
4529 end SSP_control;
4530 --------------------------------------------------------------------------------
4531 end ssp_SSP_pkg;