DBA Data[Home] [Help]

PACKAGE BODY: APPS.SSP_APAD_PKG

Source


1 package body SSP_APAD_PKG as
2 /*$Header: spapadapi.pkb 120.3 2011/05/02 15:14:31 npannamp noship $
3 +==============================================================================+
4 |                       Copyright (c) 1994 Oracle Corporation                  |
5 |                          Redwood Shores, California, USA                     |
6 |                               All rights reserved.                           |
7 +==============================================================================+
8 --
9 Name
10 	Additional Statutory Paternity Pay Adoption Business Process
11 --
12 Purpose
13 	To perform calculation of entitlement and payment for APAD purposes
14 --
15 History
16 	13 Nov 10       npannamp   9897338  Created from SSP_PAD_PKG
17 	27 Nov 10       npannamp   9897338  Added check_disruption_date.
18                                             Modified stoppages and ASPP logic.
19         31 Dec 10       npannamp   10326113 Fixed issue with delete absence.
20         02 May 11       npannamp   12312795 Modified LATEST_ASPPP_START_DATE func.
21 */
22 --------------------------------------------------------------------------------
23 g_package  varchar2(33) := '  ssp_APAD_pkg.';  -- Global package name
24 --
25 
26 --------------------------------------------------------------------------------
27 -- Get details of initial paternity leave for a paternity
28 --
29 cursor csr_absence_details (p_maternity_id in number) is
30 select	absence.absence_attendance_id,
31 	absence.date_start,
32 	nvl (absence.date_end, hr_general.end_of_time) date_end,
33 	absence.date_notification,
34 	absence.accept_late_notification_flag
35 from    per_absence_attendances	ABSENCE
36 where   absence.maternity_id = p_maternity_id
37 and     absence.absence_attendance_id =
38          (select min(paa_tab.absence_attendance_id)
39           from per_absence_attendances paa_tab
40           where paa_tab.maternity_id = absence.maternity_id);
41 --------------------------------------------------------------------------------
42 --
43 -- Get details of the maternal woman
44 --
45 cursor csr_personal_details (p_maternity_id in number) is
46 select	maternity.person_id,
47 	maternity.due_date,
48 	ssp_APAD_pkg.MATCHING_WEEK_OF_ADOPTION (MATCHING_DATE) MW,
49 	MATCHING_DATE MATCHING_DATE,
50         PLACEMENT_DATE PLACEMENT_DATE,
51         DISRUPTED_PLACEMENT_DATE DISRUPTED_PLACEMENT_DATE,
52 	maternity.maternity_id,
53 	maternity.actual_birth_date,
54 	maternity.live_birth_flag,
55 	maternity.start_date_with_new_employer,
56 	maternity.MPP_start_date ASPP_start_date,
57 	maternity.notification_of_birth_date,
58 	maternity.start_date_maternity_allowance,
59 	maternity.pay_SMP_as_lump_sum pay_APAD_as_lump_sum,
60         maternity.partner_return_to_work partner_return_date,   -- newly added columns
61         maternity.partner_death_date partner_date_of_death, -- newly added columns
62         maternity.partner_stat_pay_start_date, -- newly added columns
63         person.date_of_death,
64         service.date_start,
65 	nvl (service.final_process_date, hr_general.end_of_time) FINAL_PROCESS_DATE
66 from   	ssp_maternities				MATERNITY,
67 	per_all_people_f				PERSON,
68 	per_periods_of_service			SERVICE
69 where   person.person_id = maternity.person_id
70 and	person.person_id = service.person_id
71 and	maternity.maternity_id = p_maternity_id
72 and	service.date_start between person.effective_start_date
73 				and person.effective_end_date
74 and     service.date_start = (select max(serv.date_start)
75                               from   per_periods_of_service serv
76                               where  serv.person_id = person.person_id);
77 --------------------------------------------------------------------------------
78 person	                 csr_personal_details%rowtype;
79 g_APAD_element            csr_APAD_element_details%rowtype;
80 g_APAD_Correction_element csr_APAD_element_details%rowtype;
81 --------------------------------------------------------------------------------
82 l_sunday  varchar2(100) := to_char(to_date('07/01/2001','DD/MM/YYYY'),'DAY');
83 
84 function MATCHING_WEEK_OF_ADOPTION (p_matching_date in date) return date is
85 --
86 -- Returns the date on which the MW starts
87 --
88 -- p_matching_date comes from the person's maternity record
89 -- MW is the Sunday prior to MATCHING_WEEK DATE
90 --
91 l_MW  date := (next_day (p_matching_date,l_sunday) -7);
92 --
93 begin
94 --
95   return l_MW;
96 --
97 end MATCHING_WEEK_OF_ADOPTION;
98 --------------------------------------------------------------------------------
99 Function CONTINUOUS_EMPLOYMENT_DATE (p_matching_date in date) return date is
100 --
101 l_APAD_element			csr_APAD_element_details%rowtype;
102 l_Continuously_employed_since	date;
103 l_saturday varchar2(100) := to_char(to_date('06/01/2001','DD/MM/YYYY'),'DAY');
104 --
105 begin
106 --
107   open  csr_APAD_element_details (p_matching_date,c_APAD_element_name);
108   fetch csr_APAD_element_details into l_APAD_element;
109   close csr_APAD_element_details;
110   --
111   l_Continuously_employed_since :=
112           next_day(next_day(
113                     MATCHING_WEEK_OF_ADOPTION (p_matching_date) ,l_saturday)
114           - (l_APAD_element.continuous_employment_period),l_saturday);
115   --
116   return l_Continuously_employed_since;
117   --
118 end continuous_employment_date;
119 --------------------------------------------------------------------------------
120 procedure get_APAD_correction_element (p_effective_date in date) is
121 --
122 l_proc        varchar2(72) := g_package||'get_APAD_correction_element';
123 --
124   procedure check_parameters is
125   begin
126   --
127     hr_utility.trace (l_proc||'	p_effective_date = '
128 	||to_char (p_effective_date));
129   --
130     hr_api.mandatory_arg_error (
131 		p_api_name	=> l_proc,
132 		p_argument	=> 'effective_date',
133 		p_argument_value=> p_effective_date);
134   end check_parameters;
135   --
136 begin
137 --
138   hr_utility.set_location (l_proc,1);
139   --
140   check_parameters;
141   --
142   open  csr_APAD_element_details (p_effective_date,c_APAD_Corr_element_name);
143   fetch csr_APAD_element_details into g_APAD_Correction_element;
144   close csr_APAD_element_details;
145   --
146   hr_utility.set_location (l_proc,100);
147   --
148 end get_APAD_correction_element;
149 --------------------------------------------------------------------------------
150 procedure get_APAD_element (p_effective_date in date) is
151 --
152 l_proc        varchar2(72) := g_package||'get_APAD_element';
153 --
154   procedure check_parameters is
155   begin
156   --
157     hr_utility.trace (l_proc||'     p_effective_date = '
158 		||to_char (p_effective_date));
159     --
160 	hr_api.mandatory_arg_error (
161 		p_api_name	=> l_proc,
162 		p_argument	=> 'effective_date',
163 		p_argument_value=> p_effective_date);
164     --
165   end check_parameters;
166 --
167 begin
168 --
169   hr_utility.set_location (l_proc,1);
170   --
171   check_parameters;
172   --
173   open  csr_APAD_element_details (p_effective_date,c_APAD_element_name);
174   fetch csr_APAD_element_details into g_APAD_element;
175   close csr_APAD_element_details;
176   --
177   hr_utility.set_location (l_proc,100);
178   --
179 end get_APAD_element;
180 --------------------------------------------------------------------------------
181 function EARLIEST_ASPPP_START_DATE (p_placement_date in date) return date is
182 --
183 l_earliest_ASPPP_start	date;
184 l_APAD_element		csr_APAD_element_details%rowtype;
185 --
186 begin
187 --
188   open  csr_APAD_element_details (p_placement_date,c_APAD_element_name);
189   fetch csr_APAD_element_details into l_APAD_element;
190   close csr_APAD_element_details;
191   --
192   l_earliest_ASPPP_start := p_placement_date
193 				+ (l_APAD_element.earliest_start_of_ASPPP);
194 
195   return l_earliest_ASPPP_start;
196 --
197 end earliest_ASPPP_start_date;
198 --------------------------------------------------------------------------------
199 function LATEST_ASPPP_START_DATE (p_placement_date in date, p_mpp_start_date in date) return date is
200 --
201 l_latest_ASPPP_start	date;
202 l_APAD_element		csr_APAD_element_details%rowtype;
203 --
204 begin
205 --
206   open  csr_APAD_element_details (p_placement_date,c_APAD_element_name);
207   fetch csr_APAD_element_details into l_APAD_element;
208   close csr_APAD_element_details;
209   -- bug 12312795 fix
210   -- l_latest_ASPPP_start := add_months(p_mpp_start_date, l_APAD_element.latest_end_of_APL) - 14;
211   l_latest_ASPPP_start := add_months(p_placement_date, l_APAD_element.latest_end_of_APL) - 14;
212 
213   return l_latest_ASPPP_start;
214 --
215 end latest_ASPPP_start_date;
216 --------------------------------------------------------------------------------
217 /* function partner_app_end_date
218    p_partner_app_start_date - The date on which the employee starts his ASPP
219    p_partner_return_to_work - The date on which the employee partner returns to work.
220 
221    if p_partner_return_to_work is passed as null, then the supposed end date of employee partners APP is returned,
222    which is 39 weeks.
223    if p_partner_return_to_work is passed with the return to work date of employee's partner, then the date returned
224    is the end date of APP for partner in the week before the Return to work.
225 */
226 
227 function partner_app_end_date (p_partner_app_start_date	in date, p_partner_return_to_work in date) return date is
228 --
229 cursor csr_ele_details (p_effective_date date default sysdate, p_element_name varchar2) is
230 	select	ele1.element_type_id,
231 		ele1.effective_start_date,
232 		ele1.effective_end_date,
233 		to_number (ele1.element_information3) * 7  MAXIMUM_WEEKS
234 	from	pay_element_types_f ele1
235 	where	ele1.element_name = p_element_name
236 	and	p_effective_date between ele1.effective_start_date
237 					and ele1.effective_end_date;
238 l_partner_app_end_date date;
239 l_max_sppa_days number;
240 l_ele_details csr_ele_details%rowtype;
241 --
242 begin
243   --
244   if p_partner_return_to_work is not null then
245      l_partner_app_end_date := p_partner_return_to_work -1;
246   else
247      open csr_ele_details(p_partner_app_start_date, 'Statutory Adoption Pay');
248      fetch csr_ele_details into l_ele_details;
249      if csr_ele_details%found then
250         l_partner_app_end_date := p_partner_app_start_date + l_ele_details.maximum_weeks;
251      else
252         null;
253      end if;
254      close csr_ele_details;
255   end if;
256   --
257   return l_partner_app_end_date;
258 --
259 end partner_app_end_date;
260 --------------------------------------------------------------------------------
261 function MATERNITY_RECORD_EXISTS (p_person_id in number) return boolean is
262 --
263 cursor maternity_record is
264 select 1
265 from   ssp_maternities
266 where  person_id = p_person_id;
267 --
268 l_dummy	                  number (1);
269 l_maternity_record_exists boolean;
270 --
271 begin
272 --
273   open  maternity_record;
274   fetch maternity_record into l_dummy;
275   l_maternity_record_exists := maternity_record%found;
276   close maternity_record;
277   --
278   return l_maternity_record_exists;
279 --
280 end maternity_record_exists;
281 --------------------------------------------------------------------------------
282 function AVERAGE_EARNINGS return number is
283 --
284 l_average_earnings  number       := null;
285 l_effective_date    date         := null;
286 l_dummy		    number;
287 l_dummy2	    number; -- nocopy fix, placeholder variable
288 l_user_entered	    varchar2(30) := 'N';  --DFoster 1304683
289 l_absence_category  varchar2(30) := 'GB_ADDL_PAT_ADOPT';  --DFoster 1304683
290 l_payment_periods   number       := null; --DFoster 1304683
291 l_proc		    varchar2(72) := g_package||'average_earnings';
292 --
293 cursor csr_average_earnings is
294 select average_earnings_amount
295 from   ssp_earnings_calculations
296 where  person_id = person.person_id
297 and    effective_date = l_effective_date;
298 --
299 begin
300 --
301   hr_utility.set_location ('Entering '||l_proc,1);
302   --
303   l_effective_date := greatest(person.MW, person.date_start);
304   --
305   open csr_average_earnings;
306   fetch csr_average_earnings into l_average_earnings;
307 
308   if csr_average_earnings%notfound
309   then
310     ssp_ern_ins.ins (p_earnings_calculations_id  => l_dummy,
311                      p_object_version_number     => l_dummy2,
312                      p_person_id                 => person.person_id,
313                      p_effective_date            => l_effective_date,
314                      p_average_earnings_amount   => l_average_earnings,
315         	     p_user_entered	         => l_user_entered,     --DFoster 1304683
316         	     p_absence_category		 => l_absence_category, --DFoster 1304683
317         	     p_payment_periods		 => l_payment_periods); --DFoster 1304683
318   end if;
319   --
320   close csr_average_earnings;
321   --
322   hr_utility.set_location ('Leaving '||l_proc,10);
323   --
324   return l_average_earnings;
325 --
326 end average_earnings;
327 --------------------------------------------------------------------------------
328 function entitled_to_APAD (p_maternity_id in number) return boolean is
329 --
330 -- See header for description of this procedure.
331 --
332 no_prima_facia_entitlement	exception;
333 invalid_absence_date		exception;
334 l_work_start_date		date := hr_general.end_of_time;
335 stoppage_end_date		date := null;
336 no_of_absence_periods		integer := 0;
337 l_proc                  	varchar2(72) := g_package||'entitled_to_APAD';
338 l_keep_stoppages                boolean default FALSE;
339 l_partner_app_end_date date := null;
340 --
341 --
342 cursor csr_no_of_absences is
343 select count (*)
344 from   per_absence_attendances
345 where  person_id = person.person_id
346 and    maternity_id = p_maternity_id
347 and    absence_attendance_id =
348         (select min(paa_tab.absence_attendance_id)
349          from per_absence_attendances paa_tab
350          where paa_tab.maternity_id = p_maternity_id);
351 --
352 cursor csr_check_if_existing_entries is
353 select /*+ ORDERED use_nl(paa,paaf,etype,entry) */
354        entry.element_entry_id,
355        entry.effective_start_date
356 from   per_all_assignments_f   PAAF,
357        pay_element_types_f     ETYPE,
358        pay_element_entries_f   ENTRY
359 where  PAAF.person_id = person.person_id
360 and    ETYPE.element_name = c_APAD_element_name
361 and    ETYPE.legislation_code = 'GB'
362 and    ENTRY.element_type_id = ETYPE.element_type_id
363 and    ENTRY.creator_type = c_APAD_creator_type
364 and    ENTRY.creator_id = p_maternity_id
365 and    ENTRY.assignment_id = PAAF.assignment_id
366 and not exists (
367                --
368                -- Do not select entries which have already had reversal action
369                -- taken against them because they are effectively cancelled out.
370                --
371                select 1
372                from   pay_element_entries_f ENTRY2
373                where  entry.element_entry_id  = entry2.target_entry_id
374                and    entry.assignment_id     = entry2.assignment_id)
375                  --
376 and not exists (
377                --
378                -- Do not select reversal entries
379                --
380                select 1
381                from   pay_element_links_f LINK,
382                       pay_element_types_f TYPE
383                where  link.element_link_id = entry.element_link_id
384                and    entry.effective_start_date between link.effective_start_date and link.effective_end_date
385                and    link.element_type_id = type.element_type_id
386                and    link.effective_start_date between type.effective_start_date and type.effective_end_date
387                and    type.element_name = c_APAD_Corr_element_name);
388 --
389 l_existing_entries              csr_check_if_existing_entries%rowtype;
390 --
391   procedure create_stoppage (
392   --
393   -- Create a stoppage of payment for APAD
394   --
395   p_reason        in varchar2,
396   p_withhold_from in date,
397   p_withhold_to	  in date default null) is
398   --
399   l_proc        varchar2(72) := g_package||'create_stoppage';
400   l_dummy       number;
401   l_reason_id	number;
402 	--
403     procedure check_parameters is
404     --
405     begin
406     --
407       hr_utility.trace (l_proc||'	p_reason = '||p_reason);
408       hr_utility.trace (l_proc||'	withhold from '||to_char (p_withhold_from));
409       hr_utility.trace (l_proc||'	withhold to '||to_char (p_withhold_to));
410       --
411       hr_api.mandatory_arg_error (
412 			p_api_name	=> l_proc,
413 			p_argument	=> 'reason',
414 			p_argument_value=> p_reason);
415 			--
416       hr_api.mandatory_arg_error (
417 			p_api_name      => l_proc,
418 			p_argument      => 'withhold_from',
419 			p_argument_value=> p_withhold_from);
420 			--
421     end check_parameters;
422 		--
423   begin
424   --
425     hr_utility.set_location (l_proc,1);
426     --
427     check_parameters;
428     --
429     l_reason_id := ssp_smp_support_pkg.withholding_reason_id (
430       	                        g_APAD_element.element_type_id,
431 				p_reason);
432     --
433     if not ssp_smp_support_pkg.stoppage_overridden (
434                           	p_maternity_id => p_maternity_id,
435 				p_reason_id => l_reason_id)
436     then
437     --
438     -- Only create the stoppage if there is not already a stoppage marked
439     -- as overridden. Thus, overriding a stoppage effectively blocks that
440     -- reason being used to withhold payment for this person.
441     --
442       ssp_stp_ins.ins (p_withhold_from => p_withhold_from,
443                        p_withhold_to   => p_withhold_to,
444 		       p_stoppage_id   => l_dummy,
445 		       p_object_version_number => l_dummy,
446 		       p_maternity_id	=> p_maternity_id,
447 		       p_user_entered  => 'N',
448 		       p_reason_id     => l_reason_id);
449     else
450       hr_utility.trace (l_proc||'	Stoppage is overridden');
451     end if;
452     --
453     hr_utility.set_location (l_proc,100);
454     --
455   end create_stoppage;
456   --
457   procedure remove_stoppages is
458   --
459   -- Remove old system, non-overridden stoppages
460   --
461   cursor csr_stoppages is
462   select stoppage_id
463   from   ssp_stoppages
464   where  user_entered <>'Y'
465   and    override_stoppage <> 'Y'
466   and    maternity_id = p_maternity_id;
467   --
468   l_dummy number;
469   l_proc  varchar2 (72) := g_package||'remove_stoppages';
470   --
471   begin
472   --
473     hr_utility.set_location (l_proc,1);
474     --
475     for each_stoppage in csr_stoppages LOOP
476        ssp_stp_del.del (p_stoppage_id => each_stoppage.stoppage_id,
477                         p_object_version_number => l_dummy);
478     end loop;
479     --
480     hr_utility.set_location (l_proc,100);
481     --
482   end remove_stoppages;
483   --
484   procedure check_employment_end is
485 
486   cursor csr_termination_date is
487   select actual_termination_date
488   from   per_periods_of_service
489   where  person_id = person.person_id
490   -- 3516539 Added condition to obtain termination date for latest assignment
491   and    period_of_service_id = (select max(period_of_service_id)
492     				 from   per_periods_of_service ppos
493                                  where  ppos.person_id = person.person_id);
494   --
495   l_termination_date date := null;
496   l_proc  varchar2 (72)   := g_package||'check_employment_end';
497   --
498   begin
499     --
500     hr_utility.set_location (l_proc,1);
501     --
502     open  csr_termination_date;
503     fetch csr_termination_date into l_termination_date;
504     close csr_termination_date;
505     --
506     if l_termination_date < person.placement_date then
507       --
508       -- Stop all APAD payment for the Adoption because the person left
509       -- before the APP start date.
510       --
511       create_stoppage (p_withhold_from => person.placement_date,
512                        p_reason        => 'Not employed on APL First week');
513     end if;
514     --
515     hr_utility.set_location (l_proc,100);
516     --
517   end check_employment_end;
518   --
519   procedure check_continuity_rule is
520   --
521   -- Check that the person has the right amount of continuous service to
522   -- qualify for APAD
523   --
524   cursor period_of_service is
525   --
526   -- Check the period of service length up to the MW start date
527   --
528   select 1
529   from   per_periods_of_service
530   where  person_id = person.person_id
531   and    date_start <= ssp_APAD_pkg.continuous_employment_date
532 			        	(person.matching_date)
533   and    nvl (actual_termination_date, hr_general.end_of_time)
534 				>= person.MW;
535   --
536   l_dummy number (1);
537   l_proc  varchar2 (72) := g_package||'check_continuity_rule';
538   --
539   begin
540   --
541     hr_utility.set_location (l_proc,1);
542     --
543     open period_of_service;
544     fetch period_of_service into l_dummy;
545     --
546     if period_of_service%notfound then
547       --
548       -- Stop all APAD payment for the Adoption because the person has not
549       -- been continuously employed for long enough.
550       --
551       create_stoppage (p_withhold_from => person.ASPP_start_date,
552                        p_reason        => 'Insufficient employment');
553     end if;
554     --
555     close period_of_service;
556     --
557     hr_utility.set_location (l_proc,100);
558     --
559   end check_continuity_rule;
560   --
561   procedure check_partner_app_days is
562 
563   l_proc varchar2 (72) := g_package||'check_partner_app_days';
564   --
565   l_latest_ASPPP_start    date;
566   l_APAD_element         csr_APAD_element_details%rowtype;
567   --
568   begin
569   --
570     hr_utility.set_location (l_proc,1);
571     --
572     open  csr_APAD_element_details (person.placement_date,c_APAD_element_name);
573     fetch csr_APAD_element_details into l_APAD_element;
574     close csr_APAD_element_details;
575     --
576     if (partner_app_end_date(person.partner_stat_pay_start_date, null) -
577        partner_app_end_date(person.partner_stat_pay_start_date, nvl(person.partner_return_date, person.partner_date_of_death))) <
578        (l_APAD_element.MIN_APL_WEEKS * 7)
579     then
580       create_stoppage (p_withhold_from => person.ASPP_start_date ,
581                        p_reason        => 'Partner APP less than 2 weeks');
582     end if;
583     --
584     hr_utility.set_location (l_proc,100);
585     --
586   end check_partner_app_days;
587 
588   procedure check_start_date is
589 
590   l_proc varchar2 (72) := g_package||'check_start_date';
591   --
592   l_latest_ASPPP_start    date;
593   l_APAD_element         csr_APAD_element_details%rowtype;
594   l_mother_death varchar2(2) := 'N';
595   --
596   begin
597   --
598     hr_utility.set_location (l_proc,1);
599     --
600     open  csr_APAD_element_details (person.placement_date,c_APAD_element_name);
601     fetch csr_APAD_element_details into l_APAD_element;
602     close csr_APAD_element_details;
603     --
604     l_partner_app_end_date := partner_app_end_date(person.partner_stat_pay_start_date, null);
605     hr_utility.set_location (l_proc,2);
606 
607     if person.partner_date_of_death is not null and
608        add_months(person.placement_date, 12) > person.partner_date_of_death
609     then
610        hr_utility.set_location (l_proc,4);
611        l_mother_death := 'Y';
612     end if;
613 
614 /* If employee APL is after partner APP end date, then ASPP payment should stop from ASPP Start date */
615       if person.ASPP_start_date > l_partner_app_end_date
616       then
617         hr_utility.set_location (l_proc,6);
618         create_stoppage (p_withhold_from => person.ASPP_start_date,
619                          p_reason        => 'Partner Max APP weeks over');
620       else
621 
622       /* If employee APL goes beyond partner APP end date, then ASPP payment should stop on partners APP end date */
623         if ((person.ASPP_start_date + (l_APAD_element.MAX_APL_WEEKS*7) >  l_partner_app_end_date ) and
624             (l_mother_death = 'N'))
625         then
626           hr_utility.set_location (l_proc,7);
627           create_stoppage (p_withhold_from => l_partner_app_end_date,
628                            p_reason        => 'Max ASPP Period Exceeded');
629         end if;
630 
631         if ((person.ASPP_start_date + (l_APAD_element.MAX_APL_MOM_DEATH_WEEKS*7) >  l_partner_app_end_date ) and
632             (l_mother_death = 'Y'))
633         then
634           hr_utility.set_location (l_proc,8);
635           create_stoppage (p_withhold_from => l_partner_app_end_date,
636                            p_reason        => 'Max ASPP Period Exceeded');
637         end if;
638       end if;
639 
640     --
641     hr_utility.set_location (l_proc,100);
642     --
643   end check_start_date;
644   --
645   procedure check_death is
646   --
647   -- APAD ceases after the death of the woman.
648   --
649   l_proc varchar2 (72) := g_package||'check_death';
650   --
651   cursor csr_check_death is
652   select ppf.date_of_death
653   from   per_all_people_f ppf
654   where  ppf.person_id = person.person_id
655   and    ppf.date_of_death is not null;
656 
657   l_death_date date;
658 
659   begin
660   --
661     hr_utility.set_location (l_proc,1);
662     --
663     -- APAD ceases on the Saturday following death
664     --
665     l_death_date := null;
666     --
667     open  csr_check_death;
668     fetch csr_check_death into l_death_date;
669     close csr_check_death;
670     --
671     if l_death_date is not null then
672        create_stoppage (p_withhold_from => ssp_smp_support_pkg.end_of_rolling_week(
673                                            person.ASPP_start_date, l_death_date) +1,
674                         p_reason => 'Employee died');
675     end if;
676     --
677     hr_utility.set_location (l_proc,100);
678     --
679   end check_death;
680   --
681   procedure check_disruption_date is
682   begin
683       if person.disrupted_placement_date is not null
684       then
685          create_stoppage (p_withhold_from => ssp_smp_support_pkg.end_of_rolling_week(
686                                            person.ASPP_start_date, person.disrupted_placement_date) +1,
687                         p_reason => 'Disruption of the Placement');
688       end if;
689   end check_disruption_date;
690   --
691   procedure check_average_earnings is
692   --
693   -- The person must earn enough to qualify for APAD
694   --
695   l_proc                   varchar2 (72) := g_package||'check_average_earnings';
696   l_average_earnings       number := average_earnings;
697   l_reason_for_no_earnings varchar2 (80) := null;
698   earnings_not_derived     exception;
699   --
700   begin
701   --
702     hr_utility.set_location (l_proc,1);
703     --
704     -- If the average earnings figure returned is zero then check that
705     -- no error message was set. Error messages will be set for system-
706     -- generated average earnings when the earnings could not be derived
707     -- for some reason, but to allow this procedure to continue, no error
708     -- will be raised.
709     --
710     if l_average_earnings = 0
711     then
712       l_reason_for_no_earnings:=ssp_smp_support_pkg.average_earnings_error;
713       --
714       if l_reason_for_no_earnings is not null then
715          create_stoppage (p_withhold_from => person.ASPP_start_date,
716                           p_reason => l_reason_for_no_earnings);
717       --
718          raise earnings_not_derived;
719       end if;
720     end if;
721     --
722     -- Stop APAD payment from the APP start date
723     --
724     if l_average_earnings
725             < ssp_smp_support_pkg.NI_Lower_Earnings_Limit (person.MW)
726     then
727       create_stoppage (p_withhold_from => person.ASPP_start_date,
728                        p_reason => 'Earnings too low');
729     end if;
730     --
731     hr_utility.set_location (l_proc,100);
732     --
733   exception
734   --
735     when earnings_not_derived then
736       --
737       -- Exit silently from this procedure
738       --
739       hr_utility.trace (l_proc||'	Earnings not derived');
740       null;
741       --
742   end check_average_earnings;
743   --
744   procedure check_parameters is
745   --
746   begin
747   --
748     hr_utility.trace (l_proc||'	p_maternity_id = '
749                       	||to_char (p_maternity_id));
750     --
751     hr_api.mandatory_arg_error (
752                 p_api_name	=> l_proc,
753 		p_argument	=> 'maternity_id',
754 		p_argument_value=> p_maternity_id);
755     --
756   end check_parameters;
757   --
758   begin
759   --
760 
761     hr_utility.set_location (l_proc,1);
762     --
763     check_parameters;
764     --
765     -- Get the details of the person.
766     --
767     open csr_personal_details (p_maternity_id);
768     fetch csr_personal_details into person;
769     --
770     -- If no maternity record exists then there can be no entitlement to APAD
771     --
772     if csr_personal_details%notfound
773     then
774       close csr_personal_details;
775       --
776       hr_utility.trace (l_proc||'	Person has no maternity record - exiting');
777       --
778       raise no_prima_facia_entitlement;
779     end if;
780     --
781     close csr_personal_details;
782     --
783     -- If the APP has not started then there is no entitlement to APAD.
784     --
785     if person.ASPP_start_date is null then
786       hr_utility.trace (l_proc||'	Person has no APP start date - exiting');
787       --
788       raise no_prima_facia_entitlement;
789     end if;
790     --
791     -- Count how many absences there are for the maternity.
792     --
793     open csr_no_of_absences;
794     fetch csr_no_of_absences into no_of_absence_periods;
795     close csr_no_of_absences;
796     --
797     -- check if entries exist despite there being no absence
798     --
799     if no_of_absence_periods = 0
800     then
801       open csr_check_if_existing_entries;
802       fetch csr_check_if_existing_entries into l_existing_entries;
803       --
804       if csr_check_if_existing_entries%NOTFOUND
805       then
806         hr_utility.trace (l_proc||'    Person has not stopped work - exiting');
807         raise no_prima_facia_entitlement;
808       end if;
809       --
810       -- if entries are found then the absence has been deleted and entries remain
811       -- that must be dealt with
812       --
813       while csr_check_if_existing_entries%FOUND LOOP
814         fetch csr_check_if_existing_entries into l_existing_entries;
815       end loop;
816       --
817       close csr_check_if_existing_entries;
818       l_keep_stoppages := TRUE;
819     end if;
820     --
821     -- Having established a prima facia entitlement to APAD, perform checks which
822     -- may lead to creation of stoppages for particular periods.
823     --
824     hr_utility.set_location ('ssp_apad_pkg.entitled_to_APAD',2);
825     --
826     -- Get the APAD legislative parameters.
827     --
828     get_APAD_element (person.due_date);
829     --
830     -- Clear stoppages created by previous calculations of APAD but if an absence
831     -- is being deleted, then must keep stoppages so that when later comparison of
832     -- old_entry and hypothetical_entry is done then stoppages are still there.
833     --
834     if not l_keep_stoppages then
835       remove_stoppages;
836     end if;
837     --
838     for absence in csr_absence_details (p_maternity_id) LOOP
839     --
840     -- Check that sufficient notification of absence was given
841     --
842 /*  if (absence.date_notification > (absence.date_start - (g_APAD_element.ASPP_NOTICE_REQUIREMENT * 7))
843         and absence.accept_late_notification_flag = 'N'
844         and (person.partner_date_of_death is null
845              or nvl(person.partner_date_of_death, hr_general.end_of_time) < add_months(person.placement_date, 12))
846        )
847     then
848     -- Stop ASPPA payment. Need to verify is any end is required for this stoppage
849       create_stoppage (
850           	p_withhold_from => ssp_smp_support_pkg.start_of_week
851         							(absence.date_start),
852           	-- p_withhold_to => ssp_smp_support_pkg.end_of_week (stoppage_end_date),
853           	p_reason => 'Late absence notification');
854     end if;*/
855     --
856     hr_utility.set_location ('ssp_apad_pkg.entitled_to_apad',3);
857     --
858     -- Check for any work done during the ASPP.
859     --
860     if  csr_absence_details%rowcount = 1
861     then
862     -- Check if this is the first absence period in the ASPP
863     -- and the absence starts after the ASPP start date
864       if absence.date_start > person.ASPP_start_date then
865         create_stoppage (p_reason => 'Some work was done',
866                          p_withhold_from => person.ASPP_start_date,
867                          p_withhold_to => (absence.date_start -1));
868       end if;
869       -- Absence ends before Partner APP End, stop ASPP as on absence end date.
870       l_partner_app_end_date := partner_app_end_date(person.partner_stat_pay_start_date, null);
871       if absence.date_end < l_partner_app_end_date then
872         create_stoppage (p_reason => 'Some work was done',
873                          p_withhold_from => (absence.date_end + 1));
874       end if;
875     else -- more than one absence, but ASPP has to be taken in one block only.
876         create_stoppage (p_reason => 'Some work was done',
877                          p_withhold_from => absence.date_start,
878                          p_withhold_to => absence.date_end);
879     end if;
880   end loop;
881   --
882   check_continuity_rule;
883   check_start_date;
884   check_employment_end;
885   check_partner_app_days;
886   check_death;
887   check_disruption_date;
888   check_average_earnings;
889   --
890   -- If we get this far the person is entitled to APAD (though stoppages may apply)
891   --
892   return TRUE;
893   --
894 exception
895 --
896   when invalid_absence_date then
897     fnd_message.set_name ('PAY', 'HR_6153_ALL_PROCEDURE_FAIL');
898     fnd_message.set_token ('PROCEDURE','ssp_apad_pkg.entitled_to_APAD');
899     fnd_message.set_token ('STEP','3');
900     --
901   when no_prima_facia_entitlement then
902     --
903     -- Exit silently; this will allow us to call this procedure with impunity
904     -- from absences which are not maternity absences (e.g. via a row trigger)
905     --
906     return FALSE;
907     --
908 end entitled_to_APAD;
909 --------------------------------------------------------------------------------
910 procedure generate_payments (p_maternity_id in number,
911                              p_deleting     in boolean default FALSE) is
912 --
913 type date_table    is table of date index by binary_integer;
914 type number_table  is table of number index by binary_integer;
915 type varchar_table is table of varchar2 (80) index by binary_integer;
916 l_proc varchar2(72) := g_package||'generate_payments';
917 --
918 type APAD_entry is record (
919 	--
920 	element_entry_id	number_table,
921 	element_link_id		number_table,
922 	assignment_id		number_table,
923 	effective_start_date	date_table,
924 	effective_end_date	date_table,
925 	amount			number_table,
926 	rate			varchar_table,
927 	week_commencing		date_table,
928 	recoverable_amount	number_table,
929 	stopped			varchar_table,
930 	dealt_with		varchar_table);
931 	--
932 --
933 -- A store for all the APAD entries that potentially may be
934 -- granted to the person.
935 --
936 hypothetical_entry	APAD_entry;
937 --
938 -- A tally of the number of weeks of the APP which are subject to stoppages.
939 --
940 l_stopped_weeks		number := 0;
941 --
942 l_high_rate	varchar2 (80) := null;
943 l_low_rate	varchar2 (80) := null;
944 -- RT entries prob
945 l_no_of_absence_periods  integer := 0;
946 -- Max ASPPP weeks varies depending on partner died or not.
947 l_max_asppp_weeks number :=0;
948   --
949   -- p_deleting passed into save_hypothetical_entries, so that logic can be
950   -- dealt with for deleted absences.
951   --
952   procedure save_hypothetical_entries (p_deleting in boolean default false) is
953   --
954   -- Having generated the potential APAD entries, reconcile them with any
955   -- previously granted entries for the same maternity.
956   --
957   cursor csr_existing_entries is
958   --
959   -- Get all entries and entry values for the Adoption
960   --
961   -- Decode the rate code to give the meaning using local variables
962   -- populated earlier by Calculate_correct_APAD_rate
963   -- these can then be passed directly into the hr_entry_api's and
964   -- simplifies comparison with hypo entries
965   --
966   select entry.element_entry_id,
967          entry.element_link_id,
968          entry.assignment_id,
969          entry.effective_start_date,
970          entry.effective_end_date,
971          -- if in future we get two different rates then a decode can be added here
972          l_high_rate RATE,
973          /*to_date (ssp_smp_support_pkg.value
974             (entry.element_entry_id,
975             ssp_APAD_pkg.c_week_commencing_name),
976             'DD-MON-YYYY') WEEK_COMMENCING,*/
977 	 fnd_date.chardate_to_date(ssp_smp_support_pkg.value
978 	  (entry.element_entry_id,
979 	   ssp_APAD_pkg.c_week_commencing_name)) WEEK_COMMENCING,
980          to_number(ssp_smp_support_pkg.value (entry.element_entry_id,
981             ssp_APAD_pkg.c_amount_name)) AMOUNT,
982          to_number(ssp_smp_support_pkg.value (entry.element_entry_id,
983             ssp_APAD_pkg.c_recoverable_amount_name)) RECOVERABLE_AMOUNT
984   from	 pay_element_entries_f ENTRY,
985          per_all_assignments_f     asg
986   where	 creator_type = c_APAD_creator_type
987   and    creator_id = p_maternity_id
988   and    asg.person_id     = person.person_id
989   and    asg.assignment_id = entry.assignment_id
990   and    entry.effective_start_date between asg.effective_start_date
991                                                and asg.effective_end_date
992   and not exists (
993         --
994         -- Do not select entries which have already had reversal action taken
995         -- against them because they are effectively cancelled out.
996         --
997         select 1
998         from   pay_element_entries_f	ENTRY2
999         where  entry.element_entry_id= entry2.target_entry_id
1000         and    entry.assignment_id   = entry2.assignment_id)
1001         --
1002   and not exists (
1003         --
1004         -- Do not select reversal entries
1005         --
1006         select 1
1007         from	pay_element_links_f LINK,
1008                 pay_element_types_f TYPE
1009         where link.element_link_id = entry.element_link_id
1010         and	entry.effective_start_date between link.effective_start_date
1011                 and link.effective_end_date
1012         and link.element_type_id = type.element_type_id
1013         and	link.effective_start_date between type.effective_start_date
1014                 and type.effective_end_date
1015         and type.element_name = c_APAD_Corr_element_name);
1016 	--
1017   cursor csr_no_of_absences is
1018   --
1019   select count (*)
1020   from   per_absence_attendances
1021   where  person_id = person.person_id
1022   and    maternity_id = p_maternity_id
1023   and    absence_attendance_id =
1024           (select min(paa_tab.absence_attendance_id)
1025            from per_absence_attendances paa_tab
1026            where paa_tab.maternity_id = p_maternity_id);
1027   --
1028   l_ins_corr_ele  boolean;
1029   l_dummy         number;
1030   Entry_number    integer;
1031   l_ern_calc_id   number;
1032   l_ob_v_no       number;
1033   l_new_ob_v_no   number;
1034   l_proc varchar2 (72) := g_package||'save_hypothetical_entries';
1035   --
1036   -- This procedure was a private procedure in the function entitled_to_APAD. I
1037   -- wanted to call it within this procedure (generate_payments) aswell, so
1038   -- instead of making it a public procedure I have copied the procedure to here.
1039   --
1040     procedure remove_stoppages is
1041     --
1042     -- Remove old system, non-overridden stoppages
1043     --
1044     cursor csr_stoppages is
1045     --
1046     select stoppage_id
1047     from   ssp_stoppages
1048     where  user_entered <>'Y'
1049     and    override_stoppage <> 'Y'
1050     and    maternity_id = p_maternity_id;
1051     --
1052     l_dummy number;
1053     l_proc varchar2 (72) := g_package||'.remove_stoppages';
1054     --
1055     begin
1056     --
1057       hr_utility.set_location (l_proc,1);
1058       --
1059       for each_stoppage in csr_stoppages LOOP
1060         ssp_stp_del.del (p_stoppage_id => each_stoppage.stoppage_id,
1061                          p_object_version_number => l_dummy);
1062       end loop;
1063       --
1064       hr_utility.set_location (l_proc,100);
1065       --
1066     end remove_stoppages;
1067     --
1068   begin
1069     --
1070     hr_utility.set_location('Entering: '||l_proc,10);
1071     --
1072     get_APAD_correction_element (person.due_date);
1073     --
1074     -- Check each existing apad entry in turn against all the potential new ones.
1075     --
1076     <<OLD_ENTRIES>>
1077     for old_entry in csr_existing_entries
1078     LOOP
1079       --First loop through the hypothetical entries to see if there is one
1080       --which covers the same week as the old entry and is not subject to
1081       --a stoppage.  If there isn't one, invalidate the old entry.
1082       --Assume we don't need to correct the entry until we discover otherwise:
1083       --
1084       l_ins_corr_ele := FALSE;
1085       begin
1086         entry_number := 0;
1087         if p_deleting then
1088            raise no_data_found; -- enter exception handler
1089         end if;
1090         LOOP
1091           entry_number := entry_number +1;
1092           -- Exit the loop when we find a hypothetical entry covering the
1093           -- same week as the old entry, which is not subject to a stoppage.
1094           -- If no such match is found, then we will reach the end of the
1095           -- pl/sql table and attempt to read beyond the existing rows; this
1096           -- will cause us to enter the exception handler and indicate that
1097           -- no match was found.
1098           exit when ((old_entry.week_commencing
1099              = hypothetical_entry.week_commencing (entry_number)
1100              and not hypothetical_entry.stopped (entry_number) = 'TRUE'
1101              and ssp_smp_pkg.g_smp_update = 'N')
1102              or (old_entry.effective_start_date
1103                    = hypothetical_entry.effective_start_date (entry_number)
1104                  and old_entry.week_commencing
1105                    = hypothetical_entry.week_commencing (entry_number)
1106                  and not hypothetical_entry.stopped (entry_number) = 'TRUE'
1107                  and ssp_smp_pkg.g_smp_update = 'Y'));
1108         end loop;
1109         hr_utility.trace (l_proc||' Old entry / Hypo entry time Match with values:');
1110         hr_utility.trace (l_proc||'        Rate: ' ||old_entry.rate||' / '
1111           ||hypothetical_entry.rate (Entry_number));
1112         hr_utility.trace (l_proc||'      Amount: '
1113           ||old_entry.amount||' / '
1114           ||hypothetical_entry.amount (entry_number));
1115         hr_utility.trace (l_proc||' Recoverable: '
1116           ||old_entry.recoverable_amount||' / '
1117           ||hypothetical_entry.recoverable_amount (entry_number));
1118         hr_utility.trace (l_proc||'   Week Comm: '
1119           ||hypothetical_entry.week_commencing (entry_number) );
1120         --A hypo entry covers the same week as the old one
1121         if    old_entry.rate   = hypothetical_entry.rate (entry_number)
1122           and old_entry.amount = hypothetical_entry.amount(entry_number)
1123           and old_entry.recoverable_amount
1124                    = hypothetical_entry.recoverable_amount (entry_number)
1125         then
1126           -- the hypo entry has the same values as the old one
1127           -- don't create a correction element.
1128           -- don't create a new entry
1129           hypothetical_entry.dealt_with (entry_number) := 'TRUE';
1130           hr_utility.trace (l_proc||' leave unchanged');
1131         else
1132           if ssp_smp_support_pkg.entry_already_processed
1133                                             (old_entry.element_entry_id)
1134           then l_ins_corr_ele := TRUE;
1135           hr_utility.trace (l_proc||' processed - correct it');
1136           else
1137             -- update old entry
1138             hr_utility.trace (l_proc||' unprocessed - update it');
1139             hr_entry_api.update_element_entry (
1140               p_dt_update_mode => 'CORRECTION',
1141               p_session_date => old_entry.effective_start_date,
1142               p_element_entry_id => old_entry.element_entry_id,
1143               p_input_value_id1 => g_APAD_element.rate_id,
1144               p_input_value_id2 => g_APAD_element.amount_id,
1145               p_input_value_id3 => g_APAD_element.recoverable_amount_id,
1146               p_entry_value1=> hypothetical_entry.rate (entry_number),
1147               p_entry_value2=> hypothetical_entry.amount(entry_number),
1148               p_entry_value3=>
1149                       hypothetical_entry.recoverable_amount (entry_number));
1150             --
1151             --prevent insertion of new entry
1152             --
1153             hypothetical_entry.dealt_with (entry_number) := 'TRUE';
1154           end if;
1155         end if;
1156       exception
1157         when no_data_found then
1158           -- There was no new entry which exactly matched the old entry.
1159           -- or we are deleting.
1160           entry_number := null;
1161           hr_utility.trace (l_proc||' No Old entry - Hypo entry time Match');
1162           hr_utility.trace (l_proc||' or p_deleting is true');
1163           hr_utility.trace (l_proc||' Old entry values:');
1164           hr_utility.trace (l_proc||'        Rate: '||old_entry.rate);
1165           hr_utility.trace (l_proc||'      Amount: '||old_entry.amount);
1166           hr_utility.trace (l_proc||' Recoverable: '
1167                                         ||old_entry.recoverable_amount);
1168           if ssp_smp_support_pkg.entry_already_processed
1169                                             (old_entry.element_entry_id)
1170           then l_ins_corr_ele := TRUE;
1171             hr_utility.trace (l_proc||' Old entry already processed');
1172           else
1173             hr_utility.trace (l_proc||' Old entry NOT already processed');
1174             --Old entry not already processed so delete it
1175             hr_entry_api.delete_element_entry (
1176               p_dt_delete_mode => 'ZAP',
1177               p_session_date => old_entry.effective_start_date,
1178               p_element_entry_id => old_entry.element_entry_id);
1179           end if;
1180       end;
1181       if l_ins_corr_ele
1182       then
1183         -- Create a correction element to reverse the old entry. Then create a
1184         -- brand new entry with the correct values.
1185         --
1186         hr_utility.trace (l_proc ||
1187                           ' Inserting CORRECTION entry for week commencing ' ||
1188                           to_char (old_entry.week_commencing));
1189         hr_utility.trace (l_proc||'              Old value / New value:');
1190         if entry_number is null then
1191           hr_utility.trace (l_proc||'        Rate: '
1192             ||old_entry.rate||' / NA');
1193           hr_utility.trace (l_proc||'      Amount: '
1194             ||old_entry.amount||' / NA');
1195           hr_utility.trace (l_proc||' Recoverable: '
1196             ||old_entry.recoverable_amount||' / NA');
1197         else
1198           hr_utility.trace (l_proc||'        Rate: '
1199             ||old_entry.rate||' / '
1200             ||hypothetical_entry.rate (Entry_number));
1201           hr_utility.trace (l_proc||'      Amount: '
1202             ||old_entry.amount||' / '
1203             ||hypothetical_entry.amount (entry_number));
1204           hr_utility.trace (l_proc||' Recoverable: '
1205             ||old_entry.recoverable_amount||' /'
1206             ||hypothetical_entry.recoverable_amount (entry_number));
1207         end if;
1208         --
1209         -- Determine the next available period in which to place the
1210         -- correction entry
1211         --
1212         ssp_smp_support_pkg.get_entry_details (
1213           p_date_earned  => old_entry.week_commencing,
1214           p_last_process_date => person.final_process_date,
1215           p_person_id  => person.person_id,
1216           p_element_type_id => g_APAD_Correction_element.element_type_id,
1217           p_element_link_id => old_entry.element_link_id,
1218           p_assignment_id  => old_entry.assignment_id,
1219           p_effective_start_date => old_entry.effective_start_date,
1220           p_effective_end_date => old_entry.effective_end_date,
1221           p_pay_as_lump_sum => person.pay_APAD_as_lump_sum);
1222         --
1223         -- hr_entry_api's take the lookup meanings not the lookup codes.
1224         -- converted rate codes to meanings before calling the
1225         -- api.  Later fix made old_entry (csr_existing_entries) return
1226         -- the meaning, so rate passed directly.
1227         --
1228         hr_entry_api.insert_element_entry (
1229           p_effective_start_date=> old_entry.effective_start_date,
1230           p_effective_end_date => old_entry.effective_end_date,
1231           p_element_entry_id  => l_dummy,
1232           p_target_entry_id  => old_entry.element_entry_id,
1233           p_assignment_id  => old_entry.assignment_id,
1234           p_element_link_id  => old_entry.element_link_id,
1235           p_creator_type  => c_APAD_creator_type,
1236           p_creator_id  => p_maternity_id,
1237           p_entry_type  => c_APAD_entry_type,
1238           p_input_value_id1=> g_APAD_correction_element.rate_id,
1239           p_input_value_id2=> g_APAD_correction_element.week_commencing_id,
1240           p_input_value_id3=> g_APAD_correction_element.amount_id,
1241           p_input_value_id4=> g_APAD_correction_element.recoverable_amount_id,
1242           p_entry_value1=> old_entry.rate,
1243 --          p_entry_value2=> old_entry.week_commencing,
1244        -- p_entry_value2  => to_char(old_entry.week_commencing,'DD-MON-YYYY'),
1245 	  p_entry_value2  => fnd_date.date_to_chardate(old_entry.week_commencing),
1246           p_entry_value3=> old_entry.amount * -1,
1247           p_entry_value4=> old_entry.recoverable_amount * -1);
1248         --
1249         --New entry will be created by brand_new_entries loop if not p_deleting
1250       end if;
1251       --
1252     end loop old_entries;
1253     --
1254     -- Having been through all the existing entries, we now check that we
1255     -- have dealt with all the newly derived entries by inserting any which
1256     -- were not flagged as dealt with during the above actions.
1257     --
1258     hr_utility.set_location (l_proc,20);
1259     --
1260     <<BRAND_NEW_ENTRIES>>
1261     begin
1262       if p_deleting then
1263         hr_utility.trace('Deleting an absence so don''t insert entries');
1264       else
1265         for new_entry in 1..l_max_asppp_weeks LOOP
1266           if (not hypothetical_entry.dealt_with (new_entry) = 'TRUE')
1267             and (not hypothetical_entry.stopped (new_entry) = 'TRUE')
1268           then
1269             hr_entry_api.insert_element_entry (
1270               p_effective_start_date =>
1271                           hypothetical_entry.effective_start_date (new_entry),
1272               p_effective_end_date =>
1273                           hypothetical_entry.effective_end_date (new_entry),
1274               p_element_entry_id => l_dummy,
1275               p_assignment_id  => hypothetical_entry.assignment_id (new_entry),
1276               p_element_link_id => hypothetical_entry.element_link_id (new_entry),
1277               p_creator_type  => c_APAD_creator_type,
1278               p_creator_id  => p_maternity_id,
1279               p_entry_type  => c_APAD_entry_type,
1280               p_input_value_id1 => g_APAD_element.rate_id,
1281               p_input_value_id2 => g_APAD_element.week_commencing_id,
1282               p_input_value_id3 => g_APAD_element.amount_id,
1283               p_input_value_id4 => g_APAD_element.recoverable_amount_id,
1284               p_entry_value1  => hypothetical_entry.rate (new_entry),
1285 --            p_entry_value2  => hypothetical_entry.week_commencing (new_entry),
1286               p_entry_value2  => to_char(hypothetical_entry.week_commencing(new_entry),'DD-MON-YYYY'),
1287               p_entry_value3  => hypothetical_entry.amount (new_entry),
1288               p_entry_value4  =>
1289                           hypothetical_entry.recoverable_amount (new_entry));
1290           end if;
1291         end loop brand_new_entries;
1292       end if;
1293     exception
1294       when no_data_found then
1295         --
1296         -- We have run out of hypothetical entries to insert
1297         --
1298         null;
1299         --
1300     end;
1301     --
1302     -- Orphaned stoppages, associated with deleted absence can now be deleted
1303     -- This replaces cross product constraints that are no longer allowed.
1304     --
1305     open csr_no_of_absences;
1306     fetch csr_no_of_absences into l_no_of_absence_periods;
1307     close csr_no_of_absences;
1308     --
1309     if l_no_of_absence_periods = 0 then
1310       remove_stoppages;
1311     end if;
1312     --
1313     hr_utility.set_location(' Leaving: '||l_proc,100);
1314     --
1315   end save_hypothetical_entries;
1316 	--
1317 procedure derive_APAD_week (p_week_number in integer) is
1318 	--
1319 	-- Derive the start and end dates of the week covered by the APAD
1320 	-- payment. This is done by finding out how many weeks into the APP
1321 	-- we are and finding the offset from the start date.
1322 	--
1323 	begin
1324 	--
1325 	hr_utility.set_location ('Entering: ssp_APAD_pkg.derive_APAD_week',1);
1326 	hr_utility.trace ('Entry number = '||to_char (p_week_number));
1327 	--
1328 	hypothetical_entry.week_commencing (p_week_number)
1329 		:= (person.ASPP_start_date + ((p_week_number -1) * 7));
1330 	--
1331 	hypothetical_entry.dealt_with (p_week_number) := 'FALSE';
1332 	hypothetical_entry.stopped (p_week_number) := 'FALSE';
1333 	hypothetical_entry.element_link_id (p_week_number) := null;
1334 	hypothetical_entry.assignment_id (p_week_number) := null;
1335 	--
1336 	hr_utility.trace ('week_commencing = '
1337 		||to_char (hypothetical_entry.week_commencing (p_week_number)));
1338 		--
1339 	hr_utility.set_location ('Leaving : ssp_APAD_pkg.derive_APAD_week',100);
1340 	--
1341 	end derive_APAD_week;
1342 	--
1343 procedure Check_APAD_stoppages (p_week_number in integer) is
1344 	--
1345 	-- Find any APAD stoppage for the Adoption which overlaps a date range
1346 	--
1347 	employee_died varchar2 (30) := 'Employee died';
1348         max_aspp varchar2 (50) := 'Max ASPP Period Exceeded';
1349 	--
1350 	cursor csr_stoppages (p_start_date in date, p_end_date in date) is
1351 		--
1352 		-- Find any non-overridden stoppages
1353 		--
1354 		select	wre.reason, stp.withhold_from, stp.withhold_to
1355 		from	ssp_stoppages STP,
1356 			ssp_withholding_reasons WRE
1357 		where	stp.override_stoppage <> 'Y'
1358 		--
1359 		-- and the stoppage ovelaps the period or the stoppage is for
1360 		-- death and is prior to the period
1361 		--
1362 		and	((wre.reason <> employee_died
1363 			   and stp.withhold_from <= p_end_date
1364 			   and nvl (stp.withhold_to, hr_general.end_of_time)
1365 				>= p_start_date)
1366 			--
1367 			or (wre.reason = employee_died
1368 			   and stp.withhold_from < p_start_date))
1369 		--
1370 		and	stp.maternity_id = p_maternity_id
1371 		and	stp.reason_id = wre.reason_id;
1372 		--
1373 	--l_dummy	integer (1);
1374         l_dummy csr_stoppages%rowtype;
1375 	--
1376 	begin
1377 	--
1378 	hr_utility.set_location ('ssp_APAD_pkg.Check_APAD_stoppages',1);
1379 	--
1380 	hypothetical_entry.stopped (p_week_number) := 'FALSE';
1381 	--
1382 	open csr_stoppages (
1383 		hypothetical_entry.week_commencing (p_week_number),
1384 		hypothetical_entry.week_commencing (p_week_number) + 6);
1385 	--
1386 	fetch csr_stoppages into l_dummy;
1387 	--
1388 	if csr_stoppages%found
1389 	then
1390 	  --
1391 	  -- There is an overlap between the APAD week and a stoppage so no APAD
1392 	  -- is payable.
1393 	  --
1394 	  hypothetical_entry.stopped (p_week_number) := 'TRUE';
1395 	  --
1396 	  hr_utility.trace ('Entry is STOPPED');
1397 	  --
1398           if l_dummy.reason=max_aspp
1399              and hypothetical_entry.week_commencing (p_week_number) < l_dummy.withhold_from
1400           then
1401              hypothetical_entry.stopped (p_week_number) := 'PARTIAL';
1402              hr_utility.trace('ssp_apad_pkg.Check_APAB_stoppages Partial Week Payment');
1403           end if;
1404 	  -- Keep a tally of the number of stopped weeks
1405 	  --
1406 	  l_stopped_weeks := l_stopped_weeks +1;
1407 	end if;
1408 	--
1409 	-- Check to see if any further stoppages can be found.
1410 	-- If so then PARTIAL stoppage to be made full stoppage.
1411 	fetch csr_stoppages into l_dummy;
1412 
1413 	if csr_stoppages%found
1414 	then
1415            hypothetical_entry.stopped (p_week_number) := 'TRUE';
1416 	end if;
1417 	--
1418 	close csr_stoppages;
1419 	--
1420 	hr_utility.set_location ('ssp_APAD_pkg.Check_APAD_stoppages',10);
1421 	--
1422 	end Check_APAD_stoppages;
1423 	--
1424 procedure Calculate_correct_APAD_rate (p_week_number in number) is
1425 	--
1426 	-- The entry API takes the lookup meanings so we must find
1427 	-- the meanings rather than the codes for APAD rates.
1428 	--
1429 	cursor csr_rate_meaning (p_rate_band varchar2) is
1430 		--
1431 	        select	meaning
1432 		from	hr_lookups
1433 		where	lookup_type = 'ASPP_RATES'
1434 		and	lookup_code = p_rate_band;
1435 		--
1436 	begin
1437 	--
1438 	hr_utility.set_location ('ssp_APAD_pkg.Calculate_correct_APAD_rate',1);
1439 	--
1440 	if l_high_rate is null then
1441 	  --
1442 	  -- Get the meanings for the rate bands
1443 	  --
1444 	  -- Get the higher rate band
1445 	  --
1446 	  open csr_rate_meaning ('STD');
1447 	  fetch csr_rate_meaning into l_high_rate;
1448 	  close csr_rate_meaning;
1449 
1450 	end if;
1451 	--
1452 /*
1453 	if (p_week_number - l_stopped_weeks)
1454 		<= g_SMP_element.period_at_higher_rate
1455 	then
1456 	  hr_utility.set_location ('ssp_smp_pkg.Calculate_correct_SMP_rate',1);
1457 	  --
1458 	  -- We have not yet given the employee all their higher rate weeks
1459 	  --
1460 */
1461 	  hypothetical_entry.rate (p_week_number) := l_high_rate;
1462 /*
1463 	else
1464 	  hypothetical_entry.rate (p_week_number) := l_low_rate;
1465 	end if;
1466 */
1467 	--
1468 	hr_utility.trace ('APAD Rate = '
1469 		||hypothetical_entry.rate (p_week_number));
1470 		--
1471 	hr_utility.set_location ('ssp_APAD_pkg.Calculate_correct_APAD_rate',10);
1472 	--
1473 	end Calculate_correct_APAD_rate;
1474 	--
1475 procedure Calculate_APAD_amounts (p_week_number in integer, p_ASPP_start_date in date) is
1476 	--
1477 	l_days_in_week number := 0;
1478         begin
1479 	--
1480 	hr_utility.set_location('Entering: ssp_apad_pkg.Calculate_apad_amounts',1);
1481 	--
1482 	-- Get the APAD element for each week in case the APAD rate has changed
1483 	--
1484 	get_APAD_element (hypothetical_entry.week_commencing (p_week_number));
1485 	--
1486     hypothetical_entry.amount (p_week_number)
1487 		:= least (round (
1488 			(average_earnings * g_APAD_element.ASPP_rate)
1489 				+ 0.0049,2),
1490 			g_APAD_element.STANDARD_RATE);
1491 	--
1492 	hypothetical_entry.recoverable_amount (p_week_number)
1493 		:= round (hypothetical_entry.amount (p_week_number)
1494 			* g_APAD_element.recovery_rate,2);
1495 	--
1496         if hypothetical_entry.stopped(p_week_number) = 'PARTIAL' then
1497 
1498         /* This week is the week where partner MPP/APP ends, but employee leave spans the whole week.
1499            If the number of days in the week before stoppage >0, ASPP needs to be paid for these days */
1500            l_days_in_week := partner_app_end_date(person.partner_stat_pay_start_date,null) - hypothetical_entry.week_commencing(p_week_number);
1501 
1502            if l_days_in_week > 0 then
1503                hypothetical_entry.amount (p_week_number)
1504            		:= least (round (
1505            			(average_earnings * g_APAD_element.ASPP_rate * l_days_in_week/7 )
1506            				+ 0.0049,2),
1507            			round((g_APAD_element.STANDARD_RATE * l_days_in_week/7 )
1508                      + 0.0049,2));
1509            	--
1510            	hypothetical_entry.recoverable_amount (p_week_number)
1511            		:= round (hypothetical_entry.amount (p_week_number) * g_APAD_element.recovery_rate *  l_days_in_week/7
1512                           ,2);
1513            end if;
1514         end if;
1515 	--
1516 	hr_utility.trace ('APAD amount = '
1517 		||to_char (hypothetical_entry.amount (p_week_number)));
1518 	hr_utility.trace ('Recoverable amount = '
1519 	||to_char (hypothetical_entry.recoverable_amount (p_week_number)));
1520 	--
1521 	hr_utility.set_location('Leaving : ssp_APAD_pkg.Calculate_APAD_amounts',100);
1522 	--
1523 	end calculate_APAD_amounts;
1524 	--
1525 	procedure check_parameters is
1526 	begin
1527 	hr_api.mandatory_arg_error (
1528 		p_api_name	=> l_proc,
1529 		p_argument	=> 'maternity_id',
1530 		p_argument_value=> p_maternity_id);
1531 		--
1532 	end check_parameters;
1533 	--
1534 begin
1535 --
1536 hr_utility.set_location ('ssp_APAD_pkg.generate_payments',1);
1537 --
1538 check_parameters;
1539 --
1540 <<APAD_WEEKS>>
1541 --
1542 if person.ASPP_start_date is not null then
1543 
1544    get_APAD_element (person.due_date); /* Added for bug fix 10326113 */
1545 
1546    if person.partner_date_of_death is not null and
1547       add_months(person.placement_date, 12) > person.partner_date_of_death
1548    then
1549       l_max_asppp_weeks := g_APAD_element.MAXIMUM_ASPPP_MOM_DEATH_WEEKS;
1550    else
1551       l_max_asppp_weeks := g_APAD_element.MAXIMUM_ASPPP_WEEKS;
1552    end if;
1553 
1554    for week_number in 1..l_max_asppp_weeks
1555    LOOP
1556       --
1557       -- Derive hypothetical entries ie those entries which would be applied for a
1558       -- completely new maternity. Store them internally because we must check
1559       -- previously created entries before applying the hypothetical entries to the
1560       -- database.
1561       --
1562       Derive_APAD_week			(week_number);
1563       Check_APAD_stoppages			(week_number);
1564       Calculate_correct_APAD_rate		(week_number);
1565       Calculate_APAD_amounts		(week_number, person.ASPP_start_date);
1566       --
1567       if (not(hypothetical_entry.stopped (week_number) = 'TRUE')) then
1568       --
1569       -- Get the entry details unless the entry has been stopped (in which case
1570       -- we do not need the entry details and errors may occur if we call the
1571       -- procedure; eg the woman's assignment ends)
1572       --
1573          ssp_smp_support_pkg.get_entry_details	(
1574             p_date_earned          => hypothetical_entry.week_commencing
1575                                                 (week_number),
1576             p_pay_as_lump_sum      => person.pay_APAD_as_lump_sum,
1577             p_last_process_date    => person.final_process_date,
1578             p_person_id            => person.person_id,
1579             p_element_type_id      => g_APAD_element.element_type_id,
1580             p_element_link_id      => hypothetical_entry.element_link_id
1581                                                 (week_number),
1582             p_assignment_id        => hypothetical_entry.assignment_id
1583                                                 (week_number),
1584             p_effective_start_date => hypothetical_entry.effective_start_date
1585                                                 (week_number),
1586             p_effective_end_date   => hypothetical_entry.effective_end_date
1587                                                 (week_number));
1588       end if;
1589    end loop APAD_weeks;
1590 end if;
1591 --
1592 Save_hypothetical_entries(p_deleting);
1593 --
1594 end generate_payments;
1595 --
1596 --------------------------------------------------------------------------------
1597 procedure APAD_control (p_maternity_id	in number,
1598                        p_deleting       in boolean default FALSE) is
1599 --
1600 -- p_deleting parameter added to deal with absences being deleted, without
1601 -- maternity being deleted.
1602 --
1603 
1604 -- Find out if the maternity exists
1605 --
1606 cursor csr_maternity is
1607 select 1
1608 from   ssp_maternities
1609 where  maternity_id = p_maternity_id;
1610 
1611 --
1612 -- Get all element entries associated with a maternity
1613 --
1614 cursor csr_entries is
1615 select entry.element_entry_id,
1616        entry.effective_start_date
1617 from   per_absence_attendances PAA,
1618        per_all_assignments_f   PAAF,
1619        pay_element_entries_f   entry
1620 where  PAA.maternity_id = p_maternity_id
1621 and    PAAF.person_id = PAA.person_id
1622 and    entry.creator_type = 'M'
1623 and    entry.creator_id = p_maternity_id
1624 and    entry.assignment_id = paaf.assignment_id;
1625 --
1626 cursor csr_count_absences is
1627 select count(*)
1628 from   ssp_maternities mat,
1629        per_absence_attendances ab
1630 where  mat.maternity_id = p_maternity_id
1631 and    ab.person_id = mat.person_id
1632 and    ab.maternity_id = mat.maternity_id;
1633         --
1634 l_count number;
1635 l_dummy	number;
1636 l_proc	varchar2 (72) := g_package||'APAD_control';
1637 --
1638 begin
1639 --
1640   hr_utility.set_location (l_proc,1);
1641   --
1642   open csr_maternity;
1643   fetch csr_maternity into l_dummy;
1644 
1645   --
1646   -- Recalculate APAD
1647   --
1648   if csr_maternity%found then
1649      if entitled_to_APAD (p_maternity_id) then
1650         open csr_count_absences;
1651         fetch csr_count_absences into l_count;
1652         close csr_count_absences;
1653         if l_count > 0 then
1654             generate_payments (p_maternity_id, false);
1655         else
1656             generate_payments (p_maternity_id, p_deleting);
1657         end if;
1658      elsif p_deleting then
1659         -- not entitled but deleting absence then
1660         generate_payments (p_maternity_id, p_deleting);
1661      end if;
1662   else
1663     --
1664     -- The maternity may have been deleted. Remove any element entries associated
1665     -- with it (the absences, stoppages and medicals are handled by constraints).
1666     --
1667     for obsolete in csr_entries LOOP
1668       hr_utility.trace (l_proc||'	Deleting element entry_id '||
1669                         to_char (obsolete.element_entry_id));
1670       hr_utility.trace (l_proc||'-------------------------------------------');
1671       --
1672       hr_entry_api.delete_element_entry (
1673                            p_dt_delete_mode    => 'ZAP',
1674                            p_session_date      => obsolete.effective_start_date,
1675                            p_element_entry_id  => obsolete.element_entry_id);
1676     end loop;
1677   end if;
1678   --
1679   hr_utility.set_location (l_proc,100);
1680   --
1681 end APAD_control;
1682 --------------------------------------------------------------------------------
1683 end ssp_APAD_pkg;