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