DBA Data[Home] [Help]

PACKAGE BODY: APPS.SSP_PAD_PKG

Source


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