DBA Data[Home] [Help]

PACKAGE BODY: APPS.SSP_SAP_PKG

Source


1 package body SSP_SAP_PKG as
2 /*$Header: spsapapi.pkb 120.7.12010000.2 2008/11/14 07:04:39 npannamp ship $
3 +==============================================================================+
4 |                       Copyright (c) 1994 Oracle Corporation                  |
5 |                          Redwood Shores, California, USA                     |
6 |                               All rights reserved.                           |
7 +==============================================================================+
8 --
9 Name
10 	Statutory Paternity Pay Business Process
11 --
12 Purpose
13 	To perform calculation of entitlement and payment for SAP purposes
14 --
15 History
16 History
17 	03 Oct 02       V Khandelwal  2690305  Created from SSP_SMP_PKG
18 	27 Jan 03	G Butler	       nocopy fix to average_earnings -
19 					       added 2nd dummy variable to act as
20 					       placeholder variable for OUT param
21 					       from ssp_ern_ins
22         01 Feb 03       A Blinko      2774865  Added code for disrupted placement
23         03 Feb 03       A Blinko               disrupted placement stop only created
24                                                if before end of APP Period
25         06 Feb 03       A Blinko      2779883  Fixed Employee died stoppage
26         24 Oct 03       A Blinko      3208325  Removed hardcoded SATURDAY and
27                                                SUNDAY references
28         13 Jul 04       A Blinko      3682122  Changes for recalculating lump sum
29                                                updates
30         09 Feb 06       K Thampan     4891953  Fixed performance bug.
31         23-AUG-06       K Thampan     5482199  Statutory changes for 2007
32         19-SEP-06       K Thampan     5547703  Amend sap_control to call generate_payments
33                                                with insert-mode if absence is > 0 and
34                                                also change csr_check_if_existing_entries
35                                                not to reference from per_absence_attendances
36                                                table
37         19-OCT-06       K Thampan     5604330  Amended function entitled_to_sap to
38                                                check for employee date of death before creating
39                                                'Some work was done' stoppage.
40                                                Also update check_death to create stoppage based
41                                                on the 'rolling 7-day week' not the next Sunday.
42 	02-AUG-07      P Balu	      6271407  Changed the To_Date function to fnd_date.canonical_to_date
43 					       function in the cursor csr_existing_entries.
44 	14-NOV-08      Nagabushan     7563477  Changed the fnd_date.canonical_to_date function to
45 					       fnd_date.chardate_to_date function in the cursor csr_existing_entries.
46 */
47 --------------------------------------------------------------------------------
48 g_package  varchar2(33) := '  ssp_sap_pkg.';  -- Global package name
49 --
50 
51 cursor csr_absence_details (p_maternity_id in number) is
52 	--
53 	-- Get details of maternity leave for a maternity, in chronological
54 	-- order of start date
55 	--
56 	select	absence.absence_attendance_id,
57 		absence.date_start,
58 		nvl (absence.date_end, hr_general.end_of_time) date_end,
59 		absence.date_notification,
60 		absence.accept_late_notification_flag
61 	from
62             per_absence_attendances	ABSENCE
63 	   where absence.maternity_id = p_maternity_id
64 	order by absence.date_start;
65 	--
66 --------------------------------------------------------------------------------
67 cursor csr_personal_details (p_maternity_id in number) is
68 	--
69 	-- Get details of the maternal woman
70 	--
71 	select	maternity.person_id,
72 		maternity.due_date,
73 		ssp_sap_pkg.MATCHING_WEEK_OF_ADOPTION (MATCHING_DATE) MW,
74 		MATCHING_DATE MATCHING_DATE,
75         PLACEMENT_DATE PLACEMENT_DATE,
76         DISRUPTED_PLACEMENT_DATE DISRUPTED_PLACEMENT_DATE,
77 		maternity.maternity_id,
78 		maternity.actual_birth_date,
79 		maternity.live_birth_flag,
80 		maternity.start_date_with_new_employer,
81 		maternity.MPP_start_date APP_start_date,
82 		maternity.notification_of_birth_date,
83 		maternity.start_date_maternity_allowance,
84 		maternity.pay_SMP_as_lump_sum pay_SAP_as_lump_sum,
85 		person.date_of_death,
86         service.date_start,
87 		nvl (service.final_process_date, hr_general.end_of_time) FINAL_PROCESS_DATE
88 	from
89     	ssp_maternities				    MATERNITY,
90 		per_all_people_f				    PERSON,
91 		per_periods_of_service			SERVICE
92 	where
93         person.person_id = maternity.person_id
94 	and	person.person_id = service.person_id
95 	and	maternity.maternity_id = p_maternity_id
96 	and	nvl(service.actual_termination_date+1,service.date_start)
97                 between person.effective_start_date
98 		and person.effective_end_date
99         and     service.date_start = (select max(serv.date_start)
100                                      from per_periods_of_service serv
101                                      where serv.person_id = person.person_id);
102 	--
103 --------------------------------------------------------------------------------
104 person				            csr_personal_details%rowtype;
105 g_SAP_element			        csr_SAP_element_details%rowtype;
106 g_SAP_Correction_element    	csr_SAP_element_details%rowtype;
107 --------------------------------------------------------------------------------
108 l_saturday  varchar2(100) := to_char(to_date('06/01/2001','DD/MM/YYYY'),'DAY');
109 l_sunday    varchar2(100) := to_char(to_date('07/01/2001','DD/MM/YYYY'),'DAY');
110 
111 function MATCHING_WEEK_OF_ADOPTION
112 	 --
113 	 -- Returns the date on which the MW starts
114 	 --
115 	(p_matching_date  in date)
116 	--
117 	-- p_matching_date comes from the person's maternity record
118 	--
119 	return date is
120 	--
121 -- MW is the Sunday prior to MATCHING_WEEK DATE
122 --
123 l_MW  date := (next_day (p_matching_date,l_sunday) -7);
124 --
125 begin
126 --
127 return l_MW;
128 --
129 end MATCHING_WEEK_OF_ADOPTION;
130 --
131 --------------------------------------------------------------------------------
132 Function CONTINUOUS_EMPLOYMENT_DATE (p_matching_date	in date)
133 return date is
134 --
135 -- The continuous employment start date is the date on which the woman must
136 -- have been employed (and continuously from then to the MW) in order to
137 -- qualify for SAP. It is the MW minus the continuous employment period
138 -- specified on the SAP element.
139 -- A woman must have started work on or before the last day of the
140 -- week which starts 182 days (26 weeks) before the last day of the MW. In
141 -- SAP weeks start on Sunday and end on Saturday.
142 --
143 l_SAP_element			csr_SAP_element_details%rowtype;
144 l_Continuously_employed_since	date;
145 --
146 begin
147 --
148     open csr_SAP_element_details (p_matching_date,c_SAP_element_name);
149     fetch csr_SAP_element_details into l_SAP_element;
150     close csr_SAP_element_details;
151     --
152     l_Continuously_employed_since :=
153           next_day(next_day(
154                     MATCHING_WEEK_OF_ADOPTION (p_matching_date) ,l_saturday)
155           - (l_SAP_element.continuous_employment_period),l_saturday);
156 --
157 return l_Continuously_employed_since;
158 --
159 end continuous_employment_date;
160 --
161 --------------------------------------------------------------------------------
162 
163 
164 procedure get_SAP_correction_element (p_effective_date in date) is
165 --
166 l_proc        varchar2(72) := g_package||'get_SAP_correction_element';
167 --
168 procedure check_parameters is
169 	begin
170 	--
171 	hr_utility.trace (l_proc||'	p_effective_date = '
172 		||to_char (p_effective_date));
173 	--
174 	hr_api.mandatory_arg_error (
175 		p_api_name	=> l_proc,
176 		p_argument	=> 'effective_date',
177 		p_argument_value=> p_effective_date);
178 	end check_parameters;
179 	--
180 begin
181 --
182 hr_utility.set_location (l_proc,1);
183 --
184 check_parameters;
185 --
186 open csr_SAP_element_details (p_effective_date,c_SAP_Corr_element_name);
187 fetch csr_SAP_element_details into g_SAP_Correction_element;
188 close csr_SAP_element_details;
189 --
190 hr_utility.set_location (l_proc,100);
191 --
192 end get_SAP_correction_element;
193 --
194 --------------------------------------------------------------------------------
195 procedure get_SAP_element (p_effective_date in date) is
196 --
197 l_proc        varchar2(72) := g_package||'get_SAP_element';
198 --
199 procedure check_parameters is
200 	begin
201 	--
202 	hr_utility.trace (l_proc||'     p_effective_date = '
203 		||to_char (p_effective_date));
204 	--
205 	hr_api.mandatory_arg_error (
206 		p_api_name	=> l_proc,
207 		p_argument	=> 'effective_date',
208 		p_argument_value=> p_effective_date);
209 	end check_parameters;
210 	--
211 begin
212 --
213 hr_utility.set_location (l_proc,1);
214 --
215 check_parameters;
216 --
217 open csr_SAP_element_details (p_effective_date,c_SAP_element_name);
218 fetch csr_SAP_element_details into g_SAP_element;
219 close csr_SAP_element_details;
220 --
221 hr_utility.set_location (l_proc,100);
222 --
223 end get_SAP_element;
224 --
225 --------------------------------------------------------------------------------
226 function EARLIEST_APP_START_DATE (p_due_date in date) return date is
227 --
228 -- The earliest APP start date, under normal circumstances is  the
229 -- child expected date minus
230 -- the number of weeks specified on the SAP element for earliest SAP start
231 --
232 l_earliest_APP_start	date;
233 l_SAP_element		csr_SAP_element_details%rowtype;
234 --
235 begin
236 --
237 open csr_SAP_element_details (p_due_date,c_SAP_element_name);
238 fetch csr_SAP_element_details into l_SAP_element;
239 close csr_SAP_element_details;
240 --
241 l_earliest_APP_start := p_due_date
242 				- (l_SAP_element.earliest_start_of_APP);
243 return l_earliest_APP_start;
244 --
245 end earliest_APP_start_date;
246 --
247 --------------------------------------------------------------------------------
248 function MATERNITY_RECORD_EXISTS (p_person_id in number) return boolean is
249 --
250 cursor maternity_record is
251 	select	1
252 	from	ssp_maternities
253 	where	person_id = p_person_id;
254 --
255 l_dummy		number (1);
256 l_maternity_record_exists	boolean;
257 --
258 begin
259 --
260 open maternity_record;
261 fetch maternity_record into l_dummy;
262 l_maternity_record_exists := maternity_record%found;
263 close maternity_record;
264 --
265 return l_maternity_record_exists;
266 --
267 end maternity_record_exists;
268 --
269 --------------------------------------------------------------------------------
270 function AVERAGE_EARNINGS return number is
271 --
272 l_average_earnings	number := null;
273 l_effective_date	date := null;
274 l_dummy			    number;
275 l_dummy2		number; -- nocopy fix, placeholder variable
276 l_user_entered		varchar2(30) := 'N'; -- DFoster 1304683
277 l_absence_category	varchar2(30) := 'GB_ADO'; --DFoster 1304683
278 l_payment_periods	number := null; --DFoster 1304683
279 l_proc			    varchar2(72) := g_package||'average_earnings';
280 --
281 cursor csr_average_earnings is
282 	select	average_earnings_amount
283 	from	ssp_earnings_calculations
284 	where	person_id = person.person_id
285 	and	effective_date = l_effective_date;
286 --
287 begin
288 --
289 hr_utility.set_location ('Entering '||l_proc,1);
290 --
291 l_effective_date := greatest(person.MW, person.date_start);
292 --
293 open csr_average_earnings;
294 fetch csr_average_earnings into l_average_earnings;
295 if csr_average_earnings%notfound
296 then
297    ssp_ern_ins.ins (p_earnings_calculations_id  => l_dummy,
298                     p_object_version_number     => l_dummy2,
299                     p_person_id                 => person.person_id,
300                     p_effective_date            => l_effective_date,
301                     p_average_earnings_amount   => l_average_earnings,
302         		    p_user_entered	        => l_user_entered, --DFoster 1304683
303         		    p_absence_category		=> l_absence_category, --DFoster 1304683
304         		    p_payment_periods		=> l_payment_periods); --DFoster 1304683
305 end if;
306 --
307 close csr_average_earnings;
308 --
309 hr_utility.set_location ('Leaving '||l_proc,10);
310 --
311 return l_average_earnings;
312 --
313 end average_earnings;
314 --------------------------------------------------------------------------------
315 function entitled_to_SAP (p_maternity_id in number) return boolean is
316 --
317 -- See header for description of this procedure.
318 --
319 no_prima_facia_entitlement	exception;
320 invalid_absence_date		exception;
321 l_work_start_date		date := hr_general.end_of_time;
322 stoppage_end_date		date := null;
323 no_of_absence_periods		integer := 0;
324 l_proc                  	varchar2(72) := g_package||'entitled_to_SAP';
325 l_keep_stoppages                boolean default FALSE;
326 --
327 cursor csr_no_of_absences is
328 	--
329 	-- Get the number of distinct absences within a maternity pay period
330 	--
331 	select	count (*)
332 	from	per_absence_attendances
333 	where	person_id = person.person_id
334 	and	maternity_id = p_maternity_id;
335        --
336        --  returns entries associated with a maternity_id.
337 cursor csr_check_if_existing_entries is
338        --
339 select /*+ ORDERED use_nl(paa,paaf,etype,entry) */
340        entry.element_entry_id,
341        entry.effective_start_date
342 from   per_all_assignments_f   PAAF,
343        pay_element_types_f     ETYPE,
344        pay_element_entries_f   ENTRY
345 where  PAAF.person_id = person.person_id
346 and    ETYPE.element_name = c_SAP_element_name
347 and    ETYPE.legislation_code = 'GB'
348 and    ENTRY.element_type_id = ETYPE.element_type_id
349 and    entry.creator_type = c_SAP_creator_type
350 and    entry.creator_id = p_maternity_id
351 and    entry.assignment_id = PAAF.assignment_id
352 and not exists (
353        --
354        -- Do not select entries which have already had reversal action
355        -- taken against them because they are effectively cancelled out.
356        --
357        select 1
358        from   pay_element_entries_f      ENTRY2
359        where  entry.element_entry_id=entry2.target_entry_id
360        and    entry.assignment_id = entry2.assignment_id)
361        --
362 and not exists (
363        --
364        -- Do not select reversal entries
365        --
366        select  1
367        from    pay_element_links_f LINK,
368                pay_element_types_f TYPE
369        where   link.element_link_id = entry.element_link_id
370        and     entry.effective_start_date between link.effective_start_date and link.effective_end_date
371        and     link.element_type_id = type.element_type_id
372        and     link.effective_start_date between type.effective_start_date and type.effective_end_date
373        and     type.element_name = c_SAP_Corr_element_name);
374 --
375 l_existing_entries              csr_check_if_existing_entries%rowtype;
376 --
377 procedure create_stoppage (
378 	--
379 	-- Create a stoppage of payment for SAP
380 	--
381 	p_reason	in varchar2,
382 	p_withhold_from	in date,
383 	p_withhold_to	in date default null
384 	) is
385 	--
386 	l_proc		varchar2(72) := g_package||'create_stoppage';
387 	l_dummy		number;
388 	l_reason_id	number;
389 	--
390 	procedure check_parameters is
391 		--
392 		begin
393 		--
394 		hr_utility.trace (l_proc||'	p_reason = '||p_reason);
395 		hr_utility.trace (l_proc||'	withhold from '||to_char (p_withhold_from));
396 		hr_utility.trace (l_proc||'	withhold to '||to_char (p_withhold_to));
397 		--
398 		hr_api.mandatory_arg_error (
399 			p_api_name	=> l_proc,
400 			p_argument	=> 'reason',
401 			p_argument_value=> p_reason);
402 			--
403 		hr_api.mandatory_arg_error (
404 			p_api_name      => l_proc,
405 			p_argument      => 'withhold_from',
406 			p_argument_value=> p_withhold_from);
407 			--
408 		end check_parameters;
409 		--
410 	begin
411 	--
412 	hr_utility.set_location (l_proc,1);
413 	--
414 	check_parameters;
415 	--
416 	l_reason_id := ssp_smp_support_pkg.withholding_reason_id (
417 				g_SAP_element.element_type_id,
418 				p_reason);
419 				--
420 	if not ssp_smp_support_pkg.stoppage_overridden (
421 				p_maternity_id => p_maternity_id,
422 				p_reason_id => l_reason_id)
423 	then
424 	  --
425 	  -- Only create the stoppage if there is not already a stoppage marked
426 	  -- as overridden. Thus, overriding a stoppage effectively blocks that
427 	  -- reason being used to withhold payment for this person.
428 	  --
429 	  ssp_stp_ins.ins (p_withhold_from => p_withhold_from,
430 			p_withhold_to   => p_withhold_to,
431 			p_stoppage_id   => l_dummy,
432 			p_object_version_number => l_dummy,
433 			p_maternity_id	=> p_maternity_id,
434 			p_user_entered  => 'N',
435 			p_reason_id     => l_reason_id);
436 	else
437 	   hr_utility.trace (l_proc||'	Stoppage is overridden');
438 	end if;
439 	--
440 	hr_utility.set_location (l_proc,100);
441 	--
442 	end create_stoppage;
443 	--
444 procedure remove_stoppages is
445 	--
446 	-- Remove old system, non-overridden stoppages
447 	--
448 	cursor csr_stoppages is
449 		select	stoppage_id
450 		from	ssp_stoppages
451 		where	user_entered <>'Y'
452 		and	override_stoppage <> 'Y'
453 		and	maternity_id = p_maternity_id;
454 		--
455 	l_dummy	number;
456 	l_proc varchar2 (72) := g_package||'remove_stoppages';
457 	--
458 	begin
459 	--
460 	hr_utility.set_location (l_proc,1);
461 	--
462 	for each_stoppage in csr_stoppages LOOP
463 	   ssp_stp_del.del (p_stoppage_id => each_stoppage.stoppage_id,
464                             p_object_version_number => l_dummy);
465 	end loop;
466 	--
467 	hr_utility.set_location (l_proc,100);
468 	--
469       end remove_stoppages;
470       --
471 procedure check_continuity_rule is
472 	--
473 	-- Check that the person has the right amount of continuous service to
474 	-- qualify for SAP
475 	--
476 	cursor period_of_service is
477 		--
478 		-- Check the period of service length up to the MW start date
479 		--
480 		select	1
481 		from	per_periods_of_service
482 		where	person_id = person.person_id
483 		and	date_start <= ssp_sap_pkg.continuous_employment_date
484 						(person.matching_date)
485 		and	nvl (actual_termination_date, hr_general.end_of_time)
486 				>= person.MW;
487 	--
488 	l_dummy number (1);
489 	l_proc	varchar2 (72) := g_package||'check_continuity_rule';
490 	--
491 	begin
492 	--
493 	hr_utility.set_location (l_proc,1);
494 	--
495 	open period_of_service;
496 	fetch period_of_service into l_dummy;
497 	--
498 	if period_of_service%notfound then
499 	  --
500 	  -- Stop all SAP payment for the Adoption because the person has not
501 	  -- been continuously employed for long enough.
502 	  --
503 	  create_stoppage (p_withhold_from => person.APP_start_date,
504                        p_reason => 'Insufficient employment');
505 	end if;
506 	--
507 	close period_of_service;
508 	--
509 	hr_utility.set_location (l_proc,100);
510 	--
511 	end check_continuity_rule;
512 	--
513 /*
514 procedure check_stillbirth is
515 	--
516 	-- Check the pregnancy condition for qualification for SMP
517 	--
518 	l_proc varchar2 (72) := g_package||'check_stillbirth';
519 	--
520 	begin
521 	--
522 	hr_utility.set_location (l_proc,1);
523 	--
524 	-- Woman must be still pregnant, have had a live birth, or have had a
525 	-- stillbirth after the threshhold week to be eligible for SMP
526 	--
527 	if	NOT (woman.actual_birth_date is null
528 		or woman.live_birth_flag = 'Y'
529 		or woman.actual_birth_date > woman.EWC
530 				- g_SMP_element.stillbirth_threshhold_week)
531 	then
532 	  --
533 	  -- Stop SMP payment from the start of the week in which the absence
534 	  -- started.
535 	  --
536 	  create_stoppage (p_withhold_from => woman.MPP_start_date,
537                            p_reason => 'Stillbirth');
538 	end if;
539 	--
540 	hr_utility.set_location (l_proc,100);
541 	--
542 	end check_stillbirth;
543 	--
544 */
545 procedure check_new_employer is
546 	--
547 	-- Check the person has not been employed by a new employer after the
548 	-- child placement
549 	--
550 	l_proc	varchar2 (72) := g_package||'check_new_employer';
551 	--
552 	begin
553 	--
554 	hr_utility.set_location (l_proc,1);
555 	--
556 	if person.start_date_with_new_employer >= person.placement_date then
557 	  --
558 	  -- Stop SAP payment from the start of the week in which the person
559 	  -- started work for a new employer after the placement of her child.
560 	  --
561 	  create_stoppage (p_withhold_from => ssp_smp_support_pkg.start_of_week
562                                            (person.start_date_with_new_employer),
563                       p_reason => 'Worked for another employer');
564 	end if;
565 	--
566 	hr_utility.set_location (l_proc,100);
567 	--
568 	end check_new_employer;
569 	--
570 procedure check_maternity_allowance is
571 	--
572 	-- SAP ceases when SMA starts.
573 	--
574 	l_proc	varchar2 (72) := g_package||'check_maternity_allowance';
575 	--
576 	begin
577 	--
578 	hr_utility.set_location (l_proc,1);
579 	--
580 	if person.start_date_maternity_allowance is not null then
581 	  --
582 	  -- Stop SAP payment from the start of the week in which SMA was first
583 	  -- paid.
584 	  --
585 	  create_stoppage (p_withhold_from => ssp_smp_support_pkg.start_of_week
586                                          (person.start_date_maternity_allowance),
587                            p_reason => 'Employee is receiving SMA');
588 	end if;
589 	--
590 	hr_utility.set_location (l_proc,100);
591 	--
592 	end check_maternity_allowance;
593 	--
594 procedure check_death is
595 	--
596 	-- SAP ceases after the death of the woman.
597 	--
598 	l_proc	varchar2 (72) := g_package||'check_death';
599 	--
600         cursor csr_check_death is
601         select ppf.date_of_death
602         from per_all_people_f ppf
603         where ppf.person_id = person.person_id
604         and ppf.date_of_death is not null;
605         --
606         cursor csr_get_week_date is
607         select to_char(person.app_start_date, 'DAY')
608         from   dual;
609         --
610         l_date_of_the_week varchar2(20);
611         l_death_date date;
612 
613 	begin
614 	--
615 	hr_utility.set_location (l_proc,1);
616 	--
617         open  csr_check_death;
618         fetch csr_check_death into l_death_date;
619         close csr_check_death;
620         --
621 	if l_death_date is not null then
622           open csr_get_week_date;
623           fetch csr_get_week_date into l_date_of_the_week;
624           close csr_get_week_date;
625 	  --
626 	  -- SAP ceases on the Saturday following death
627 	  --
628 	  create_stoppage (p_withhold_from => next_day (person.date_of_death,
629                                                         l_date_of_the_week), --l_sunday),
630                            p_reason => 'Employee died');
631 	end if;
632 	--
633 	hr_utility.set_location (l_proc,100);
634 	--
635 	end check_death;
636 	--
637 procedure check_disrupted_placement is
638 
639 begin
640 
641         if person.disrupted_placement_date is not null
642         and (person.disrupted_placement_date + (g_SAP_element.disrupted_placement_weeks)) <
643             ((g_SAP_element.maximum_APP * 7) + person.APP_start_date)
644         then
645 
646 	  create_stoppage (p_withhold_from => person.disrupted_placement_date +
647                                               (g_SAP_element.disrupted_placement_weeks),
648                            p_reason => 'Placement disrupted');
649 
650         end if;
651 
652 end check_disrupted_placement;
653 
654 procedure check_average_earnings is
655 	--
656 	-- The woman must earn enough to qualify for SAP
657 	--
658 	l_proc varchar2 (72) := g_package||'check_average_earnings';
659 	l_average_earnings		number := average_earnings;
660 	l_reason_for_no_earnings	varchar2 (80) := null;
661 	earnings_not_derived		exception;
662 	--
663 	begin
664 	--
665 	hr_utility.set_location (l_proc,1);
666 	--
667         if l_average_earnings = 0
668         then
669            --
670            -- If the average earnings figure returned is zero then check that
671            -- no error message was set. Error messages will be set for system-
672            -- generated average earnings when the earnings could not be derived
673            -- for some reason, but to allow this procedure to continue, no error
674            -- will be raised.
675            --
676            l_reason_for_no_earnings:=ssp_smp_support_pkg.average_earnings_error;
677            --
678            if l_reason_for_no_earnings is not null then
679     	      create_stoppage (p_withhold_from => person.aPP_start_date,
680                                p_reason => l_reason_for_no_earnings);
681 	      --
682 	      raise earnings_not_derived;
683 	   end if;
684 	end if;
685 	--
686 	if l_average_earnings
687 		< ssp_smp_support_pkg.NI_Lower_Earnings_Limit (person.MW)
688 	then
689 	  --
690 	  -- Stop SAP payment from the APP start date
691 	  --
692 	  create_stoppage (p_withhold_from => person.APP_start_date,
693                            p_reason => 'Earnings too low');
694 	end if;
695 	--
696 	hr_utility.set_location (l_proc,100);
697 	--
698 	exception
699 	--
700 	when earnings_not_derived then
701 	  --
702 	  -- Exit silently from this procedure
703 	  --
704 	  hr_utility.trace (l_proc||'	Earnings not derived');
705 	  null;
706 	  --
707 	end check_average_earnings;
708 	--
709 /*
710 procedure check_medical_evidence is
711 	--
712 	-- Check the acceptability of the maternity evidence
713 	--
714 	cursor medical is
715 		select	*
716 		from	ssp_medicals
717 		where	maternity_id = woman.maternity_id
718 		and	evidence_status = 'CURRENT';
719 		--
720 	l_proc varchar2 (72) := g_package||'check_medical_evidence';
721 	l_medical	medical%rowtype;
722 	--
723 	begin
724 	--
725 	hr_utility.set_location (l_proc,1);
726 	--
727 	open medical;
728 	fetch medical into l_medical;
729 	--
730 	if medical%notfound -- no medical evidence recorded
731 	or (medical%found and
732 		--
733 		-- evidence is dated too early
734 		--
735 	   (l_medical.evidence_date < person.EWC
736 					- g_SMP_element.earliest_SMP_evidence)
737 		--
738 		-- evidence was received late for no good reason
739 		--
740 	   or (l_medical.evidence_received_date > woman.MPP_start_date
741 					+ g_SMP_element.latest_SMP_evidence
742 	      and l_medical.accept_late_evidence_flag = 'N')
743 		--
744 		-- evidence was received late, even after extension allowed
745 		--
746 	   or (l_medical.evidence_received_date > woman.MPP_start_date
747 					+ g_SMP_element.extended_SMP_evidence))
748 	then
749 	  --
750 	  -- Stop SMP payment from the start of the week in which the MPP
751 	  -- started.
752 	  --
753 	  create_stoppage (p_withhold_from => woman.MPP_start_date,
754                        p_reason => 'Late/unacceptable evidence');
755 	end if;
756 	--
757 	close medical;
758 	--
759 	hr_utility.set_location (l_proc,100);
760 	--
761 	end check_medical_evidence;
762 	--
763 */
764 /*
765 procedure check_birth_confirmation is
766 	--
767 	-- Check that confirmation of birth was received in good time.
768 	--
769 	l_proc	varchar2 (72) := g_package||'check_birth_confirmation';
770 	--
771 	begin
772 	--
773 	hr_utility.set_location (l_proc,1);
774 	--
775         --
776         -- This should not create a stoppage. A quick fix for bug 1021179
777         -- is to comment out the stoppage process.
778         --
779         null;
780 
781 --	if (woman.actual_birth_date is not null
782 --	and (nvl (woman.notification_of_birth_date, sysdate)
783 --		> woman.actual_birth_date
784 --				+ g_SMP_element.notice_of_birth_requirement))
785 --	then
786  	  --
787 	   -- Stop SMP payment from the start of the week in which the MPP
788 	   -- started.
789 	   --
790 --          create_stoppage (p_withhold_from => woman.MPP_start_date,
791 --                          p_reason => 'Late notification of birth');
792 --	end if;
793 	--
794 	hr_utility.set_location (l_proc,100);
795 	--
796 	end check_birth_confirmation;
797 	--
798 */
799 procedure check_parameters is
800 	--
801 	begin
802 	--
803 	hr_utility.trace (l_proc||'	p_maternity_id = '
804 		||to_char (p_maternity_id));
805 	--
806 	hr_api.mandatory_arg_error (
807 		p_api_name	=> l_proc,
808 		p_argument	=> 'maternity_id',
809 		p_argument_value=> p_maternity_id);
810 		--
811 	end check_parameters;
812 	--
813 begin
814 --
815 hr_utility.set_location (l_proc,1);
816 --
817 check_parameters;
818 --
819 -- Get the details of the woman and her maternity.
820 --
821 open csr_personal_details (p_maternity_id);
822 fetch csr_personal_details into person;
823 --
824 if csr_personal_details%notfound
825 then
826    --
827    -- If no maternity record exists then there can be no entitlement to SAP
828    --
829    close csr_personal_details;
830    --
831    hr_utility.trace (l_proc||'	Person has no maternity record - exiting');
832    --
833    raise no_prima_facia_entitlement;
834 end if;
835 --
836 close csr_personal_details;
837 --
838 if person.APP_start_date is null then
839    --
840    -- If the APP has not started then there is no entitlement to SAP.
841    --
842    hr_utility.trace (l_proc||'	Person has no APP start date - exiting');
843    --
844    raise no_prima_facia_entitlement;
845 end if;
846 --
847 -- Count how many absences there are for the maternity.
848 --
849 open csr_no_of_absences;
850 fetch csr_no_of_absences into no_of_absence_periods;
851 close csr_no_of_absences;
852 --
853 if no_of_absence_periods = 0
854 then
855    --
856    -- check if entries exist despite there being no absence
857    --
858    open csr_check_if_existing_entries;
859    fetch csr_check_if_existing_entries into l_existing_entries;
860    --
861    if csr_check_if_existing_entries%NOTFOUND
862    then
863       hr_utility.trace (l_proc||'    Person has not stopped work - exiting');
864       raise no_prima_facia_entitlement;
865    end if;
866    --
867    -- if entries are found then the absence has been deleted and entries remain
868    -- that must be dealt with
869    --
870    while csr_check_if_existing_entries%FOUND LOOP
871       fetch csr_check_if_existing_entries into l_existing_entries;
872    end loop;
873    --
874    close csr_check_if_existing_entries;
875    l_keep_stoppages := TRUE;
876 end if;
877 --
878 -- Having established a prima facia entitlement to SAP, perform checks which
879 -- may lead to creation of stoppages for particular periods.
880 --
881 hr_utility.set_location ('ssp_smp_pkg.entitled_to_SAP',2);
882 --
883 -- Get the SAP legislative parameters.
884 --
885 get_SAP_element (person.due_date);
886 --
887 -- Clear stoppages created by previous calculations of SAP but if an absence
888 -- is being deleted, then must keep stoppages so that when later comparison of
889 -- old_entry and hypothetical_entry is done then stoppages are still there.
890 --
891 if not l_keep_stoppages then
892    remove_stoppages;
893 end if;
894 --
895 for absence in csr_absence_details (p_maternity_id) LOOP
896   --
897   -- Check that sufficient notification of absence was given
898   --
899   if
900      -- notification of absence was later than the allowed date
901      (absence.date_notification > absence.date_start
902   				- g_SAP_element.APP_notice_requirement
903      -- and there was no acceptable reason for the delay
904      and absence.accept_late_notification_flag = 'N')
905      --
906      -- or notification of absence was later than the extended allowable date
907      --
908      or (absence.date_notification > person.placement_date
909 					+ g_SAP_element.APP_notice_requirement)
910   then
911     --
912     -- Stop SAP payment from the start of the week in which the absence
913     -- starts, to the end of the notice period
914     --
915     stoppage_end_date := g_SAP_element.APP_notice_requirement
916 			+ absence.date_start - 1;
917     --
918 /*
919 Bug 2772479 - Late absence notification is no longer required for SAP. This may be reintroduced
920 so all code has been left in, with only the creation of the stoppage commented out.
921 
922     create_stoppage (
923           	p_withhold_from => ssp_smp_support_pkg.start_of_week
924         							(absence.date_start),
925           	p_withhold_to => ssp_smp_support_pkg.end_of_week (stoppage_end_date),
926           	p_reason => 'Late absence notification');
927 */
928   end if;
929   --
930   hr_utility.set_location ('ssp_sap_pkg.entitled_to_SaP',3);
931   --
932   -- Check for any work done during the APP.
933   --
934   if
935      -- this is the first absence period in the APP
936      csr_absence_details%rowcount = 1
937      --
938      -- and the absence starts after the APP start date
939      and absence.date_start > person.APP_start_date
940   then
941      create_stoppage (p_reason => 'Some work was done',
942                       p_withhold_from => person.APP_start_date,
943                       p_withhold_to => ssp_smp_support_pkg.end_of_week
944                                                        (absence.date_start -1));
945   end if;
946   --
947   if
948      -- this is the last absence period in the MPP
949      csr_absence_details%rowcount = no_of_absence_periods
950      --
951      -- and the absence period ends before the end of the MPP
952      and absence.date_end < (g_SAP_element.maximum_APP * 7)
953 				+ person.APP_start_date
954      and person.date_of_death is null
955   then
956      create_stoppage (p_reason => 'Some work was done',
957                       p_withhold_from => ssp_smp_support_pkg.start_of_week
958 							(absence.date_end+1));
959   elsif
960 	-- there is a period of work between two absences
961 	l_work_start_date < absence.date_start
962         and l_work_start_date < (g_SAP_element.maximum_APP * 7)
963 					+ person.APP_start_date
964   then
965      create_stoppage (p_reason => 'Some work was done',
966 		p_withhold_from => ssp_smp_support_pkg.start_of_week
967 							(l_work_start_date),
968 		p_withhold_to => ssp_smp_support_pkg.end_of_week
969 						(absence.date_start -1));
970      --
971      if absence.date_end <> hr_general.end_of_time
972      then
973         l_work_start_date := absence.date_end + 1;
974      else
975         --
976         -- This is not the last absence in the maternity but it has no end date.
977         --
978         hr_utility.trace (l_proc||'    ERROR: Invalid null absence end date');
979         --
980         raise invalid_absence_date;
981      end if;
982   end if;
983 end loop;
984 --
985 check_continuity_rule;
986 --check_stillbirth;
987 check_new_employer;
988 check_maternity_allowance;
989 check_death;
990 check_disrupted_placement;
991 --check_medical_evidence;
992 --check_birth_confirmation;
993 check_average_earnings;
994 --
995 -- If we get this far the person is entitled to SAP (though stoppages may apply)
996 --
997 return TRUE;
998 --
999 exception
1000 --
1001 when invalid_absence_date then
1002    fnd_message.set_name ('PAY', 'HR_6153_ALL_PROCEDURE_FAIL');
1003    fnd_message.set_token ('PROCEDURE','ssp_smp_pkg.entitled_to_SAP');
1004    fnd_message.set_token ('STEP','3');
1005    --
1006 when no_prima_facia_entitlement then
1007    --
1008    -- Exit silently; this will allow us to call this procedure with impunity
1009    -- from absences which are not maternity absences (e.g. via a row trigger)
1010    --
1011    return FALSE;
1012    --
1013 end entitled_to_SAP;
1014 --------------------------------------------------------------------------------
1015 procedure generate_payments
1016 --
1017 	--
1018 	-- Starting with the start of the Adoption Pay Period (APP), create
1019 	-- a nonrecurring entry for each week of maternity absence up to the
1020 	-- end of the maternity absence or to the maximum number of weeks
1021 	-- specified by the SAP rules. Note that there may be more than one
1022 	-- absence for a maternity, and the absences should be put together;
1023 	-- however, if the woman works for any part of a week (Sun-Sat), then
1024 	-- that week does not count towards maternity pay.
1025 	--
1026 	-- If there is a stoppage which overlaps either partially or completely
1027 	-- with the period covered by an entry then skip the creation of that
1028 	-- entry and move on to the next week. There are two kinds of stoppages;
1029         -- those which apply temporarily, and those which apply forever once
1030         -- started. Stoppages only apply within a maternity. If there is a
1031         -- stoppage which applies forever (ie it has no end date), then there
1032         -- is no need to continue creating entries after the start of that
1033         -- stoppage. Temporary entries should only affect creation while they
1034 	-- apply. A further feature of stoppages is that they may be overridden
1035 	-- by the user; if the override flag is set, then take no acount of
1036 	-- that stoppage when creating entries.
1037 	--
1038 	-- The maximum allowed number of weeks is held as a DDF segment on the
1039 	-- SAP element.
1040 	--
1041 	-- Whilst each entry is created to cover a particular period of absence,
1042 	-- the payroll period in which the entry resides is determined
1043 	-- separately. The default is that the entry will be created in the
1044 	-- payroll period which covers the end of the week of absence for which
1045 	-- the entry is created. If, however, that payroll period is in the
1046 	-- past, or has already been processed, or is closed, or is after the
1047 	-- person's last standard process date, then the entry must be placed
1048 	-- in the next open period for which no main payroll run has been
1049 	-- performed and which falls around or before the last standard process
1050 	-- date. If the entry cannot be created in any such period, for whatever
1051 	-- reason, then an error should be raised and the user required to
1052 	-- resolve the problem before any entry for the absence can be created.
1053 	-- The user may choose to pay SAP as a lump sum, in which case all
1054 	-- entries are to be placed in the next possible payroll period after
1055 	-- the start of the Maternity Pay Period.
1056 	--
1057 	-- If any detail of the absence is changed, then the entries must be
1058 	-- recalculated to ensure that the change is reflected in the
1059 	-- payments. Therefore, we may be performing the entry creation when
1060 	-- entries already exist for the absence. For each entry which we are
1061 	-- about to create, we must check that there is not an existing entry
1062 	-- which covers the same absence period. If there is not, then we
1063 	-- create the entry as planned; if there is, then we must update the
1064 	-- existing one rather than create a new one, if a change is required.
1065 	-- However, if that entry has already been processed in a payroll run,
1066 	-- then rather than updating it, we must ensure that the
1067 	-- over/underpayment is corrected at the next opportunity. This is
1068 	-- done by creating two entries; one which pays the correct amount
1069 	-- and another, for the SAP Correction element, which reverses the
1070 	-- incorrect payment by replicating it with a negative sign in front of
1071 	-- the amount entry value. Before creating the negative entry, it is
1072 	-- essential to check that there is not already a negative entry for
1073 	-- the incorrect entry; we do not want to overcorrect.
1074 	--
1075 	-- The week commencing entry value is the date of the Sunday of the
1076 	-- week for which this entry is being created.
1077 	--
1078 	-- The Rate entry value is simply 'Higher' or 'Lower'. The number of
1079 	-- entries to be created at the higher rate is determined by the
1080 	-- DDF segment on the SAP element. When creating entries for SAP,
1081 	-- that number of entries is to be created at the higher rate before
1082 	-- any are created at the lower rate, and so stoppages are always
1083 	-- affecting the lower rate first.
1084 	--
1085 	-- The amount entry value is determined by the rate; if it is the
1086 	-- higher rate, then the higer rate DDF segment of the SAP element
1087 	-- will identify a percentage of average earnings. The average
1088 	-- earnings should have been calculated by the entitlement check, for
1089 	-- payroll users, or entered independently by HR users. If it is the
1090 	-- lower rate, then the amount to be paid is held directly in the
1091 	-- lower rate DDF segment on the SAP element.
1092 	--
1093 	-- Each entry created by this procedure is to have a creator type
1094 	-- which identifies it as an SAP entry, and a creator_id which is
1095 	-- the maternity_id.
1096         --
1097         -- p_deleting parameter has been added to carry out logic for
1098         -- dealing with deleted absences
1099 --
1100 (p_maternity_id	in number,
1101  p_deleting     in boolean default FALSE) is
1102 --
1103 type date_table is table of date index by binary_integer;
1104 type number_table is table of number index by binary_integer;
1105 type varchar_table is table of varchar2 (80) index by binary_integer;
1106 l_proc varchar2(72) := g_package||'generate_payments';
1107 --
1108 type SAP_entry is record (
1109 	--
1110 	element_entry_id	number_table,
1111 	element_link_id		number_table,
1112 	assignment_id		number_table,
1113 	effective_start_date	date_table,
1114 	effective_end_date	date_table,
1115 	amount			number_table,
1116 	rate			varchar_table,
1117 	week_commencing		date_table,
1118 	recoverable_amount	number_table,
1119 	stopped			varchar_table,
1120 	dealt_with		varchar_table);
1121 	--
1122 --
1123 -- A store for all the SAP entries that potentially may be
1124 -- granted to the person.
1125 --
1126 hypothetical_entry	SAP_entry;
1127 --
1128 -- A tally of the number of weeks of the APP which are subject to stoppages.
1129 --
1130 l_stopped_weeks		number := 0;
1131 --
1132 l_high_rate	varchar2 (80) := null;
1133 l_low_rate	varchar2 (80) := null;
1134 -- RT entries prob
1135 l_no_of_absence_periods  integer := 0;
1136 --
1137 -- p_deleting passed into save_hypothetical_entries, so that logic can be
1138 -- dealt with for deleted absences.
1139 --
1140 procedure save_hypothetical_entries (p_deleting in boolean default false) is
1141 	--
1142 	-- Having generated the potential SAP entries, reconcile them with any
1143 	-- previously granted entries for the same maternity.
1144 	--
1145     cursor csr_existing_entries is
1146       --
1147       -- Get all entries and entry values for the Adoption
1148       --
1149       -- Decode the rate code to give the meaning using local variables
1150       -- populated earlier by Calculate_correct_SAP_rate
1151       -- these can then be passed directly into the hr_entry_api's and
1152       -- simplifies comparison with hypo entries
1153       --
1154       select	entry.element_entry_id,
1155         entry.element_link_id,
1156         entry.assignment_id,
1157         entry.effective_start_date,
1158         entry.effective_end_date,
1159 -- if in future we get two different rates then a decode can be added here
1160          l_high_rate RATE,
1161 --BUG 6271407 begin
1162 /*        to_date (ssp_smp_support_pkg.value
1163             (entry.element_entry_id,
1164             ssp_sap_pkg.c_week_commencing_name),
1165           'DD-MON-YYYY') WEEK_COMMENCING,*/
1166 --BUG 7563477 begin
1167 /*        fnd_date.canonical_to_date(ssp_smp_support_pkg.value
1168             (entry.element_entry_id,
1169             ssp_sap_pkg.c_week_commencing_name)) WEEK_COMMENCING,*/
1170         fnd_date.chardate_to_date(ssp_smp_support_pkg.value
1171             (entry.element_entry_id,
1172             ssp_sap_pkg.c_week_commencing_name)) WEEK_COMMENCING,
1173 --BUG 7563477 end
1174 --BUG 6271407 end
1175         to_number(ssp_smp_support_pkg.value (entry.element_entry_id,
1176               ssp_sap_pkg.c_amount_name)) AMOUNT,
1177         to_number(ssp_smp_support_pkg.value (entry.element_entry_id,
1178               ssp_sap_pkg.c_recoverable_amount_name)) RECOVERABLE_AMOUNT
1179       from	pay_element_entries_f ENTRY,
1180             per_all_assignments_f     asg
1181       where	creator_type = c_SAP_creator_type
1182       and creator_id = p_maternity_id
1183       and asg.person_id     = person.person_id
1184       and asg.assignment_id = entry.assignment_id
1185       and	entry.effective_start_date between asg.effective_start_date
1186                                                and asg.effective_end_date
1187       and not exists (
1188         --
1189         -- Do not select entries which have already had reversal action taken
1190         -- against them because they are effectively cancelled out.
1191         --
1192         select 1
1193         from pay_element_entries_f	ENTRY2
1194         where entry.element_entry_id= entry2.target_entry_id
1195         and   entry.assignment_id   = entry2.assignment_id)
1196         --
1197       and not exists (
1198         --
1199         -- Do not select reversal entries
1200         --
1201         select 1
1202         from	pay_element_links_f LINK,
1203                 pay_element_types_f TYPE
1204         where link.element_link_id = entry.element_link_id
1205         and	entry.effective_start_date between link.effective_start_date
1206                 and link.effective_end_date
1207         and link.element_type_id = type.element_type_id
1208         and	link.effective_start_date between type.effective_start_date
1209                 and type.effective_end_date
1210         and type.element_name = c_SAP_Corr_element_name);
1211 		--
1212 cursor csr_no_of_absences is
1213         --
1214         -- Get the number of distinct absences within a maternity pay period
1215         --
1216         select  count (*)
1217         from    per_absence_attendances
1218         where   person_id = person.person_id
1219         and     maternity_id = p_maternity_id;
1220          --
1221     l_ins_corr_ele  boolean;
1222     l_dummy         number;
1223     Entry_number    integer;
1224     l_ern_calc_id   number;
1225     l_ob_v_no       number;
1226     l_new_ob_v_no   number;
1227     l_proc varchar2 (72) := g_package||'save_hypothetical_entries';
1228 --
1229 -- This procedure was a private procedure in the function entitled_to_sap. I
1230 -- wanted to call it within this procedure (generate_payments) aswell, so
1231 -- instead of making it a public procedure I have copied the procedure to here.
1232 --
1233 procedure remove_stoppages is
1234         --
1235         -- Remove old system, non-overridden stoppages
1236         --
1237         cursor csr_stoppages is
1238                 --
1239                 select  stoppage_id
1240                 from    ssp_stoppages
1241                 where   user_entered <>'Y'
1242                 and     override_stoppage <> 'Y'
1243                 and     maternity_id = p_maternity_id;
1244                 --
1245         l_dummy number;
1246         l_proc varchar2 (72) := g_package||'.remove_stoppages';
1247         --
1248         begin
1249         --
1250         hr_utility.set_location (l_proc,1);
1251         --
1252         for each_stoppage in csr_stoppages LOOP
1253            ssp_stp_del.del (p_stoppage_id => each_stoppage.stoppage_id,
1254                             p_object_version_number => l_dummy);
1255         end loop;
1256         --
1257         hr_utility.set_location (l_proc,100);
1258         --
1259       end remove_stoppages;
1260 	--
1261   begin
1262     --
1263     hr_utility.set_location('Entering: '||l_proc,10);
1264     --
1265     get_SAP_correction_element (person.due_date);
1266     --
1267     -- Check each existing SaP entry in turn against all the potential new ones.
1268     --
1269     <<OLD_ENTRIES>>
1270     for old_entry in csr_existing_entries
1271     LOOP
1272       --First loop through the hypothetical entries to see if there is one
1273       --which covers the same week as the old entry and is not subject to
1274       --a stoppage.  If there isn't one, invalidate the old entry.
1275       --Assume we don't need to correct the entry until we discover otherwise:
1276       --
1277       l_ins_corr_ele := FALSE;
1278       begin
1279         entry_number := 0;
1280         if p_deleting then
1281            raise no_data_found; -- enter exception handler
1282         end if;
1283         LOOP
1284           entry_number := entry_number +1;
1285           -- Exit the loop when we find a hypothetical entry covering the
1286           -- same week as the old entry, which is not subject to a stoppage.
1287           -- If no such match is found, then we will reach the end of the
1288           -- pl/sql table and attempt to read beyond the existing rows; this
1289           -- will cause us to enter the exception handler and indicate that
1290           -- no match was found.
1291           exit when ((old_entry.week_commencing
1292              = hypothetical_entry.week_commencing (entry_number)
1293              and not hypothetical_entry.stopped (entry_number) = 'TRUE'
1294              and ssp_smp_pkg.g_smp_update = 'N')
1295              or (old_entry.effective_start_date
1296                    = hypothetical_entry.effective_start_date (entry_number)
1297                  and old_entry.week_commencing
1298                    = hypothetical_entry.week_commencing (entry_number)
1299                  and not hypothetical_entry.stopped (entry_number) = 'TRUE'
1300                  and ssp_smp_pkg.g_smp_update = 'Y'));
1301         end loop;
1302         hr_utility.trace (l_proc||' Old entry / Hypo entry time Match with values:');
1303         hr_utility.trace (l_proc||'        Rate: ' ||old_entry.rate||' / '
1304           ||hypothetical_entry.rate (Entry_number));
1305         hr_utility.trace (l_proc||'      Amount: '
1306           ||old_entry.amount||' / '
1307           ||hypothetical_entry.amount (entry_number));
1308         hr_utility.trace (l_proc||' Recoverable: '
1309           ||old_entry.recoverable_amount||' / '
1310           ||hypothetical_entry.recoverable_amount (entry_number));
1311         hr_utility.trace (l_proc||'   Week Comm: '
1312           ||hypothetical_entry.week_commencing (entry_number) );
1313         --A hypo entry covers the same week as the old one
1314         if    old_entry.rate   = hypothetical_entry.rate (entry_number)
1315           and old_entry.amount = hypothetical_entry.amount(entry_number)
1316           and old_entry.recoverable_amount
1317                    = hypothetical_entry.recoverable_amount (entry_number)
1318         then
1319           -- the hypo entry has the same values as the old one
1320           -- don't create a correction element.
1321           -- don't create a new entry
1322           hypothetical_entry.dealt_with (entry_number) := 'TRUE';
1323           hr_utility.trace (l_proc||' leave unchanged');
1324         else
1325           if ssp_smp_support_pkg.entry_already_processed
1326                                             (old_entry.element_entry_id)
1327           then l_ins_corr_ele := TRUE;
1328           hr_utility.trace (l_proc||' processed - correct it');
1329           else
1330             -- update old entry
1331             hr_utility.trace (l_proc||' unprocessed - update it');
1332             hr_entry_api.update_element_entry (
1333               p_dt_update_mode => 'CORRECTION',
1334               p_session_date => old_entry.effective_start_date,
1335               p_element_entry_id => old_entry.element_entry_id,
1336               p_input_value_id1 => g_SAP_element.rate_id,
1337               p_input_value_id2 => g_SAP_element.amount_id,
1338               p_input_value_id3 => g_SAP_element.recoverable_amount_id,
1339               p_entry_value1=> hypothetical_entry.rate (entry_number),
1340               p_entry_value2=> hypothetical_entry.amount(entry_number),
1341               p_entry_value3=>
1342                       hypothetical_entry.recoverable_amount (entry_number));
1343             --
1344             --prevent insertion of new entry
1345             --
1346             hypothetical_entry.dealt_with (entry_number) := 'TRUE';
1347           end if;
1348         end if;
1349       exception
1350         when no_data_found then
1351           -- There was no new entry which exactly matched the old entry.
1352           -- or we are deleting.
1353           entry_number := null;
1354           hr_utility.trace (l_proc||' No Old entry - Hypo entry time Match');
1355           hr_utility.trace (l_proc||' or p_deleting is true');
1356           hr_utility.trace (l_proc||' Old entry values:');
1357           hr_utility.trace (l_proc||'        Rate: '||old_entry.rate);
1358           hr_utility.trace (l_proc||'      Amount: '||old_entry.amount);
1359           hr_utility.trace (l_proc||' Recoverable: '
1360                                         ||old_entry.recoverable_amount);
1361           if ssp_smp_support_pkg.entry_already_processed
1362                                             (old_entry.element_entry_id)
1363           then l_ins_corr_ele := TRUE;
1364             hr_utility.trace (l_proc||' Old entry already processed');
1365           else
1366             hr_utility.trace (l_proc||' Old entry NOT already processed');
1367             --Old entry not already processed so delete it
1368             hr_entry_api.delete_element_entry (
1369               p_dt_delete_mode => 'ZAP',
1370               p_session_date => old_entry.effective_start_date,
1371               p_element_entry_id => old_entry.element_entry_id);
1372           end if;
1373       end;
1374       if l_ins_corr_ele
1375       then
1376         -- Create a correction element to reverse the old entry. Then create a
1377         -- brand new entry with the correct values.
1378         --
1379         hr_utility.trace (l_proc ||
1380                           ' Inserting CORRECTION entry for week commencing ' ||
1381                           to_char (old_entry.week_commencing));
1382         hr_utility.trace (l_proc||'              Old value / New value:');
1383         if entry_number is null then
1384           hr_utility.trace (l_proc||'        Rate: '
1385             ||old_entry.rate||' / NA');
1386           hr_utility.trace (l_proc||'      Amount: '
1387             ||old_entry.amount||' / NA');
1388           hr_utility.trace (l_proc||' Recoverable: '
1389             ||old_entry.recoverable_amount||' / NA');
1390         else
1391           hr_utility.trace (l_proc||'        Rate: '
1392             ||old_entry.rate||' / '
1393             ||hypothetical_entry.rate (Entry_number));
1394           hr_utility.trace (l_proc||'      Amount: '
1395             ||old_entry.amount||' / '
1396             ||hypothetical_entry.amount (entry_number));
1397           hr_utility.trace (l_proc||' Recoverable: '
1398             ||old_entry.recoverable_amount||' /'
1399             ||hypothetical_entry.recoverable_amount (entry_number));
1400         end if;
1401         --
1402         -- Determine the next available period in which to place the
1403         -- correction entry
1404         --
1405         ssp_smp_support_pkg.get_entry_details (
1406           p_date_earned  => old_entry.week_commencing,
1407           p_last_process_date => person.final_process_date,
1408           p_person_id  => person.person_id,
1409           p_element_type_id => g_SAP_Correction_element.element_type_id,
1410           p_element_link_id => old_entry.element_link_id,
1411           p_assignment_id  => old_entry.assignment_id,
1412           p_effective_start_date => old_entry.effective_start_date,
1413           p_effective_end_date => old_entry.effective_end_date,
1414           p_pay_as_lump_sum => person.pay_SAP_as_lump_sum);
1415         --
1416         -- hr_entry_api's take the lookup meanings not the lookup codes.
1417         -- converted rate codes to meanings before calling the
1418         -- api.  Later fix made old_entry (csr_existing_entries) return
1419         -- the meaning, so rate passed directly.
1420         --
1421         hr_entry_api.insert_element_entry (
1422           p_effective_start_date=> old_entry.effective_start_date,
1423           p_effective_end_date => old_entry.effective_end_date,
1424           p_element_entry_id  => l_dummy,
1425           p_target_entry_id  => old_entry.element_entry_id,
1426           p_assignment_id  => old_entry.assignment_id,
1427           p_element_link_id  => old_entry.element_link_id,
1428           p_creator_type  => c_SAP_creator_type,
1429           p_creator_id  => p_maternity_id,
1430           p_entry_type  => c_SAP_entry_type,
1431           p_input_value_id1=> g_SAP_correction_element.rate_id,
1432           p_input_value_id2=> g_SAP_correction_element.week_commencing_id,
1433           p_input_value_id3=> g_SAP_correction_element.amount_id,
1434           p_input_value_id4=> g_SAP_correction_element.recoverable_amount_id,
1435           p_entry_value1=> old_entry.rate,
1436 --          p_entry_value2=> old_entry.week_commencing,
1437           p_entry_value2  => to_char(old_entry.week_commencing,'DD-MON-YYYY'),
1438           p_entry_value3=> old_entry.amount * -1,
1439           p_entry_value4=> old_entry.recoverable_amount * -1);
1440         --
1441         --New entry will be created by brand_new_entries loop if not p_deleting
1442       end if;
1443       --
1444     end loop old_entries;
1445     --
1446     -- Having been through all the existing entries, we now check that we
1447     -- have dealt with all the newly derived entries by inserting any which
1448     -- were not flagged as dealt with during the above actions.
1449     --
1450     hr_utility.set_location (l_proc,20);
1451     --
1452     <<BRAND_NEW_ENTRIES>>
1453     begin
1454       if p_deleting then
1455         hr_utility.trace('Deleting an absence so don''t insert entries');
1456       else
1457         for new_entry in 1..g_SAP_element.maximum_APP LOOP
1458           if (not hypothetical_entry.dealt_with (new_entry) = 'TRUE')
1459             and (not hypothetical_entry.stopped (new_entry) = 'TRUE')
1460           then
1461             hr_entry_api.insert_element_entry (
1462               p_effective_start_date =>
1463                           hypothetical_entry.effective_start_date (new_entry),
1464               p_effective_end_date =>
1465                           hypothetical_entry.effective_end_date (new_entry),
1466               p_element_entry_id => l_dummy,
1467               p_assignment_id  => hypothetical_entry.assignment_id (new_entry),
1468               p_element_link_id => hypothetical_entry.element_link_id (new_entry),
1469               p_creator_type  => c_SAP_creator_type,
1470               p_creator_id  => p_maternity_id,
1471               p_entry_type  => c_SAP_entry_type,
1472               p_input_value_id1 => g_SAP_element.rate_id,
1473               p_input_value_id2 => g_SAP_element.week_commencing_id,
1474               p_input_value_id3 => g_SAP_element.amount_id,
1475               p_input_value_id4 => g_SAP_element.recoverable_amount_id,
1476               p_entry_value1  => hypothetical_entry.rate (new_entry),
1477 --            p_entry_value2  => hypothetical_entry.week_commencing (new_entry),
1478               p_entry_value2  => to_char(hypothetical_entry.week_commencing(new_entry),'DD-MON-YYYY'),
1479               p_entry_value3  => hypothetical_entry.amount (new_entry),
1480               p_entry_value4  =>
1481                           hypothetical_entry.recoverable_amount (new_entry));
1482           end if;
1483         end loop brand_new_entries;
1484       end if;
1485     exception
1486       when no_data_found then
1487         --
1488         -- We have run out of hypothetical entries to insert
1489         --
1490         null;
1491         --
1492     end;
1493     --
1494     -- Orphaned stoppages, associated with deleted absence can now be deleted
1495     -- This replaces cross product constraints that are no longer allowed.
1496     --
1497     open csr_no_of_absences;
1498     fetch csr_no_of_absences into l_no_of_absence_periods;
1499     close csr_no_of_absences;
1500     --
1501     if l_no_of_absence_periods = 0 then
1502       remove_stoppages;
1503     end if;
1504     --
1505     hr_utility.set_location(' Leaving: '||l_proc,100);
1506     --
1507   end save_hypothetical_entries;
1508 	--
1509 procedure derive_SAP_week (p_week_number in integer) is
1510 	--
1511 	-- Derive the start and end dates of the week covered by the SAP
1512 	-- payment. This is done by finding out how many weeks into the APP
1513 	-- we are and finding the offset from the start date.
1514 	--
1515 	begin
1516 	--
1517 	hr_utility.set_location ('Entering: ssp_sap_pkg.derive_SAP_week',1);
1518 	hr_utility.trace ('Entry number = '||to_char (p_week_number));
1519 	--
1520 	hypothetical_entry.week_commencing (p_week_number)
1521 		:= (person.APP_start_date + ((p_week_number -1) * 7));
1522 	--
1523 	hypothetical_entry.dealt_with (p_week_number) := 'FALSE';
1524 	hypothetical_entry.stopped (p_week_number) := 'FALSE';
1525 	hypothetical_entry.element_link_id (p_week_number) := null;
1526 	hypothetical_entry.assignment_id (p_week_number) := null;
1527 	--
1528 	hr_utility.trace ('week_commencing = '
1529 		||to_char (hypothetical_entry.week_commencing (p_week_number)));
1530 		--
1531 	hr_utility.set_location ('Leaving : ssp_sap_pkg.derive_SAP_week',100);
1532 	--
1533 	end derive_SAP_week;
1534 	--
1535 procedure Check_SAP_stoppages (p_week_number in integer) is
1536 	--
1537 	-- Find any SAP stoppage for the Adoption which overlaps a date range
1538 	--
1539 	employee_died varchar2 (30) := 'Employee died';
1540 	--
1541 	cursor csr_stoppages (p_start_date in date, p_end_date in date) is
1542 		--
1543 		-- Find any non-overridden stoppages
1544 		--
1545 		select	1
1546 		from	ssp_stoppages STP,
1547 			ssp_withholding_reasons WRE
1548 		where	stp.override_stoppage <> 'Y'
1549 		--
1550 		-- and the stoppage ovelaps the period or the stoppage is for
1551 		-- death and is prior to the period
1552 		--
1553 		and	((wre.reason <> employee_died
1554 			   and stp.withhold_from <= p_end_date
1555 			   and nvl (stp.withhold_to, hr_general.end_of_time)
1556 				>= p_start_date)
1557 			--
1558 			or (wre.reason = employee_died
1559 			   and stp.withhold_from <= p_end_date))
1560 		--
1561 		and	stp.maternity_id = p_maternity_id
1562 		and	stp.reason_id = wre.reason_id;
1563 		--
1564 	l_dummy	integer (1);
1565 	--
1566 	begin
1567 	--
1568 	hr_utility.set_location ('ssp_sap_pkg.Check_SAP_stoppages',1);
1569 	--
1570 	hypothetical_entry.stopped (p_week_number) := 'FALSE';
1571 	--
1572 	open csr_stoppages (
1573 		hypothetical_entry.week_commencing (p_week_number),
1574 		ssp_smp_support_pkg.end_of_week
1575 			(hypothetical_entry.week_commencing (p_week_number)));
1576 	--
1577 	fetch csr_stoppages into l_dummy;
1578 	--
1579 	if csr_stoppages%found
1580 	then
1581 	  --
1582 	  -- There is an overlap between the SAP week and a stoppage so no SAP
1583 	  -- is payable.
1584 	  --
1585 	  hypothetical_entry.stopped (p_week_number) := 'TRUE';
1586 	  --
1587 	  hr_utility.trace ('Entry is STOPPED');
1588 	  --
1589 	  -- Keep a tally of the number of stopped weeks
1590 	  --
1591 	  l_stopped_weeks := l_stopped_weeks +1;
1592 	end if;
1593 	--
1594 	close csr_stoppages;
1595 	--
1596 	hr_utility.set_location ('ssp_sap_pkg.Check_SAP_stoppages',10);
1597 	--
1598 	end Check_SAP_stoppages;
1599 	--
1600 procedure Calculate_correct_SAP_rate (p_week_number in number) is
1601 	--
1602 	-- The entry API takes the lookup meanings so we must find
1603 	-- the meanings rather than the codes for SAP rates.
1604 	--
1605 	cursor csr_rate_meaning (p_rate_band varchar2) is
1606 		--
1607 	        select	meaning
1608 		from	hr_lookups
1609 		where	lookup_type = 'SAP_RATES'
1610 		and	lookup_code = p_rate_band;
1611 		--
1612 	begin
1613 	--
1614 	hr_utility.set_location ('ssp_sap_pkg.Calculate_correct_SAP_rate',1);
1615 	--
1616 	if l_high_rate is null then
1617 	  --
1618 	  -- Get the meanings for the rate bands
1619 	  --
1620 	  -- Get the higher rate band
1621 	  --
1622 	  open csr_rate_meaning ('STD');
1623 	  fetch csr_rate_meaning into l_high_rate;
1624 	  close csr_rate_meaning;
1625 
1626 	end if;
1627 	--
1628 /*
1629 	if (p_week_number - l_stopped_weeks)
1630 		<= g_SMP_element.period_at_higher_rate
1631 	then
1632 	  hr_utility.set_location ('ssp_smp_pkg.Calculate_correct_SMP_rate',1);
1633 	  --
1634 	  -- We have not yet given the employee all their higher rate weeks
1635 	  --
1636 */
1637 	  hypothetical_entry.rate (p_week_number) := l_high_rate;
1638 /*
1639 	else
1640 	  hypothetical_entry.rate (p_week_number) := l_low_rate;
1641 	end if;
1642 */
1643 	--
1644 	hr_utility.trace ('SAP Rate = '
1645 		||hypothetical_entry.rate (p_week_number));
1646 		--
1647 	hr_utility.set_location ('ssp_sap_pkg.Calculate_correct_SAP_rate',10);
1648 	--
1649 	end Calculate_correct_SaP_rate;
1650 	--
1651 procedure Calculate_SAP_amounts (p_week_number in integer, p_APP_start_date in date) is
1652 	--
1653 	begin
1654 	--
1655 	hr_utility.set_location('Entering: ssp_sAp_pkg.Calculate_SaP_amounts',1);
1656 	--
1657 	-- Get the SAP element for each week in case the SAP rate has changed
1658 	--
1659 	get_SAP_element (hypothetical_entry.week_commencing (p_week_number));
1660 	--
1661     hypothetical_entry.amount (p_week_number)
1662 		:= least (round (
1663 			(average_earnings * g_SAP_element.SAP_rate)
1664 				+ 0.0049,2),
1665 			g_SAP_element.STANDARD_SAP_RATE);
1666 	--
1667 	hypothetical_entry.recoverable_amount (p_week_number)
1668 		:= round (hypothetical_entry.amount (p_week_number)
1669 			* g_SAP_element.recovery_rate,2);
1670 	--
1671 	hr_utility.trace ('SAP amount = '
1672 		||to_char (hypothetical_entry.amount (p_week_number)));
1673 	hr_utility.trace ('Recoverable amount = '
1674 	||to_char (hypothetical_entry.recoverable_amount (p_week_number)));
1675 	--
1676 	hr_utility.set_location('Leaving : ssp_sap_pkg.Calculate_SAP_amounts',100);
1677 	--
1678 	end calculate_SAP_amounts;
1679 	--
1680 	procedure check_parameters is
1681 	begin
1682 	hr_api.mandatory_arg_error (
1683 		p_api_name	=> l_proc,
1684 		p_argument	=> 'maternity_id',
1685 		p_argument_value=> p_maternity_id);
1686 		--
1687 	end check_parameters;
1688 	--
1689 begin
1690 --
1691 hr_utility.set_location ('ssp_sap_pkg.generate_payments',1);
1692 --
1693 check_parameters;
1694 --
1695 <<SAP_WEEKS>>
1696 --
1697 if person.APP_start_date is not null then
1698    for week_number in 1..g_SAP_element.maximum_APP
1699    LOOP
1700       --
1701       -- Derive hypothetical entries ie those entries which would be applied for a
1702       -- completely new maternity. Store them internally because we must check
1703       -- previously created entries before applying the hypothetical entries to the
1704       -- database.
1705       --
1706       Derive_SAP_week			(week_number);
1707       Check_SAP_stoppages			(week_number);
1708       Calculate_correct_SAP_rate		(week_number);
1709       Calculate_SAP_amounts		(week_number, person.APP_start_date);
1710       --
1711       if (hypothetical_entry.stopped (week_number) = 'FALSE') then
1712       --
1713       -- Get the entry details unless the entry has been stopped (in which case
1714       -- we do not need the entry details and errors may occur if we call the
1715       -- procedure; eg the woman's assignment ends)
1716       --
1717          ssp_smp_support_pkg.get_entry_details	(
1718             p_date_earned          => hypothetical_entry.week_commencing
1719                                                 (week_number),
1720             p_pay_as_lump_sum      => person.pay_SAP_as_lump_sum,
1721             p_last_process_date    => person.final_process_date,
1722             p_person_id            => person.person_id,
1723             p_element_type_id      => g_SAP_element.element_type_id,
1724             p_element_link_id      => hypothetical_entry.element_link_id
1725                                                 (week_number),
1726             p_assignment_id        => hypothetical_entry.assignment_id
1727                                                 (week_number),
1728             p_effective_start_date => hypothetical_entry.effective_start_date
1729                                                 (week_number),
1730             p_effective_end_date   => hypothetical_entry.effective_end_date
1731                                                 (week_number));
1732       end if;
1733    end loop SAP_weeks;
1734 end if;
1735 --
1736 Save_hypothetical_entries(p_deleting);
1737 --
1738 end generate_payments;
1739 --
1740 --------------------------------------------------------------------------------
1741 procedure SAP_control (p_maternity_id	in number,
1742                        p_deleting       in boolean default FALSE) is
1743 --
1744 -- p_deleting parameter added to deal with absences being deleted, without
1745 -- maternity being deleted.
1746 --
1747 cursor csr_maternity is
1748 	--
1749 	-- Find out if the maternity exists
1750 	--
1751 	select	1
1752 	from	ssp_maternities
1753 	where	maternity_id = p_maternity_id;
1754 	--
1755 cursor csr_entries is
1756 	--
1757 	-- Get all element entries associated with a maternity
1758 	--
1759 select /*+ ORDERED use_nl(paa,paaf,etype,entry) */
1760        entry.element_entry_id,
1761        entry.effective_start_date
1762 from   per_absence_attendances PAA,
1763        per_all_assignments_f   PAAF,
1764        pay_element_entries_f   entry
1765 where  PAA.maternity_id = p_maternity_id
1766 and    PAAF.person_id = PAA.person_id
1767 and    entry.creator_type = 'M'
1768 and    entry.creator_id = p_maternity_id
1769 and    entry.assignment_id = paaf.assignment_id;
1770         --
1771 cursor csr_count_absences is
1772 select count(*)
1773 from   ssp_maternities mat,
1774        per_absence_attendances ab
1775 where  mat.maternity_id = p_maternity_id
1776 and    ab.person_id = mat.person_id
1777 and    ab.maternity_id = mat.maternity_id;
1778         --
1779 l_count number;
1780 l_dummy	number;
1781 l_proc	varchar2 (72) := g_package||'SAP_control';
1782 --
1783 begin
1784 --
1785 hr_utility.set_location (l_proc,1);
1786 --
1787 open csr_maternity;
1788 fetch csr_maternity into l_dummy;
1789 --
1790 if csr_maternity%found then
1791    --
1792    -- Recalculate SAP
1793    --
1794    if entitled_to_SAP (p_maternity_id) then
1795       open csr_count_absences;
1796       fetch csr_count_absences into l_count;
1797       close csr_count_absences;
1798       if l_count > 0 then
1799           generate_payments (p_maternity_id, false);
1800       else
1801           generate_payments (p_maternity_id, p_deleting);
1802       end if;
1803    elsif p_deleting then
1804         -- not entitled but deleting absence then
1805       generate_payments (p_maternity_id, p_deleting);
1806    end if;
1807 else
1808    --
1809    -- The maternity may have been deleted. Remove any element entries associated
1810    -- with it (the absences, stoppages and medicals are handled by constraints).
1811    --
1812    for obsolete in csr_entries LOOP
1813       hr_utility.trace (l_proc||'	Deleting element entry_id '||
1814                         to_char (obsolete.element_entry_id));
1815       hr_utility.trace (l_proc||'-------------------------------------------');
1816       --
1817       hr_entry_api.delete_element_entry (
1818                            p_dt_delete_mode    => 'ZAP',
1819                            p_session_date      => obsolete.effective_start_date,
1820                            p_element_entry_id  => obsolete.element_entry_id);
1821    end loop;
1822 end if;
1823 --
1824 hr_utility.set_location (l_proc,100);
1825 --
1826 end SAP_control;
1827 --
1828 --------------------------------------------------------------------------------
1829 -- Return the maximum APP date
1830 --
1831 function get_max_SAP_date(p_maternity_id in number) return date is
1832     l_due_date  date;
1833     l_mpp_date  date;
1834     l_max_mpp   number;
1835 
1836     cursor get_person_details is
1837     select mpp_start_date, due_date
1838     from   ssp_maternities
1839     where  maternity_id = p_maternity_id;
1840 
1841     cursor get_maximum_mpp is
1842     select to_number(element_information3)
1843     from   pay_element_types_f
1844     where  element_name = c_SAP_element_name
1845     and	   l_due_date between effective_start_date and effective_end_date;
1846 begin
1847     open get_person_details;
1848     fetch get_person_details into l_mpp_date, l_due_date;
1849     close get_person_details;
1850 
1851     open get_maximum_mpp;
1852     fetch get_maximum_mpp into l_max_mpp;
1853     close get_maximum_mpp;
1854 
1855     if l_mpp_date is not null then
1856        return trunc(l_mpp_date + (l_max_mpp * 7));
1857     else
1858        return l_due_date;
1859     end if;
1860 end;
1861 --------------------------------------------------------------------------------
1862 end ssp_SAP_pkg;