DBA Data[Home] [Help]

PACKAGE BODY: APPS.SSP_SSP_PKG

Source


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