1 package body SSP_SMP_PKG as
2 /*$Header: spsmpapi.pkb 120.8 2006/12/09 16:49:27 kthampan ship $
3 +==============================================================================+
4 | Copyright (c) 1994 Oracle Corporation |
5 | Redwood Shores, California, USA |
6 | All rights reserved. |
7 +==============================================================================+
8 --
9 Name
10 Statutory Maternity Pay Business Process
11 --
12 Purpose
13 To perform calculation of entitlement and payment for SMP purposes
14 --
15 History
16 31 Aug 95 N Simpson Created
17 8 Sep 95 N Simpson Modified procedure
18 check_entitlement_to_SMP and turned it
19 into a function entitled_to_SMP.
20 15 Sep 95 N Simpson Various modifications because of
21 change in ssp_stoppages table.
22 19 Sep 95 N Simpson Modified medical_control parameters.
23 27 Oct 95 N Simpson Renamed all HR_ prefixed objects to
24 SSP_ prefix if they were SSP-specific.
25 2 Nov 95 N Simpson Replaced hrstpapi calls with new style
26 table handler names.
27 Amended derive_SMP_week to initialise
28 hypothetical_entry.element_link_id and
29 hypothetical_entry.assignment_id which
30 were being read by get_entry_details and
31 raising a no_data_found error.
32 Added a few check_parameter procedures.
33 9 Nov 95 N Simpson Removed some obsolete code.
34 16 Nov 95 N Simpson Changed last_standard_process_date
35 to final_process_date throughout as
36 it should have been in the first place.
37 27 Nov 95 N Simpson Converted the SMP rate set for each
38 entry to use the lookup meaning instead
39 of the lookup code.
40 30 Nov 95 N Simpson Changed code creating stoppages for late
41 absence notification. This should ensure
42 that the first absence day is included
43 in the stoppage period calculation
44 5 Dec 95 N Simpson Added handling of average earnings
45 errors.
46 22 Aug 96 C Barbieri Deleted function maternity_leave_exists.
47 With Oracle 7.3.2 it is not possible to
48 reference a function that returns a
49 BOOLEAN inside a SELECT statement.
50
51 DATE AUTHOR VERSION BUG NO DESCRIPTION
52 ---- ------ ------- ------ -----------
53 06 Jan 97 M Fender 434233 Fully qualified call to function within
54 cursor period_of_service with package
55 name. This is a workaround to a bug in
56 PL/SQL which is fixed in version 2.3.3.
57 See related bug 410159 for details.
58
59 04-Feb-97 RThirlby 30.34 447690 Altered function continous_employment-
60 _date to return correct date.
61
62 18-Apr-97 RThirlby 30.35 479378 Cursor csr_personal_details altered to
63 allow for rehired employees - added
64 subquery with max function on date_start
65 12-Dec-97 RThirlby 30.36 590966 Fix.
66 08-Jan-98 RThirlby 30.37 SMP Entries problem solved - on absence
67 delete the entries were not deleted, or
68 correction entries were not created if
69 the entries had been through a payroll
70 run.
71 06-Apr-98 AParkes 30.38 648313 Prevented raising of no_data_found in
72 new_entries block. Changed hr_trace
73 outputs to prevent errors.
74 08-Apr-98 AParkes 30.39 653276 Performance fix to csr_existing_entries
75 cursor; drove from per_assignments using
76 woman.person_id
77 20-Apr-98 AParkes 30.40 647543 Corrected sub-query in cursor
78 csr_existing_entries which prevents
79 selection of correction entries; used
80 base tables not dt views. Made cursor
81 csr_existing_entries return the rate
82 meaning, not code, to simplify api calls
83 and comparisons between old and hypo
84 entry rates. save_hypothetical_entries
85 altered to update existing unprocessed
86 entries covering the same week, but
87 having incorrect amounts.
88 30-JUL-98 A.Myers 30.41 705553 Added date formatting around week-
89 commencing passed in attribute 2 to
90 procedure insert_element_entry (2 calls)
91 31-JUL-98 A.Myers 30.42 701750 Only inserting temp_affected row if it
92 does not already exist (new procedure).
93 01-NOV-99 M.Vilrokx 110.8 960689 Added service.date_start to the cursor
94 csr_personal_details. This date will be
95 passed to ssp_ern_ins.ins in stead of the
96 QW date if the latter is smaller than the
97 service.date_start. When this is not done
98 the ssp_ern_ins.ins procedure will try to
99 validate the QW and raise error 35049
100 because it is before the effective start
101 date of the person.
102 06-JAN-2000 ILeath 110.9 1021179 Remove the stoppage for
103 check_birth_confirmation. A stoppage
104 should not be created if the woman
105 notifies her employer of the date the
106 baby was born.
107 11-AUG-2000 DFoster 110.10 1304683 Amended the average_earnings function so
108 that it calls the nwe version of the
109 calculate_average_earnings which can
110 treat Sicknesses and Maternities
111 differently.
112 30-MAY-2002 SMRobins 115.9 Changes to add changes for APR 2003
113 legislation. Added woman.MPP_start_date
114 to call to Calculate_SMP_amounts, and
115 so extra p_MPP_start_date parameter
116 to Calculate_SMP_amounts procedure.
117 Then code splits within
118 Calculate_SMP_amounts dependent on
119 whether MPP start date before or
120 after 06-APR-2003. The code for prior
121 to 06-APR-2003 can be removed once
122 this date has elapsed.
123 28-OCT-2002 SHVEERAB 115.10 2620611 Do not create stoppage for pre-matured
124 birth of baby.
125 06-NOV-2002 GButler 115.12 2649315 Changes to EXPECTED_WEEK_OF_CONFINEMENT,
126 CONTINUOUS_EMPLOYMENT_DATE
127 functions and CHECK_DEATH procedure to resolve
128 translation issues
129 13-NOV-2002 GButler 115.13 2620413 Change to entitled_to_smp, check on
130 creation of late notification stoppages
131 15-NOV-2002 Bhaskar 115.14 2663735 New procedure check_employment_qw is
132 created to check for employee
133 terminated in qualifying week.
134 15-NOV-2002 Bhaskar 115.14 2663899 Check for employee death in the
135 MPP pay period.
136 22-NOV-2002 BTHAMMIN 115.16 2663899 SMP was paid one week more than
137 required
138 27-JAN-2003 GButler 115.17 nocopy fix to average_earnings - 2nd
139 dummy variable created as placeholder
140 to OUT param from ssp_ern_ins
141 24-FEB-2003 ABlinko 115.18 2811430 Amended csr_maternity in earnings_control
142 for SAP/SPP
143 17-APR-2003 MMAhmad 115.19 2801805 Amended code for Late Absence Notification
144 14-MAY-2003 GButler 115.20 2939058 Changes to csr_period_of_service_qw in
145 check_employment_qw to resolve bug
146 25-AUG-2003 asengar 115.21 3111736 Added to_number to make it compatible for 10g
147 25-FEB-2004 asengar 115.22 3436510 Cursor period_of_service and Procedure
148 3429978 entitled_to_SMP have been modified.
149 29-MAR-2004 skhandwa 115.23 3510141 Added condition to generate Late evidence stoppage
150
151 15-JUN-2004 ssekhar 115.24 3693735 Added to_number to make it compatible for 10g
152 12-JUL-2004 ablinko 115.25 3682122 Changes for recalculating lump sum updates
153 11-OCT-2005 npershad 115.26 4621910 Fixed two problems with date conversion,
154 one in the cursor csr_existing_entries
155 and twice when calling insert_element_entry
156 09-FEB-2006 kthampan 115.27 4891953 Fixed performance bug.
157 21-MAR-2006 kthampan 115.28 5105039 Added function to calculate max SMP paid date.
158 16-JUN-2006 ajeyam 115.29 5210118 In check_continuity_rule procedure,
159 period_of_service cursor changed to fetch the
160 latest start date for rehired persons.
161 23-AUG-2006 kthampan 115.30 5482199 Change from per_people_f and per_assignments_f
162 to per_all_people_f and per_all_assignments_f
163 19-SEP-2006 kthampan 115.31 5547703 Amend smp_control to call generate_payments
164 with insert-mode if absence is > 0 and
165 also change csr_check_if_existing_entries
166 not to reference from per_absence_attendances
167 table
168 19-OCT-2006 kthampan 115.32 5604330 Amend check_death to create the stoppage based
169 on the '7 day rolling weeks', currently it
170 will always created using the next Sunday after
171 the date of death.
172 09-DEC-2006 kthampan 115.33 5706912 Amend procedure ins_ssp_temp_affected_rows_mat
173 and person_control
174 */
175 --------------------------------------------------------------------------------
176 g_package varchar2(33) := ' ssp_smp_pkg.'; -- Global package name
177 --
178 cursor csr_absence_details (p_maternity_id in number) is
179 --
180 -- Get details of maternity leave for a maternity, in chronological
181 -- order of start date
182 --
183 select absence.absence_attendance_id,
184 absence.date_start,
185 nvl (absence.date_end, hr_general.end_of_time) date_end,
186 absence.date_notification,
187 absence.accept_late_notification_flag
188 from per_absence_attendances ABSENCE
189 where absence.maternity_id = p_maternity_id
190 order by absence.date_start;
191 --
192 --------------------------------------------------------------------------------
193 cursor csr_personal_details (p_maternity_id in number) is
194 --
195 -- Get details of the maternal woman
196 --
197 select maternity.person_id,
198 maternity.due_date,
199 ssp_smp_pkg.qualifying_week (due_date) QW,
200 ssp_smp_pkg.expected_week_of_confinement (due_date) EWC,
201 maternity.maternity_id,
202 maternity.actual_birth_date,
203 maternity.live_birth_flag,
204 maternity.start_date_with_new_employer,
205 maternity.MPP_start_date,
206 maternity.notification_of_birth_date,
207 maternity.start_date_maternity_allowance,
208 maternity.pay_SMP_as_lump_sum,
209 person.date_of_death,
210 service.date_start,
211 nvl (service.final_process_date, hr_general.end_of_time)
212 FINAL_PROCESS_DATE
213 from ssp_maternities MATERNITY,
214 per_all_people_f PERSON,
215 per_periods_of_service SERVICE
216 where person.person_id = maternity.person_id
217 and person.person_id = service.person_id
218 and maternity.maternity_id = p_maternity_id
219 --
220 -- Bug 2663899
221 -- When employee is terminated, the person.date_of_death
222 -- is null in the old record. Check the dates with
223 -- actual termination date+1
224 --
225 and nvl(service.actual_termination_date+1,service.date_start)
226 between person.effective_start_date
227 and person.effective_end_date
228 and service.date_start = (select max(serv.date_start)
229 from per_periods_of_service serv
230 where serv.person_id = person.person_id);
231 --
232 --------------------------------------------------------------------------------
233 woman csr_personal_details%rowtype;
234 g_SMP_element csr_SMP_element_details%rowtype;
235 g_SMP_Correction_element csr_SMP_element_details%rowtype;
236 --------------------------------------------------------------------------------
237 procedure get_SMP_correction_element (p_effective_date in date) is
238 --
239 l_proc varchar2(72) := g_package||'get_SMP_correction_element';
240 --
241 procedure check_parameters is
242 begin
243 --
244 hr_utility.trace (l_proc||' p_effective_date = '
245 ||to_char (p_effective_date));
246 --
247 hr_api.mandatory_arg_error (
248 p_api_name => l_proc,
249 p_argument => 'effective_date',
250 p_argument_value=> p_effective_date);
251 end check_parameters;
252 --
253 begin
254 --
255 hr_utility.set_location (l_proc,1);
256 --
257 check_parameters;
258 --
259 open csr_SMP_element_details (p_effective_date,c_SMP_Corr_element_name);
260 fetch csr_SMP_element_details into g_SMP_Correction_element;
261
262 --hr_utility.trace('g_SMP_Correction_element'||g_SMP_Correction_element);
263
264 close csr_SMP_element_details;
265 --
266 hr_utility.set_location (l_proc,100);
267 --
268 end get_SMP_correction_element;
269 --
270 --------------------------------------------------------------------------------
271 procedure get_SMP_element (p_effective_date in date) is
272 --
273 l_proc varchar2(72) := g_package||'get_SMP_element';
274 --
275 procedure check_parameters is
276 begin
277 --
278 hr_utility.trace (l_proc||' p_effective_date = '
279 ||to_char (p_effective_date));
280 --
281 hr_api.mandatory_arg_error (
282 p_api_name => l_proc,
283 p_argument => 'effective_date',
284 p_argument_value=> p_effective_date);
285 end check_parameters;
286 --
287 begin
288 --
289 hr_utility.set_location (l_proc,1);
290 --
291 check_parameters;
292 --
293 open csr_SMP_element_details (p_effective_date,c_SMP_element_name);
294 fetch csr_SMP_element_details into g_SMP_element;
295 close csr_SMP_element_details;
296 --
297 hr_utility.set_location (l_proc,100);
298 --
299 end get_SMP_element;
300 --
301 --------------------------------------------------------------------------------
302 function EXPECTED_WEEK_OF_CONFINEMENT
303 --
304 -- Returns the date on which the EWC starts
305 --
306 (p_due_date in date)
307 --
308 -- Due date comes from the woman's maternity record
309 --
310 return date is
311 --
312 -- EWC is the Sunday prior to the due date
313 --
314 -- l_EWC date := (next_day (p_due_date,'SUNDAY') -7);
315 --
316 l_EWC date;
317 l_sunday varchar2(100) := to_char(to_date('07/01/2001','DD/MM/YYYY'),'DAY');
318
319
320 begin
321 --
322 hr_utility.set_location(g_package||'EXPECTED_WEEK_OF_CONFINEMENT',1);
323
324 l_EWC := (next_day (p_due_date,l_sunday) -7);
325
326 hr_utility.trace('l_EWC: '||l_EWC);
327
328 hr_utility.set_location(g_package||'EXPECTED_WEEK_OF_CONFINEMENT',99);
329
330 return l_EWC;
331 --
332 end expected_week_of_confinement;
333 --
334 --------------------------------------------------------------------------------
335 function QUALIFYING_WEEK
336 --
337 -- Returns the start date of the QW
338 --
339 (p_due_date in date)
340 --
341 return date is
342 --
343 -- QW is the EWC minus the QW weeks from the SMP element
344 --
345 l_QW date;
346 l_SMP_element csr_SMP_element_details%rowtype;
347 --
348 begin
349 --
350 open csr_SMP_element_details (p_due_date, c_SMP_element_name);
351 fetch csr_SMP_element_details into l_SMP_element;
352 close csr_SMP_element_details;
353 --
354 l_QW := expected_week_of_confinement (p_due_date)
355 - (l_SMP_element.qualifying_week);
356 return l_QW;
357 --
358 end qualifying_week;
359 --
360 --------------------------------------------------------------------------------
361 function EARLIEST_MPP_START_DATE (p_due_date in date) return date is
362 --
363 -- The earliest MPP start date, under normal circumstances is the EWC minus
364 -- the number of weeks specified on the SMP element for earliest SMP start
365 --
366 l_earliest_MPP_start date;
367 l_SMP_element csr_SMP_element_details%rowtype;
368 --
369 begin
370 --
371 open csr_SMP_element_details (p_due_date,c_SMP_element_name);
372 fetch csr_SMP_element_details into l_SMP_element;
373 close csr_SMP_element_details;
374 --
375 l_earliest_MPP_start := Expected_Week_of_Confinement (p_due_date)
376 - (l_SMP_element.earliest_start_of_MPP);
377 return l_earliest_MPP_start;
378 --
379 end earliest_MPP_start_date;
380 --
381 --------------------------------------------------------------------------------
382 function CONTINUOUS_EMPLOYMENT_DATE (p_due_date in date) return date is
383 --
384 -- The continuous employment start date is the date on which the woman must
385 -- have been employed (and continuously from then to the QW) in order to
386 -- qualify for SMP. It is the QW minus the continuous employment period
387 -- specified on the SMP element.
388 -- Bug 447690 a woman must have started work on or before the last day of the
389 -- week which starts 182 days (26 weeks) before the last day of the QW. In
390 -- SMP weeks start on Sunday and end on Saturday.
391 --
392 l_SMP_element csr_SMP_element_details%rowtype;
393 l_Continuously_employed_since date;
394
395 l_saturday varchar2(100) := to_char(to_date('06/01/2001','DD/MM/YYYY'),'DAY');
396
397 --
398 begin
399 --
400 hr_utility.set_location(g_package||'CONTINUOUS_EMPLOYMENT_DATE',1);
401
402 open csr_SMP_element_details (p_due_date,c_SMP_element_name);
403 fetch csr_SMP_element_details into l_SMP_element;
404 close csr_SMP_element_details;
405
406 hr_utility.set_location(g_package||'CONTINUOUS_EMPLOYMENT_DATE',2);
407 --
408
409 l_Continuously_employed_since :=
410 next_day(next_day(Qualifying_Week (p_due_date),l_saturday)
411 - (l_SMP_element.continuous_employment_period),l_saturday);
412
413 hr_utility.trace('l_Continuously_employed_since: '||l_Continuously_employed_since);
414
415 hr_utility.set_location(g_package||'CONTINUOUS_EMPLOYMENT_DATE',99);
416 --
417 return l_Continuously_employed_since;
418 --
419 end continuous_employment_date;
420 --
421 --------------------------------------------------------------------------------
422 function MATERNITY_RECORD_EXISTS (p_person_id in number) return boolean is
423 --
424 cursor maternity_record is
425 select 1
426 from ssp_maternities
427 where person_id = p_person_id;
428 --
429 l_dummy number (1);
430 l_maternity_record_exists boolean;
431 --
432 begin
433 --
434 open maternity_record;
435 fetch maternity_record into l_dummy;
436 l_maternity_record_exists := maternity_record%found;
437 close maternity_record;
438 --
439 return l_maternity_record_exists;
440 --
441 end maternity_record_exists;
442 --
443 --------------------------------------------------------------------------------
444 function AVERAGE_EARNINGS return number is
445 --
446 l_average_earnings number := null;
447 l_effective_date date := null;
448 l_dummy number;
449 l_dummy2 number; -- nocopy fix, placeholder variable
450 l_user_entered varchar2(30) := 'N'; -- DFoster 1304683
451 l_absence_category varchar2(30) := 'M'; --DFoster 1304683
452 l_payment_periods number := null; --DFoster 1304683
453 l_proc varchar2(72) := g_package||'average_earnings';
454 --
455 cursor csr_average_earnings is
456 select average_earnings_amount
457 from ssp_earnings_calculations
458 where person_id = woman.person_id
459 and effective_date = l_effective_date;
460 --
461 begin
462 --
463 hr_utility.set_location ('Entering '||l_proc,1);
464 --
465 if woman.actual_birth_date is not null then
466 l_effective_date := least (greatest(woman.QW, woman.date_start), ssp_smp_support_pkg.start_of_week
467 (woman.actual_birth_date));
468 else
469 l_effective_date := greatest(woman.QW, woman.date_start);
470 end if;
471 --
472 open csr_average_earnings;
473 fetch csr_average_earnings into l_average_earnings;
474 if csr_average_earnings%notfound
475 then
476 ssp_ern_ins.ins (p_earnings_calculations_id => l_dummy,
477 p_object_version_number => l_dummy2,
478 p_person_id => woman.person_id,
479 p_effective_date => l_effective_date,
480 p_average_earnings_amount => l_average_earnings,
481 p_user_entered => l_user_entered, --DFoster 1304683
482 p_absence_category => l_absence_category, --DFoster 1304683
483 p_payment_periods => l_payment_periods); --DFoster 1304683
484 end if;
485 --
486 close csr_average_earnings;
487 --
488 hr_utility.set_location ('Leaving '||l_proc,10);
489 --
490 return l_average_earnings;
491 --
492 end average_earnings;
493 --------------------------------------------------------------------------------
494 function entitled_to_SMP (p_maternity_id in number) return boolean is
495 --
496 -- See header for description of this procedure.
497 --
498 no_prima_facia_entitlement exception;
499 invalid_absence_date exception;
500 l_work_start_date date := hr_general.end_of_time;
501 stoppage_end_date date := null;
502 no_of_absence_periods integer := 0;
503 l_proc varchar2(72) := g_package||'entitled_to_SMP';
504 l_keep_stoppages boolean default FALSE;
505 --
506 cursor csr_no_of_absences is
507 --
508 -- Get the number of distinct absences within a maternity pay period
509 --
510 select count (*)
511 from per_absence_attendances
512 where person_id = woman.person_id
513 and maternity_id = p_maternity_id;
514 --
515 -- returns entries associated with a maternity_id.
516 cursor csr_check_if_existing_entries is
517 --
518 select /*+ ORDERED use_nl(paa,paaf,etype,entry) */
519 entry.element_entry_id,
520 entry.effective_start_date
521 from per_all_assignments_f PAAF,
522 pay_element_types_f ETYPE,
523 pay_element_entries_f ENTRY
524 where PAAF.person_id = woman.person_id
525 and ETYPE.element_name = c_SMP_element_name
526 and ETYPE.legislation_code = 'GB'
527 and ENTRY.element_type_id = ETYPE.element_type_id
528 and entry.creator_type = c_SMP_creator_type
529 and entry.creator_id = p_maternity_id
530 and entry.assignment_id = PAAF.assignment_id
531 and not exists (
532 --
533 -- Do not select entries which have already had reversal action
534 -- taken against them because they are effectively cancelled out.
535 --
536 select 1
537 from pay_element_entries_f ENTRY2
538 where entry.element_entry_id=entry2.target_entry_id
539 and entry.assignment_id = entry2.assignment_id)
540 --
541 and not exists (
542 --
543 -- Do not select reversal entries
544 --
545 select 1
546 from pay_element_links_f LINK,
547 pay_element_types_f TYPE
548 where link.element_link_id = entry.element_link_id
549 and entry.effective_start_date between link.effective_start_date and link.effective_end_date
550 and link.element_type_id = type.element_type_id
551 and link.effective_start_date between type.effective_start_date and type.effective_end_date
552 and type.element_name = c_SMP_Corr_element_name);
553 --
554 l_existing_entries csr_check_if_existing_entries%rowtype;
555 --
556 procedure create_stoppage (
557 --
558 -- Create a stoppage of payment for SMP
559 --
560 p_reason in varchar2,
561 p_withhold_from in date,
562 p_withhold_to in date default null
563 ) is
564 --
565 l_proc varchar2(72) := g_package||'create_stoppage';
566 l_dummy number;
567 l_reason_id number;
568 --
569 procedure check_parameters is
570 --
571 begin
572 --
573 hr_utility.trace (l_proc||' p_reason = '||p_reason);
574 hr_utility.trace (l_proc||' withhold from '
575 ||to_char (p_withhold_from));
576 hr_utility.trace (l_proc||' withhold to '
577 ||to_char (p_withhold_to));
578 --
579 hr_api.mandatory_arg_error (
580 p_api_name => l_proc,
581 p_argument => 'reason',
582 p_argument_value=> p_reason);
583 --
584 hr_api.mandatory_arg_error (
585 p_api_name => l_proc,
586 p_argument => 'withhold_from',
587 p_argument_value=> p_withhold_from);
588 --
589 end check_parameters;
590 --
591 begin
592 --
593 hr_utility.set_location (l_proc,1);
594 --
595 check_parameters;
596 --
597 l_reason_id := ssp_smp_support_pkg.withholding_reason_id (
598 g_SMP_element.element_type_id,
599 p_reason);
600 --
601 if not ssp_smp_support_pkg.stoppage_overridden (
602 p_maternity_id => p_maternity_id,
603 p_reason_id => l_reason_id)
604 then
605 --
606 -- Only create the stoppage if there is not already a stoppage marked
607 -- as overridden. Thus, overriding a stoppage effectively blocks that
608 -- reason being used to withhold payment for this person.
609 --
610 ssp_stp_ins.ins (p_withhold_from => p_withhold_from,
611 p_withhold_to => p_withhold_to,
612 p_stoppage_id => l_dummy,
613 p_object_version_number => l_dummy,
614 p_maternity_id => p_maternity_id,
615 p_user_entered => 'N',
616 p_reason_id => l_reason_id);
617 else
618 hr_utility.trace (l_proc||' Stoppage is overridden');
619 end if;
620 --
621 hr_utility.set_location (l_proc,100);
622 --
623 end create_stoppage;
624 --
625 procedure remove_stoppages is
626 --
627 -- Remove old system, non-overridden stoppages
628 --
629 cursor csr_stoppages is
630 select stoppage_id
631 from ssp_stoppages
632 where user_entered <>'Y'
633 and override_stoppage <> 'Y'
634 and maternity_id = p_maternity_id;
635 --
636 l_dummy number;
637 l_proc varchar2 (72) := g_package||'remove_stoppages';
638 --
639 begin
640 --
641 hr_utility.set_location (l_proc,1);
642 --
643 for each_stoppage in csr_stoppages LOOP
644 ssp_stp_del.del (p_stoppage_id => each_stoppage.stoppage_id,
645 p_object_version_number => l_dummy);
646 end loop;
647 --
648 hr_utility.set_location (l_proc,100);
649 --
650 end remove_stoppages;
651 --
652 procedure check_continuity_rule is
653 --
654 -- Check that the woman has the right amount of continuous service to
655 -- qualify for SMP
656 --
657 cursor period_of_service is
658 --
659 -- Check the period of service length up to the QW start date
660 --
661 -- 5210118 starts
662 select 1
663 from per_periods_of_service
664 where person_id = woman.person_id
665 and ssp_smp_pkg.continuous_employment_date(woman.due_date) >=
666 (select max(date_start)
667 from per_periods_of_service
668 where person_id = woman.person_id
669 );
670 -- 5210118 ends
671 --and nvl (actual_termination_date, hr_general.end_of_time) -- BUG 3436510
672 -- >= woman.QW;
673 --
674 l_dummy number (1);
675 l_proc varchar2 (72) := g_package||'check_continuity_rule';
676 --
677 begin
678 --
679 hr_utility.set_location (l_proc,1);
680 --
681 open period_of_service;
682 fetch period_of_service into l_dummy;
683 --
684 if period_of_service%notfound then
685 --
686 -- Stop all SMP payment for the maternity because the woman has not
687 -- been continuously employed for long enough.
688 --
689 create_stoppage (p_withhold_from => woman.MPP_start_date,
690 p_reason => 'Insufficient employment');
691 end if;
692 --
693 close period_of_service;
694 --
695 hr_utility.set_location (l_proc,100);
696 --
697 end check_continuity_rule;
698 --
699 --
700 -- New procedure for bug 2663735
701 --
702 procedure check_employment_qw is
703 --
704 -- retrieve period of service details relating to this maternity
705 --
706 cursor csr_period_of_service_qw is
707 select nvl(ser.actual_termination_date, hr_general.end_of_time) termination_date
708 ,leaving_reason leaving_reason
709 from per_periods_of_service ser
710 where ser.person_id = woman.person_id
711 and ssp_smp_pkg.continuous_employment_date(woman.due_date)
712 between ser.date_start and nvl(ser.actual_termination_date, hr_general.end_of_time);
713 --
714 l_proc varchar2(72) := g_package||'check_employment_qw';
715 l_termination_date per_periods_of_service.actual_termination_date%type;
716 l_leaving_reason hr_lookups.meaning%type;
717 --
718 -- Local Function
719 function get_leaving_reason(p_leaving_reason in varchar2)
720 return varchar2 is
721 cursor csr_leaving_reason is
722 select upper(meaning)
723 from hr_lookups
724 where lookup_type = 'LEAV_REAS'
725 and lookup_code = p_leaving_reason
726 and enabled_flag = 'Y' ;
727 --
728 l_leaving_reason hr_lookups.meaning%type;
729 begin
730 open csr_leaving_reason;
731 fetch csr_leaving_reason into l_leaving_reason;
732 close csr_leaving_reason;
733 --
734 return nvl(l_leaving_reason,'-1');
735 end get_leaving_reason;
736 --
737 begin
738 hr_utility.set_location('Entering : '||l_proc,1);
739 --
740 open csr_period_of_service_qw;
741 fetch csr_period_of_service_qw into l_termination_date
742 ,l_leaving_reason ;
743 close csr_period_of_service_qw;
744 --
745
746 l_leaving_reason := get_leaving_reason(l_leaving_reason);
747 --
748 hr_utility.set_location(l_proc,2);
749 --
750 --
751 -- Bug 2663735
752 -- For current regulations (due date less than 06-APR-2003)
753 -- If an employee is terminated in between QW and Due Date
754 -- she is not entitled to SMP.
755 -- But the employee gets complete SMP according to the
756 -- new regulations (due date after 06-APR-2003)
757 --
758 if woman.due_date >= fnd_date.canonical_to_date('2003/04/06 00:00:00') then
759 hr_utility.set_location(l_proc,3);
760 if l_termination_date < woman.qw then
761 hr_utility.set_location(l_proc,4);
762 create_stoppage(p_withhold_from => l_termination_date + 1
763 ,p_reason => 'Not employed in QW' );
764 end if;
765 else
766 hr_utility.set_location(l_proc,5);
767 if (l_termination_date
768 between woman.qw
769 and nvl(woman.MPP_start_date
770 ,ssp_smp_pkg.earliest_mpp_start_date(woman.due_date)) )
771 and
772 (l_leaving_reason <> 'MATERNITY')
773 then
774 hr_utility.set_location(l_proc,6);
775 create_stoppage(p_withhold_from => l_termination_date + 1
776 ,p_reason => 'Insufficient employment' );
777 elsif l_termination_date < woman.qw then
778 hr_utility.set_location(l_proc,7);
779 create_stoppage(p_withhold_from => l_termination_date + 1
780 ,p_reason => 'Not employed in QW' );
781 end if;
782 hr_utility.set_location(l_proc,8);
783 end if;
784 --
785 hr_utility.set_location('Leaving : '||l_proc,9);
786 --
787 end check_employment_qw;
788 --
789 procedure check_stillbirth is
790 --
791 -- Check the pregnancy condition for qualification for SMP
792 --
793 l_proc varchar2 (72) := g_package||'check_stillbirth';
794 --
795 begin
796 --
797 hr_utility.set_location (l_proc,1);
798 --
799 -- Woman must be still pregnant, have had a live birth, or have had a
800 -- stillbirth after the threshhold week to be eligible for SMP
801 --
802 if NOT (woman.actual_birth_date is null
803 or woman.live_birth_flag = 'Y'
804 or woman.actual_birth_date > woman.EWC
805 - g_SMP_element.stillbirth_threshhold_week)
806 then
807 --
808 -- Stop SMP payment from the start of the week in which the absence
809 -- started.
810 --
811 create_stoppage (p_withhold_from => woman.MPP_start_date,
812 p_reason => 'Stillbirth');
813 end if;
814 --
815 hr_utility.set_location (l_proc,100);
816 --
817 end check_stillbirth;
818 --
819 procedure check_new_employer is
820 --
821 -- Check the woman has not been employed by a new employer after the
822 -- birth of her child
823 --
824 l_proc varchar2 (72) := g_package||'check_new_employer';
825 --
826 begin
827 --
828 hr_utility.set_location (l_proc,1);
829 --
830 if woman.start_date_with_new_employer >= woman.actual_birth_date then
831 --
832 -- Stop SMP payment from the start of the week in which the woman
833 -- started work for a new employer after the birth of her child.
834 --
835 create_stoppage (p_withhold_from => ssp_smp_support_pkg.start_of_week
836 (woman.start_date_with_new_employer),
837 p_reason => 'Worked for another employer');
838 end if;
839 --
840 hr_utility.set_location (l_proc,100);
841 --
842 end check_new_employer;
843 --
844 procedure check_maternity_allowance is
845 --
846 -- SMP ceases when SMA starts.
847 --
848 l_proc varchar2 (72) := g_package||'check_maternity_allowance';
849 --
850 begin
851 --
852 hr_utility.set_location (l_proc,1);
853 --
854 if woman.start_date_maternity_allowance is not null then
855 --
856 -- Stop SMP payment from the start of the week in which SMA was first
857 -- paid.
858 --
859 create_stoppage (p_withhold_from => ssp_smp_support_pkg.start_of_week
860 (woman.start_date_maternity_allowance),
861 p_reason => 'Employee is receiving SMA');
862 end if;
863 --
864 hr_utility.set_location (l_proc,100);
865 --
866 end check_maternity_allowance;
867 --
868 procedure check_death is
869 --
870 -- SMP ceases after the death of the woman.
871 --
872 l_proc varchar2 (72) := g_package||'check_death';
873 l_sunday varchar2(100)
874 := to_char(to_date('07/01/2001','DD/MM/YYYY'),'DAY');
875 --
876 -- Bug 2663899 Start
877 --
878 mpp_pay_period_end date;
879 current_mpp_period number := 126;
880 new_mpp_period number := 182;
881 mpp_start_date date := nvl(woman.MPP_start_date
882 ,ssp_smp_pkg.earliest_mpp_start_date
883 (woman.due_date));
884 -- Bug 2663899 End
885 cursor csr_get_week_day is
886 select to_char(mpp_start_date,'DAY')
887 from dual;
888 --
889 l_day_of_the_week varchar2(20);
890 --
891 begin
892 --
893 hr_utility.set_location (l_proc,1);
894 --
895 if woman.date_of_death is not null then
896 --
897 -- SMP ceases on the Saturday following death
898 --
899 -- Bug 2663899 start
900 /*
901 if woman.due_date >= fnd_date.canonical_to_date('2003/04/06 00:00:00')
902 then
903 mpp_pay_period_end := mpp_start_date + new_mpp_period;
904 else
905 mpp_pay_period_end := mpp_start_date + current_mpp_period;
906 end if;
907 */
908 mpp_pay_period_end := mpp_start_date + (g_SMP_element.maximum_mpp * 7);
909 --
910 if woman.date_of_death between mpp_start_date
911 and mpp_pay_period_end then
912
913 open csr_get_week_day;
914 fetch csr_get_week_day into l_day_of_the_week;
915 close csr_get_week_day;
916 -- Instead of using the next sunday, the code will use the '7-day rolling week'
917 -- method where if the MPP start on Wednesday, the week will end on Tuesday
918 -- We can assume that the MPP start date is correct as the validation is done
919 -- when the user entered the absence/maternity record.
920 create_stoppage (p_withhold_from => next_day (woman.date_of_death,
921 l_day_of_the_week) --l_sunday)
922 ,p_reason => 'Employee died');
923 end if;
924 -- Bug 2663899 end
925 end if;
926 --
927 hr_utility.set_location (l_proc,100);
928 --
929 end check_death;
930 --
931 procedure check_average_earnings is
932 --
933 -- The woman must earn enough to qualify for SMP
934 --
935 l_proc varchar2 (72) := g_package||'check_average_earnings';
936 l_average_earnings number := average_earnings;
937 l_reason_for_no_earnings varchar2 (80) := null;
938 earnings_not_derived exception;
939 --
940 begin
941 --
942 hr_utility.set_location (l_proc,1);
943 --
944 if l_average_earnings = 0
945 then
946 --
947 -- If the average earnings figure returned is zero then check that
948 -- no error message was set. Error messages will be set for system-
949 -- generated average earnings when the earnings could not be derived
950 -- for some reason, but to allow this procedure to continue, no error
951 -- will be raised.
952 --
953 l_reason_for_no_earnings:=ssp_smp_support_pkg.average_earnings_error;
954 --
955 if l_reason_for_no_earnings is not null then
956 create_stoppage (p_withhold_from => woman.MPP_start_date,
957 p_reason => l_reason_for_no_earnings);
958 --
959 raise earnings_not_derived;
960 end if;
961 end if;
962 --
963 if l_average_earnings
964 < ssp_smp_support_pkg.NI_Lower_Earnings_Limit (woman.QW)
965 then
966 --
967 -- Stop SMP payment from the MPP start date
968 --
969 create_stoppage (p_withhold_from => woman.MPP_start_date,
970 p_reason => 'Earnings too low');
971 end if;
972 --
973 hr_utility.set_location (l_proc,100);
974 --
975 exception
976 --
977 when earnings_not_derived then
978 --
979 -- Exit silently from this procedure
980 --
981 hr_utility.trace (l_proc||' Earnings not derived');
982 null;
983 --
984 end check_average_earnings;
985 --
986 procedure check_medical_evidence is
987 --
988 -- Check the acceptability of the maternity evidence
989 --
990 cursor medical is
991 select *
992 from ssp_medicals
993 where maternity_id = woman.maternity_id
994 and evidence_status = 'CURRENT';
995 --
996 l_proc varchar2 (72) := g_package||'check_medical_evidence';
997 l_medical medical%rowtype;
998 --
999 begin
1000 --
1001 hr_utility.set_location (l_proc,1);
1002 --
1003 open medical;
1004 fetch medical into l_medical;
1005 --
1006 if medical%notfound -- no medical evidence recorded
1007 or (medical%found and
1008 --
1009 -- evidence is dated too early
1010 --
1011 (l_medical.evidence_date < woman.EWC
1012 - g_SMP_element.earliest_SMP_evidence)
1013 --
1014 -- evidence was received late for no good reason
1015 --
1016 or (l_medical.evidence_received_date > woman.MPP_start_date
1017 + g_SMP_element.latest_SMP_evidence
1018 and l_medical.accept_late_evidence_flag = 'N')
1019 --
1020 -- evidence was received late, even after extension allowed
1021 --
1022 or (l_medical.evidence_received_date > woman.MPP_start_date
1023 + g_SMP_element.extended_SMP_evidence)
1024 --
1025 -- Added condition for bug 3510141
1026 -- evidence was received late, after mpp_notice_requirement_period
1027 -- Bug 3693735 Added to_number to make the code compatible with 10g
1028 or (l_medical.evidence_received_date > woman.MPP_start_date
1029 - to_number(g_SMP_element.mpp_notice_requirement)))
1030 then
1031 --
1032 -- Stop SMP payment from the start of the week in which the MPP
1033 -- started.
1034 --
1035 create_stoppage (p_withhold_from => woman.MPP_start_date,
1036 p_reason => 'Late/unacceptable evidence');
1037 end if;
1038 --
1039 close medical;
1040 --
1041 hr_utility.set_location (l_proc,100);
1042 --
1043 end check_medical_evidence;
1044 --
1045 procedure check_birth_confirmation is
1046 --
1047 -- Check that confirmation of birth was received in good time.
1048 --
1049 l_proc varchar2 (72) := g_package||'check_birth_confirmation';
1050 --
1051 begin
1052 --
1053 hr_utility.set_location (l_proc,1);
1054 --
1055 --
1056 -- This should not create a stoppage. A quick fix for bug 1021179
1057 -- is to comment out the stoppage process.
1058 --
1059 null;
1060
1061 -- if (woman.actual_birth_date is not null
1062 -- and (nvl (woman.notification_of_birth_date, sysdate)
1063 -- > woman.actual_birth_date
1064 -- + g_SMP_element.notice_of_birth_requirement))
1065 -- then
1066 --
1067 -- Stop SMP payment from the start of the week in which the MPP
1068 -- started.
1069 --
1070 -- create_stoppage (p_withhold_from => woman.MPP_start_date,
1071 -- p_reason => 'Late notification of birth');
1072 -- end if;
1073 --
1074 hr_utility.set_location (l_proc,100);
1075 --
1076 end check_birth_confirmation;
1077 --
1078 procedure check_parameters is
1079 --
1080 begin
1081 --
1082 hr_utility.trace (l_proc||' p_maternity_id = '
1083 ||to_char (p_maternity_id));
1084 --
1085 hr_api.mandatory_arg_error (
1086 p_api_name => l_proc,
1087 p_argument => 'maternity_id',
1088 p_argument_value=> p_maternity_id);
1089 --
1090 end check_parameters;
1091 --
1092 begin
1093 --
1094 hr_utility.set_location (l_proc,1);
1095 --
1096 check_parameters;
1097 --
1098 -- Get the details of the woman and her maternity.
1099 --
1100 open csr_personal_details (p_maternity_id);
1101 fetch csr_personal_details into woman;
1102 --
1103 if csr_personal_details%notfound
1104 then
1105 --
1106 -- If no maternity record exists then there can be no entitlement to SMP
1107 --
1108 close csr_personal_details;
1109 --
1110 hr_utility.trace (l_proc||' Woman has no maternity record - exiting');
1111 --
1112 raise no_prima_facia_entitlement;
1113 end if;
1114 --
1115 close csr_personal_details;
1116 --
1117 if woman.MPP_start_date is null then
1118 --
1119 -- If the MPP has not started then there is no entitlement to SMP.
1120 --
1121 hr_utility.trace (l_proc||' Woman has no MPP start date - exiting');
1122 --
1123 raise no_prima_facia_entitlement;
1124 end if;
1125 --
1126 -- Count how many absences there are for the maternity.
1127 --
1128 open csr_no_of_absences;
1129 fetch csr_no_of_absences into no_of_absence_periods;
1130 close csr_no_of_absences;
1131 --
1132 if no_of_absence_periods = 0
1133 then
1134 --
1135 -- check if entries exist despite there being no absence
1136 --
1137 open csr_check_if_existing_entries;
1138 fetch csr_check_if_existing_entries into l_existing_entries;
1139 --
1140 if csr_check_if_existing_entries%NOTFOUND
1141 then
1142 hr_utility.trace (l_proc||' Woman has not stopped work - exiting');
1143 raise no_prima_facia_entitlement;
1144 end if;
1145 --
1146 -- if entries are found then the absence has been deleted and entries remain
1147 -- that must be dealt with
1148 --
1149 while csr_check_if_existing_entries%FOUND LOOP
1150 fetch csr_check_if_existing_entries into l_existing_entries;
1151 end loop;
1152 --
1153 close csr_check_if_existing_entries;
1154 l_keep_stoppages := TRUE;
1155 end if;
1156 --
1157 -- Having established a prima facia entitlement to SMP, perform checks which
1158 -- may lead to creation of stoppages for particular periods.
1159 --
1160 hr_utility.set_location ('ssp_smp_pkg.entitled_to_SMP',2);
1161 --
1162 -- Get the SMP legislative parameters.
1163 --
1164 get_SMP_element (woman.due_date);
1165 --
1166 -- Clear stoppages created by previous calculations of SMP but if an absence
1167 -- is being deleted, then must keep stoppages so that when later comparison of
1168 -- old_entry and hypothetical_entry is done then stoppages are still there.
1169 --
1170 if not l_keep_stoppages then
1171 remove_stoppages;
1172 end if;
1173 --
1174 for absence in csr_absence_details (p_maternity_id) LOOP
1175 --
1176 -- Check that sufficient notification of absence was given
1177 --
1178
1179 if
1180 -- for pre-matured birth of baby, Bug 2620611
1181 -- Bug 2620413, check notified date of absence is less than
1182 -- or equal to the actual birth date + 21/28 days for cases
1183 -- of premature birth (extended allowable date for notifications rule)
1184 --
1185 (woman.actual_birth_date < woman.due_date
1186 and absence.date_notification > woman.actual_birth_date
1187 + g_SMP_element.MPP_notice_requirement)
1188 --
1189 or (absence.date_notification > absence.date_start
1190 - to_number(g_SMP_element.MPP_notice_requirement)
1191 -- BUG 3111736 Added to_number to make it compatible for 10g
1192 -- and there was no acceptable reason for the delay
1193 and absence.accept_late_notification_flag = 'N'
1194 -- and baby was not born prematurely
1195 and nvl(woman.actual_birth_date,hr_general.end_of_time) >= woman.due_date )
1196 then
1197 --
1198 -- Stop SMP payment from the start of the week in which the absence
1199 -- starts, to the end of the notice period
1200 --
1201 stoppage_end_date := g_SMP_element.MPP_notice_requirement
1202 + absence.date_start - 1;
1203 --
1204 create_stoppage (
1205 --p_withhold_from => ssp_smp_support_pkg.start_of_week
1206 -- (absence.date_start),
1207 -- p_withhold_to => ssp_smp_support_pkg.end_of_week (stoppage_end_date),
1208 p_withhold_from => woman.MPP_start_date,
1209 p_reason => 'Late absence notification');
1210 end if;
1211 --
1212 hr_utility.set_location ('ssp_smp_pkg.entitled_to_SMP',3);
1213 --
1214 -- Check for any work done during the MPP.
1215 --
1216 if
1217 -- this is the first absence period in the MPP
1218 csr_absence_details%rowcount = 1
1219 --
1220 -- and the absence starts after the MPP start date
1221 and absence.date_start > woman.MPP_start_date
1222 then
1223 create_stoppage (p_reason => 'Some work was done',
1224 p_withhold_from => woman.MPP_start_date,
1225 p_withhold_to => ssp_smp_support_pkg.end_of_week
1226 (absence.date_start -1));
1227 end if;
1228 --
1229 if
1230 -- this is the last absence period in the MPP
1231 csr_absence_details%rowcount = no_of_absence_periods
1232 --
1233 -- and the absence period ends before the end of the MPP
1234 and absence.date_end < (g_SMP_element.maximum_MPP * 7)
1235 + woman.MPP_start_date
1236 and woman.date_of_death is null -- Added the condition 3429978
1237 then
1238 create_stoppage (p_reason => 'Some work was done',
1239 p_withhold_from => ssp_smp_support_pkg.start_of_week
1240 (absence.date_end+1));
1241 elsif
1242 -- there is a period of work between two absences
1243 l_work_start_date < absence.date_start
1244 and l_work_start_date < (g_SMP_element.maximum_MPP * 7)
1245 + woman.MPP_start_date
1246 then
1247 create_stoppage (p_reason => 'Some work was done',
1248 p_withhold_from => ssp_smp_support_pkg.start_of_week
1249 (l_work_start_date),
1250 p_withhold_to => ssp_smp_support_pkg.end_of_week
1251 (absence.date_start -1));
1252 --
1253 if absence.date_end <> hr_general.end_of_time
1254 then
1255 l_work_start_date := absence.date_end + 1;
1256 else
1257 --
1258 -- This is not the last absence in the maternity but it has no end date.
1259 --
1260 hr_utility.trace (l_proc||' ERROR: Invalid null absence end date');
1261 --
1262 raise invalid_absence_date;
1263 end if;
1264 end if;
1265 end loop;
1266 --
1267 check_continuity_rule;
1268 check_stillbirth;
1269 check_new_employer;
1270 check_maternity_allowance;
1271 check_death;
1272 check_medical_evidence;
1273 check_birth_confirmation;
1274 -- bug 2663735
1275 check_employment_qw;
1276 check_average_earnings;
1277 --
1278 -- If we get this far the person is entitled to SMP (though stoppages may apply)
1279 --
1280 return TRUE;
1281 --
1282 exception
1283 --
1284 when invalid_absence_date then
1285 fnd_message.set_name ('PAY', 'HR_6153_ALL_PROCEDURE_FAIL');
1286 fnd_message.set_token ('PROCEDURE','ssp_smp_pkg.entitled_to_SMP');
1287 fnd_message.set_token ('STEP','3');
1288 --
1289 when no_prima_facia_entitlement then
1290 --
1291 -- Exit silently; this will allow us to call this procedure with impunity
1292 -- from absences which are not maternity absences (e.g. via a row trigger)
1293 --
1294 return FALSE;
1295 --
1296 end entitled_to_SMP;
1297 --------------------------------------------------------------------------------
1298 procedure generate_payments
1299 --
1300 --
1301 -- Starting with the start of the Maternity Pay Period (MPP), create
1302 -- a nonrecurring entry for each week of maternity absence up to the
1303 -- end of the maternity absence or to the maximum number of weeks
1304 -- specified by the SMP rules. Note that there may be more than one
1305 -- absence for a maternity, and the absences should be put together;
1306 -- however, if the woman works for any part of a week (Sun-Sat), then
1307 -- that week does not count towards maternity pay.
1308 --
1309 -- If there is a stoppage which overlaps either partially or completely
1310 -- with the period covered by an entry then skip the creation of that
1311 -- entry and move on to the next week. There are two kinds of stoppages;
1312 -- those which apply temporarily, and those which apply forever once
1313 -- started. Stoppages only apply within a maternity. If there is a
1314 -- stoppage which applies forever (ie it has no end date), then there
1315 -- is no need to continue creating entries after the start of that
1316 -- stoppage. Temporary entries should only affect creation while they
1317 -- apply. A further feature of stoppages is that they may be overridden
1318 -- by the user; if the override flag is set, then take no acount of
1319 -- that stoppage when creating entries.
1320 --
1321 -- The maximum allowed number of weeks is held as a DDF segment on the
1322 -- SMP element.
1323 --
1324 -- Whilst each entry is created to cover a particular period of absence,
1325 -- the payroll period in which the entry resides is determined
1326 -- separately. The default is that the entry will be created in the
1327 -- payroll period which covers the end of the week of absence for which
1328 -- the entry is created. If, however, that payroll period is in the
1329 -- past, or has already been processed, or is closed, or is after the
1330 -- person's last standard process date, then the entry must be placed
1331 -- in the next open period for which no main payroll run has been
1332 -- performed and which falls around or before the last standard process
1333 -- date. If the entry cannot be created in any such period, for whatever
1334 -- reason, then an error should be raised and the user required to
1335 -- resolve the problem before any entry for the absence can be created.
1336 -- The user may choose to pay SMP as a lump sum, in which case all
1337 -- entries are to be placed in the next possible payroll period after
1338 -- the start of the Maternity Pay Period.
1339 --
1340 -- If any detail of the absence is changed, then the entries must be
1341 -- recalculated to ensure that the change is reflected in the
1342 -- payments. Therefore, we may be performing the entry creation when
1343 -- entries already exist for the absence. For each entry which we are
1344 -- about to create, we must check that there is not an existing entry
1345 -- which covers the same absence period. If there is not, then we
1346 -- create the entry as planned; if there is, then we must update the
1347 -- existing one rather than create a new one, if a change is required.
1348 -- However, if that entry has already been processed in a payroll run,
1349 -- then rather than updating it, we must ensure that the
1350 -- over/underpayment is corrected at the next opportunity. This is
1351 -- done by creating two entries; one which pays the correct amount
1352 -- and another, for the SMP Correction element, which reverses the
1353 -- incorrect payment by replicating it with a negative sign in front of
1354 -- the amount entry value. Before creating the negative entry, it is
1355 -- essential to check that there is not already a negative entry for
1356 -- the incorrect entry; we do not want to overcorrect.
1357 --
1358 -- The week commencing entry value is the date of the Sunday of the
1359 -- week for which this entry is being created.
1360 --
1361 -- The Rate entry value is simply 'Higher' or 'Lower'. The number of
1362 -- entries to be created at the higher rate is determined by the
1363 -- DDF segment on the SMP element. When creating entries for SMP,
1364 -- that number of entries is to be created at the higher rate before
1365 -- any are created at the lower rate, and so stoppages are always
1366 -- affecting the lower rate first.
1367 --
1368 -- The amount entry value is determined by the rate; if it is the
1369 -- higher rate, then the higer rate DDF segment of the SMP element
1370 -- will identify a percentage of average earnings. The average
1371 -- earnings should have been calculated by the entitlement check, for
1372 -- payroll users, or entered independently by HR users. If it is the
1373 -- lower rate, then the amount to be paid is held directly in the
1374 -- lower rate DDF segment on the SMP element.
1375 --
1376 -- Each entry created by this procedure is to have a creator type
1377 -- which identifies it as an SMP entry, and a creator_id which is
1378 -- the maternity_id.
1379 --
1380 -- p_deleting parameter has been added to carry out logic for
1381 -- dealing with deleted absences
1382 --
1383 (p_maternity_id in number,
1384 p_deleting in boolean ) is
1385 --
1386 type date_table is table of date index by binary_integer;
1387 type number_table is table of number index by binary_integer;
1388 type varchar_table is table of varchar2 (80) index by binary_integer;
1389 l_proc varchar2(72) := g_package||'generate_payments';
1390 --
1391 type SMP_entry is record (
1392 --
1393 element_entry_id number_table,
1394 element_link_id number_table,
1395 assignment_id number_table,
1396 effective_start_date date_table,
1397 effective_end_date date_table,
1398 amount number_table,
1399 rate varchar_table,
1400 week_commencing date_table,
1401 recoverable_amount number_table,
1402 stopped varchar_table,
1403 dealt_with varchar_table);
1404 --
1405 --
1406 -- A store for all the SMP entries that potentially may be granted to the woman.
1407 --
1408 hypothetical_entry SMP_entry;
1409 --
1410 -- A tally of the number of weeks of the MPP which are subject to stoppages.
1411 --
1412 l_stopped_weeks number := 0;
1413 --
1414 l_high_rate varchar2 (80) := null;
1415 l_low_rate varchar2 (80) := null;
1416 -- RT entries prob
1417 l_no_of_absence_periods integer := 0;
1418 --
1419 -- p_deleting passed into save_hypothetical_entries, so that logic can be
1420 -- dealt with for deleted absences.
1421 --
1422 procedure save_hypothetical_entries (p_deleting in boolean ) is
1423 --
1424 -- Having generated the potential SMP entries, reconcile them with any
1425 -- previously granted entries for the same maternity.
1426 --
1427 cursor csr_existing_entries is
1428 --
1429 -- Get all entries and entry values for the maternity
1430 --
1431 -- Decode the rate code to give the meaning using local variables
1432 -- populated earlier by Calculate_correct_SMP_rate
1433 -- these can then be passed directly into the hr_entry_api's and
1434 -- simplifies comparison with hypo entries
1435 --
1436 select entry.element_entry_id,
1437 entry.element_link_id,
1438 entry.assignment_id,
1439 entry.effective_start_date,
1440 entry.effective_end_date,
1441 decode(ssp_smp_support_pkg.value(entry.element_entry_id,
1442 ssp_smp_pkg.c_rate_name),'HIGH',l_high_rate,l_low_rate) RATE,
1443 /*to_date (ssp_smp_support_pkg.value
1444 (entry.element_entry_id,
1445 ssp_smp_pkg.c_week_commencing_name),
1446 'DD-MON-YYYY') WEEK_COMMENCING,*/
1447 fnd_date.chardate_to_date(ssp_smp_support_pkg.value
1448 (entry.element_entry_id,ssp_smp_pkg.c_week_commencing_name)) WEEK_COMMENCING,
1449 to_number(ssp_smp_support_pkg.value (entry.element_entry_id,
1450 ssp_smp_pkg.c_amount_name)) AMOUNT,
1451 to_number(ssp_smp_support_pkg.value (entry.element_entry_id,
1452 ssp_smp_pkg.c_recoverable_amount_name)) RECOVERABLE_AMOUNT
1453 from pay_element_entries_f ENTRY,
1454 per_all_assignments_f asg
1455 where creator_type = c_SMP_creator_type
1456 and creator_id = p_maternity_id
1457 and asg.person_id = woman.person_id
1458 and asg.assignment_id = entry.assignment_id
1459 and entry.effective_start_date between asg.effective_start_date
1460 and asg.effective_end_date
1461 and not exists (
1462 --
1463 -- Do not select entries which have already had reversal action taken
1464 -- against them because they are effectively cancelled out.
1465 --
1466 select 1
1467 from pay_element_entries_f ENTRY2
1468 where entry.element_entry_id= entry2.target_entry_id
1469 and entry.assignment_id = entry2.assignment_id)
1470 --
1471 and not exists (
1472 --
1473 -- Do not select reversal entries
1474 --
1475 select 1
1476 from pay_element_links_f LINK,
1477 pay_element_types_f TYPE
1478 where link.element_link_id = entry.element_link_id
1479 and entry.effective_start_date between link.effective_start_date
1480 and link.effective_end_date
1481 and link.element_type_id = type.element_type_id
1482 and link.effective_start_date between type.effective_start_date
1483 and type.effective_end_date
1484 and type.element_name = c_SMP_Corr_element_name);
1485 --
1486 cursor csr_no_of_absences is
1487 --
1488 -- Get the number of distinct absences within a maternity pay period
1489 --
1490 select count (*)
1491 from per_absence_attendances
1492 where person_id = woman.person_id
1493 and maternity_id = p_maternity_id;
1494 --
1495 l_ins_corr_ele boolean;
1496 l_dummy number;
1497 Entry_number integer;
1498 l_ern_calc_id number;
1499 l_ob_v_no number;
1500 l_new_ob_v_no number;
1501 l_proc varchar2 (72) := g_package||'save_hypothetical_entries';
1502 --
1503 -- This procedure was a private procedure in the function entitled_to_smp. I
1504 -- wanted to call it within this procedure (generate_payments) aswell, so
1505 -- instead of making it a public procedure I have copied the procedure to here.
1506 --
1507 procedure remove_stoppages is
1508 --
1509 -- Remove old system, non-overridden stoppages
1510 --
1511 cursor csr_stoppages is
1512 --
1513 select stoppage_id
1514 from ssp_stoppages
1515 where user_entered <>'Y'
1516 and override_stoppage <> 'Y'
1517 and maternity_id = p_maternity_id;
1518 --
1519 l_dummy number;
1520 l_proc varchar2 (72) := g_package||'.remove_stoppages';
1521 --
1522 begin
1523 --
1524 hr_utility.set_location (l_proc,1);
1525 --
1526 for each_stoppage in csr_stoppages LOOP
1527 ssp_stp_del.del (p_stoppage_id => each_stoppage.stoppage_id,
1528 p_object_version_number => l_dummy);
1529 end loop;
1530 --
1531 hr_utility.set_location (l_proc,100);
1532 --
1533 end remove_stoppages;
1534 --
1535 begin
1536 --
1537 --hr_utility.trace_on(null,'ssp');
1538 hr_utility.set_location('Entering: '||l_proc,10);
1539
1540 hr_utility.trace('woman.due_date='||woman.due_date);
1541 --
1542 get_SMP_correction_element (woman.due_date);
1543 --
1544 -- Check each existing SMP entry in turn against all the potential new ones.
1545 --
1546 <<OLD_ENTRIES>>
1547
1548 hr_utility.trace('Old entries');
1549
1550
1551 for old_entry in csr_existing_entries
1552 LOOP
1553 --First loop through the hypothetical entries to see if there is one
1554 --which covers the same week as the old entry and is not subject to
1555 --a stoppage. If there isn't one, invalidate the old entry.
1556 --Assume we don't need to correct the entry until we discover otherwise:
1557 --
1558
1559 hr_utility.trace('Entered csr_existing_entries');
1560
1561 l_ins_corr_ele := FALSE;
1562 begin
1563 hr_utility.trace('Entering begin');
1564 entry_number := 0;
1565 if p_deleting then
1566 hr_utility.trace('Raising error');
1567 raise no_data_found; -- enter exception handler
1568 end if;
1569 LOOP
1570
1571 hr_utility.trace('First loop');
1572 entry_number := entry_number +1;
1573
1574 -- Exit the loop when we find a hypothetical entry covering the
1575 -- same week as the old entry, which is not subject to a stoppage.
1576 -- If no such match is found, then we will reach the end of the
1577 -- pl/sql table and attempt to read beyond the existing rows; this
1578 -- will cause us to enter the exception handler and indicate that
1579 -- no match was found.
1580
1581 exit when ((old_entry.week_commencing
1582 = hypothetical_entry.week_commencing (entry_number)
1583 and not hypothetical_entry.stopped (entry_number) = 'TRUE'
1584 and g_smp_update = 'N')
1585 or (old_entry.effective_start_date
1586 = hypothetical_entry.effective_start_date (entry_number)
1587 and old_entry.week_commencing
1588 = hypothetical_entry.week_commencing (entry_number)
1589 and not hypothetical_entry.stopped (entry_number) = 'TRUE'
1590 and g_smp_update = 'Y'));
1591
1592 hr_utility.trace('Exiting');
1593 end loop;
1594
1595 hr_utility.trace (l_proc||' Old entry / Hypo entry time Match with values:');
1596 hr_utility.trace (l_proc||' Rate: '
1597 ||old_entry.rate||' / '
1598 ||hypothetical_entry.rate (Entry_number));
1599 hr_utility.trace (l_proc||' Amount: '
1600 ||old_entry.amount||' / '
1601 ||hypothetical_entry.amount (entry_number));
1602 hr_utility.trace (l_proc||' Recoverable: '
1603 ||old_entry.recoverable_amount||' / '
1604 ||hypothetical_entry.recoverable_amount (entry_number));
1605 hr_utility.trace (l_proc||' Week Comm: '
1606 ||hypothetical_entry.week_commencing (entry_number) );
1607 --A hypo entry covers the same week as the old one
1608 if old_entry.rate = hypothetical_entry.rate (entry_number)
1609 and old_entry.amount = hypothetical_entry.amount(entry_number)
1610 and old_entry.recoverable_amount
1611 = hypothetical_entry.recoverable_amount (entry_number)
1612 then
1613 -- the hypo entry has the same values as the old one
1614 -- don't create a correction element.
1615 -- don't create a new entry
1616 hypothetical_entry.dealt_with (entry_number) := 'TRUE';
1617 hr_utility.trace (l_proc||' leave unchanged');
1618 else
1619 if ssp_smp_support_pkg.entry_already_processed
1620 (old_entry.element_entry_id)
1621 then l_ins_corr_ele := TRUE;
1622 hr_utility.trace (l_proc||' processed - correct it');
1623 else
1624 -- update old entry
1625 hr_utility.trace (l_proc||' unprocessed - update it');
1626 hr_entry_api.update_element_entry (
1627 p_dt_update_mode => 'CORRECTION',
1628 p_session_date => old_entry.effective_start_date,
1629 p_element_entry_id => old_entry.element_entry_id,
1630 p_input_value_id1 => g_SMP_element.rate_id,
1631 p_input_value_id2 => g_SMP_element.amount_id,
1632 p_input_value_id3 => g_SMP_element.recoverable_amount_id,
1633 p_entry_value1=> hypothetical_entry.rate (entry_number),
1634 p_entry_value2=> hypothetical_entry.amount(entry_number),
1635 p_entry_value3=>
1636 hypothetical_entry.recoverable_amount (entry_number));
1637 --
1638 --prevent insertion of new entry
1639 --
1640 hypothetical_entry.dealt_with (entry_number) := 'TRUE';
1641 end if;
1642 end if;
1643 exception
1644
1645 when no_data_found then
1646 -- There was no new entry which exactly matched the old entry.
1647 -- or we are deleting.
1648 entry_number := null;
1649 hr_utility.trace (l_proc||' No Old entry - Hypo entry time Match');
1650 hr_utility.trace (l_proc||' or p_deleting is true');
1651 hr_utility.trace (l_proc||' Old entry values:');
1652 hr_utility.trace (l_proc||' Rate: '||old_entry.rate);
1653 hr_utility.trace (l_proc||' Amount: '||old_entry.amount);
1654 hr_utility.trace (l_proc||' Recoverable: '
1655 ||old_entry.recoverable_amount);
1656 if ssp_smp_support_pkg.entry_already_processed
1657 (old_entry.element_entry_id)
1658 then l_ins_corr_ele := TRUE;
1659 hr_utility.trace (l_proc||' Old entry already processed');
1660 else
1661 hr_utility.trace (l_proc||' Old entry NOT already processed');
1662 --Old entry not already processed so delete it
1663 hr_entry_api.delete_element_entry (
1664 p_dt_delete_mode => 'ZAP',
1665 p_session_date => old_entry.effective_start_date,
1666 p_element_entry_id => old_entry.element_entry_id);
1667 end if;
1668 when others then
1669 hr_utility.trace('Entered error');
1670 hr_utility.trace('SQL ERROR:='||SQLERRM);
1671 end;
1672 if l_ins_corr_ele
1673 then
1674 -- Create a correction element to reverse the old entry. Then create a
1675 -- brand new entry with the correct values.
1676 --
1677 hr_utility.trace (l_proc ||
1678 ' Inserting CORRECTION entry for week commencing ' ||
1679 to_char (old_entry.week_commencing));
1680 hr_utility.trace (l_proc||' Old value / New value:');
1681 if entry_number is null then
1682 hr_utility.trace (l_proc||' Rate: '
1683 ||old_entry.rate||' / NA');
1684 hr_utility.trace (l_proc||' Amount: '
1685 ||old_entry.amount||' / NA');
1686 hr_utility.trace (l_proc||' Recoverable: '
1687 ||old_entry.recoverable_amount||' / NA');
1688 else
1689 hr_utility.trace (l_proc||' Rate: '
1690 ||old_entry.rate||' / '
1691 ||hypothetical_entry.rate (Entry_number));
1692 hr_utility.trace (l_proc||' Amount: '
1693 ||old_entry.amount||' / '
1694 ||hypothetical_entry.amount (entry_number));
1695 hr_utility.trace (l_proc||' Recoverable: '
1696 ||old_entry.recoverable_amount||' /'
1697 ||hypothetical_entry.recoverable_amount (entry_number));
1698 end if;
1699 --
1700 -- Determine the next available period in which to place the
1701 -- correction entry
1702 --
1703
1704 hr_utility.trace('Correction Entry');
1705
1706 ssp_smp_support_pkg.get_entry_details (
1707 p_date_earned => old_entry.week_commencing,
1708 p_last_process_date => woman.final_process_date,
1709 p_person_id => woman.person_id,
1710 p_element_type_id => g_SMP_Correction_element.element_type_id,
1711 p_element_link_id => old_entry.element_link_id,
1712 p_assignment_id => old_entry.assignment_id,
1713 p_effective_start_date => old_entry.effective_start_date,
1714 p_effective_end_date => old_entry.effective_end_date,
1715 p_pay_as_lump_sum => woman.pay_SMP_as_lump_sum);
1716 --
1717 -- hr_entry_api's take the lookup meanings not the lookup codes.
1718 -- Fix to Bug 590966 converted rate codes to meanings before calling the
1719 -- api. Later fix 647543 made old_entry (csr_existing_entries) return
1720 -- the meaning, so rate passed directly.
1721 --
1722
1723 hr_utility.trace('Insert element entry');
1724
1725 hr_entry_api.insert_element_entry (
1726 p_effective_start_date=> old_entry.effective_start_date,
1727 p_effective_end_date => old_entry.effective_end_date,
1728 p_element_entry_id => l_dummy,
1729 p_target_entry_id => old_entry.element_entry_id,
1730 p_assignment_id => old_entry.assignment_id,
1731 p_element_link_id => old_entry.element_link_id,
1732 p_creator_type => c_SMP_creator_type,
1733 p_creator_id => p_maternity_id,
1734 p_entry_type => c_SMP_entry_type,
1735 p_input_value_id1=> g_SMP_correction_element.rate_id,
1736 p_input_value_id2=> g_SMP_correction_element.week_commencing_id,
1737 p_input_value_id3=> g_SMP_correction_element.amount_id,
1738 p_input_value_id4=> g_SMP_correction_element.recoverable_amount_id,
1739 p_entry_value1=> old_entry.rate,
1740 --p_entry_value2 => to_char(old_entry.week_commencing,'DD-MON-YYYY'),
1741 p_entry_value2 => fnd_date.date_to_chardate(old_entry.week_commencing),
1742 p_entry_value3=> old_entry.amount * -1,
1743 p_entry_value4=> old_entry.recoverable_amount * -1);
1744 --
1745 --New entry will be created by brand_new_entries loop if not p_deleting
1746 end if;
1747 --
1748 end loop old_entries;
1749 --
1750 -- Having been through all the existing entries, we now check that we
1751 -- have dealt with all the newly derived entries by inserting any which
1752 -- were not flagged as dealt with during the above actions.
1753 --
1754 hr_utility.set_location (l_proc,20);
1755 --
1756 <<BRAND_NEW_ENTRIES>>
1757 begin
1758 if p_deleting then
1759 hr_utility.trace('Deleting an absence so don''t insert entries');
1760 else
1761 for new_entry in 1..g_SMP_element.maximum_MPP LOOP
1762 if (not hypothetical_entry.dealt_with (new_entry) = 'TRUE')
1763 and (not hypothetical_entry.stopped (new_entry) = 'TRUE')
1764 then
1765 hr_entry_api.insert_element_entry (
1766 p_effective_start_date =>
1767 hypothetical_entry.effective_start_date (new_entry),
1768 p_effective_end_date =>
1769 hypothetical_entry.effective_end_date (new_entry),
1770 p_element_entry_id => l_dummy,
1771 p_assignment_id => hypothetical_entry.assignment_id (new_entry),
1772 p_element_link_id => hypothetical_entry.element_link_id (new_entry),
1773 p_creator_type => c_SMP_creator_type,
1774 p_creator_id => p_maternity_id,
1775 p_entry_type => c_SMP_entry_type,
1776 p_input_value_id1 => g_SMP_element.rate_id,
1777 p_input_value_id2 => g_SMP_element.week_commencing_id,
1778 p_input_value_id3 => g_SMP_element.amount_id,
1779 p_input_value_id4 => g_SMP_element.recoverable_amount_id,
1780 p_entry_value1 => hypothetical_entry.rate (new_entry),
1781 -- p_entry_value2 => hypothetical_entry.week_commencing (new_entry),
1782 p_entry_value2 => to_char(hypothetical_entry.week_commencing(new_entry),'DD-MON-YYYY'),
1783 p_entry_value3 => hypothetical_entry.amount (new_entry),
1784 p_entry_value4 =>
1785 hypothetical_entry.recoverable_amount (new_entry));
1786 end if;
1787 end loop brand_new_entries;
1788 end if;
1789 exception
1790 when no_data_found then
1791 --
1792 -- We have run out of hypothetical entries to insert
1793 --
1794 null;
1795 --
1796 end;
1797 --
1798 -- Orphaned stoppages, associated with deleted absence can now be deleted
1799 -- This replaces cross product constraints that are no longer allowed.
1800 --
1801 open csr_no_of_absences;
1802 fetch csr_no_of_absences into l_no_of_absence_periods;
1803 close csr_no_of_absences;
1804 --
1805 if l_no_of_absence_periods = 0 then
1806 remove_stoppages;
1807 end if;
1808 --
1809 hr_utility.set_location(' Leaving: '||l_proc,100);
1810 --
1811 end save_hypothetical_entries;
1812 --
1813 procedure derive_SMP_week (p_week_number in integer) is
1814 --
1815 -- Derive the start and end dates of the week covered by the SMP
1816 -- payment. This is done by finding out how many weeks into the MPP
1817 -- we are and finding the offset from the start date.
1818 --
1819 begin
1820 --
1821 hr_utility.set_location ('Entering: ssp_smp_pkg.derive_SMP_week',1);
1822 hr_utility.trace ('Entry number = '||to_char (p_week_number));
1823 --
1824 hypothetical_entry.week_commencing (p_week_number)
1825 := (woman.MPP_start_date + ((p_week_number -1) * 7));
1826 --
1827 hypothetical_entry.dealt_with (p_week_number) := 'FALSE';
1828 hypothetical_entry.stopped (p_week_number) := 'FALSE';
1829 hypothetical_entry.element_link_id (p_week_number) := null;
1830 hypothetical_entry.assignment_id (p_week_number) := null;
1831 --
1832 hr_utility.trace ('week_commencing = '
1833 ||to_char (hypothetical_entry.week_commencing (p_week_number)));
1834 --
1835 hr_utility.set_location ('Leaving : ssp_smp_pkg.derive_SMP_week',100);
1836 --
1837 end derive_SMP_week;
1838 --
1839 procedure Check_SMP_stoppages (p_week_number in integer) is
1840 --
1841 -- Find any SMP stoppage for the maternity which overlaps a date range
1842 --
1843 employee_died varchar2 (30) := 'Employee died';
1844 --
1845 cursor csr_stoppages (p_start_date in date, p_end_date in date) is
1846 --
1847 -- Find any non-overridden stoppages
1848 --
1849 select 1
1850 from ssp_stoppages STP,
1851 ssp_withholding_reasons WRE
1852 where stp.override_stoppage <> 'Y'
1853 --
1854 -- and the stoppage ovelaps the period or the stoppage is for
1855 -- death and is prior to the period
1856 --
1857 and ((wre.reason <> employee_died
1858 and stp.withhold_from <= p_end_date
1859 and nvl (stp.withhold_to, hr_general.end_of_time)
1860 >= p_start_date)
1861 --
1862 or (wre.reason = employee_died
1863 -- Bug 2663899
1864 and stp.withhold_from <= p_end_date))
1865 --
1866 and stp.maternity_id = p_maternity_id
1867 and stp.reason_id = wre.reason_id;
1868 --
1869 l_dummy integer (1);
1870 --
1871 begin
1872 --
1873 hr_utility.set_location ('ssp_smp_pkg.Check_SMP_stoppages',1);
1874 --
1875 hypothetical_entry.stopped (p_week_number) := 'FALSE';
1876 --
1877 open csr_stoppages (
1878 hypothetical_entry.week_commencing (p_week_number),
1879 ssp_smp_support_pkg.end_of_week
1880 (hypothetical_entry.week_commencing (p_week_number)));
1881 --
1882 fetch csr_stoppages into l_dummy;
1883 --
1884 if csr_stoppages%found
1885 then
1886 --
1887 -- There is an overlap between the SMP week and a stoppage so no SMP
1888 -- is payable.
1889 --
1890 hypothetical_entry.stopped (p_week_number) := 'TRUE';
1891 --
1892 hr_utility.trace ('Entry is STOPPED');
1893 --
1894 -- Keep a tally of the number of stopped weeks
1895 --
1896 l_stopped_weeks := l_stopped_weeks +1;
1897 end if;
1898 --
1899 close csr_stoppages;
1900 --
1901 hr_utility.set_location ('ssp_smp_pkg.Check_SMP_stoppages',10);
1902 --
1903 end Check_SMP_stoppages;
1904 --
1905 procedure Calculate_correct_SMP_rate (p_week_number in number) is
1906 --
1907 -- The entry API takes the lookup meanings so we must find
1908 -- the meanings rather than the codes for SMP rates.
1909 --
1910 cursor csr_rate_meaning (p_rate_band varchar2) is
1911 --
1912 select meaning
1913 from hr_lookups
1914 where lookup_type = 'SMP_RATES'
1915 and lookup_code = p_rate_band;
1916 --
1917 begin
1918 --
1919 hr_utility.set_location ('ssp_smp_pkg.Calculate_correct_SMP_rate',1);
1920 --
1921 if l_high_rate is null then
1922 --
1923 -- Get the meanings for the rate bands
1924 --
1925 -- Get the higher rate band
1926 --
1927 open csr_rate_meaning ('HIGH');
1928 fetch csr_rate_meaning into l_high_rate;
1929 close csr_rate_meaning;
1930 --
1931 -- Get the lower rate band
1932 --
1933 open csr_rate_meaning ('LOW');
1934 fetch csr_rate_meaning into l_low_rate;
1935 close csr_rate_meaning;
1936 end if;
1937 --
1938 if (p_week_number - l_stopped_weeks)
1939 <= g_SMP_element.period_at_higher_rate
1940 then
1941 hr_utility.set_location ('ssp_smp_pkg.Calculate_correct_SMP_rate',1);
1942 --
1943 -- We have not yet given the employee all their higher rate weeks
1944 --
1945 hypothetical_entry.rate (p_week_number) := l_high_rate;
1946 else
1947 hypothetical_entry.rate (p_week_number) := l_low_rate;
1948 end if;
1949 --
1950 hr_utility.trace ('SMP Rate = '
1951 ||hypothetical_entry.rate (p_week_number));
1952 --
1953 hr_utility.set_location ('ssp_smp_pkg.Calculate_correct_SMP_rate',10);
1954 --
1955 end Calculate_correct_SMP_rate;
1956 --
1957 procedure Calculate_SMP_amounts (p_week_number in integer, p_MPP_start_date in date) is
1958 --
1959 begin
1960 --
1961 hr_utility.set_location('Entering: ssp_smp_pkg.Calculate_SMP_amounts',1);
1962 --
1963 -- Get the SMP element for each week in case the SMP rate has changed
1964 --
1965 get_SMP_element (hypothetical_entry.week_commencing (p_week_number));
1966 --
1967 if hypothetical_entry.rate (p_week_number) = l_high_rate then
1968 --
1969 -- The higher rate is the greater of the low SMP flat rate amount and
1970 -- the legislation-specified proportion of average earnings (rounded
1971 -- UP to the nearest penny)
1972 --
1973 hr_utility.trace('Calculate at high rate');
1974 hr_utility.trace('p_MPP_start_date : '||fnd_date.date_to_canonical(p_MPP_start_date));
1975 if p_MPP_start_date >= fnd_date.canonical_to_date('2003/04/06 00:00:00') then
1976 hr_utility.trace('MPP start date after 06-APR-2003, therefore 90 percent of average earnings');
1977 hypothetical_entry.amount (p_week_number)
1978 := round((average_earnings * g_SMP_element.higher_SMP_rate)
1979 + 0.0049,2);
1980 else
1981 hr_utility.trace('Due date before 06-APR-2003, therfore under higher rate with lower rate, else 90 percent of average earnings');
1982 hypothetical_entry.amount (p_week_number)
1983 := greatest (round (
1984 (average_earnings * g_SMP_element.higher_SMP_rate)
1985 + 0.0049,2),
1986 g_SMP_element.lower_SMP_rate);
1987 end if;
1988 else
1989 hr_utility.trace('Calculating for lower, therfore we need to find out if week commencing date is before or after 06-APR-2003, week_commencing : '||fnd_date.date_to_canonical(hypothetical_entry.week_commencing(p_week_number)));
1990 if hypothetical_entry.week_commencing(p_week_number) <
1991 fnd_date.canonical_to_date('2003/04/06 00:00:00') then
1992 hr_utility.trace('Decided week commencing before 06-APR-2003');
1993 -- Any SMP weeks paid before 06-APR-2003 to be paid
1994 -- at floored lower amount
1995 hypothetical_entry.amount (p_week_number)
1996 := g_SMP_element.lower_SMP_rate;
1997 elsif (hypothetical_entry.week_commencing(p_week_number) >=
1998 fnd_date.canonical_to_date('2003/04/06 00:00:00') and
1999 p_MPP_start_date < fnd_date.canonical_to_date('2003/04/06 00:00:00')) then
2000 -- For payments after 06-APR-2003 for maternities with MPP start date
2001 -- prior to 06-APR-2003, the payment must be underpinned by SMP
2002 -- lower rate
2003 hr_utility.trace('Week commenicng is after 06-APR-2003, but MPP start date is before 06-APR-2003, therfore amount must be underpinned');
2004 if g_SMP_element.lower_SMP_rate > round(
2005 (average_earnings * g_SMP_element.higher_SMP_rate)
2006 + 0.0049,2) then
2007 -- Payment to be underpinned
2008 hr_utility.trace('Average earnings * 90 percent less than lower rate, therfore underpin');
2009 hypothetical_entry.amount (p_week_number)
2010 := g_SMP_element.lower_SMP_rate;
2011 else
2012 -- Calculated amount is higher than lower SMP rate, so
2013 -- assign calculated amount
2014 hr_utility.trace('average earnings * 90 percent greater than lower rate, no need to underpin');
2015 hypothetical_entry.amount (p_week_number)
2016 := least(round(
2017 (average_earnings * g_SMP_element.higher_SMP_rate)
2018 + 0.0049,2), g_SMP_element.standard_SMP_rate);
2019 end if;
2020 else
2021 hr_utility.trace('Due date and week Commencing both after 06-APr-2003, therfore lowest of average earnings and standard rate');
2022 hypothetical_entry.amount (p_week_number)
2023 := least(round(
2024 (average_earnings * g_SMP_element.higher_SMP_rate)
2025 + 0.0049,2), g_SMP_element.standard_SMP_rate);
2026 end if;
2027 end if;
2028 --
2029 hypothetical_entry.recoverable_amount (p_week_number)
2030 := round (hypothetical_entry.amount (p_week_number)
2031 * g_SMP_element.recovery_rate,2);
2032 --
2033 hr_utility.trace ('SMP amount = '
2034 ||to_char (hypothetical_entry.amount (p_week_number)));
2035 hr_utility.trace ('Recoverable amount = '
2036 ||to_char (hypothetical_entry.recoverable_amount (p_week_number)));
2037 --
2038 hr_utility.set_location('Leaving : ssp_smp_pkg.Calculate_SMP_amounts',100);
2039 --
2040 end calculate_SMP_amounts;
2041 --
2042 procedure check_parameters is
2043 begin
2044 hr_api.mandatory_arg_error (
2045 p_api_name => l_proc,
2046 p_argument => 'maternity_id',
2047 p_argument_value=> p_maternity_id);
2048 --
2049 end check_parameters;
2050 --
2051 begin
2052 --
2053 hr_utility.set_location ('ssp_smp_pkg.generate_payments',1);
2054 --
2055 check_parameters;
2056 --
2057 <<SMP_WEEKS>>
2058 --
2059 if woman.MPP_start_date is not null then
2060 for week_number in 1..g_SMP_element.maximum_MPP
2061 LOOP
2062 --
2063 -- Derive hypothetical entries ie those entries which would be applied for a
2064 -- completely new maternity. Store them internally because we must check
2065 -- previously created entries before applying the hypothetical entries to the
2066 -- database.
2067 --
2068 Derive_SMP_week (week_number);
2069 Check_SMP_stoppages (week_number);
2070 Calculate_correct_SMP_rate (week_number);
2071 Calculate_SMP_amounts (week_number, woman.MPP_start_date);
2072 --
2073 if (hypothetical_entry.stopped (week_number) = 'FALSE') then
2074 --
2075 -- Get the entry details unless the entry has been stopped (in which case
2076 -- we do not need the entry details and errors may occur if we call the
2077 -- procedure; eg the woman's assignment ends)
2078 --
2079 ssp_smp_support_pkg.get_entry_details (
2080 p_date_earned => hypothetical_entry.week_commencing
2081 (week_number),
2082 p_pay_as_lump_sum => woman.pay_SMP_as_lump_sum,
2083 p_last_process_date => woman.final_process_date,
2084 p_person_id => woman.person_id,
2085 p_element_type_id => g_SMP_element.element_type_id,
2086 p_element_link_id => hypothetical_entry.element_link_id
2087 (week_number),
2088 p_assignment_id => hypothetical_entry.assignment_id
2089 (week_number),
2090 p_effective_start_date => hypothetical_entry.effective_start_date
2091 (week_number),
2092 p_effective_end_date => hypothetical_entry.effective_end_date
2093 (week_number));
2094 end if;
2095 end loop SMP_weeks;
2096 end if;
2097 --
2098 Save_hypothetical_entries(p_deleting);
2099 --
2100 end generate_payments;
2101 --
2102 --------------------------------------------------------------------------------
2103 procedure SMP_control (p_maternity_id in number,
2104 p_deleting in boolean ) is
2105 --
2106 -- p_deleting parameter added to deal with absences being deleted, without
2107 -- maternity being deleted.
2108 --
2109 cursor csr_maternity is
2110 --
2111 -- Find out if the maternity exists
2112 --
2113 select 1
2114 from ssp_maternities
2115 where maternity_id = p_maternity_id;
2116 --
2117 cursor csr_entries is
2118 --
2119 -- Get all element entries associated with a maternity
2120 --
2121 select /*+ ORDERED use_nl(paa,paaf,etype,entry) */
2122 entry.element_entry_id,
2123 entry.effective_start_date
2124 from per_absence_attendances PAA,
2125 per_all_assignments_f PAAF,
2126 pay_element_entries_f entry
2127 where PAA.maternity_id = p_maternity_id
2128 and PAAF.person_id = PAA.person_id
2129 and entry.creator_type = 'M'
2130 and entry.creator_id = p_maternity_id
2131 and entry.assignment_id = paaf.assignment_id;
2132 --
2133 cursor csr_count_absences is
2134 select count(*)
2135 from ssp_maternities mat,
2136 per_absence_attendances ab
2137 where mat.maternity_id = p_maternity_id
2138 and ab.person_id = mat.person_id
2139 and ab.maternity_id = mat.maternity_id;
2140 --
2141 l_count number;
2142 l_dummy number;
2143 l_proc varchar2 (72) := g_package||'SMP_control';
2144 --
2145 begin
2146 --
2147 hr_utility.set_location (l_proc,1);
2148 --
2149 open csr_maternity;
2150 fetch csr_maternity into l_dummy;
2151 --
2152 if csr_maternity%found then
2153 --
2154 -- Recalculate SMP
2155 --
2156 if entitled_to_SMP (p_maternity_id) then
2157 open csr_count_absences;
2158 fetch csr_count_absences into l_count;
2159 close csr_count_absences;
2160 if l_count > 0 then
2161 generate_payments (p_maternity_id, false);
2162 else
2163 generate_payments (p_maternity_id, p_deleting);
2164 end if;
2165 elsif p_deleting then
2166 -- not entitled but deleting absence then
2167 generate_payments (p_maternity_id, p_deleting);
2168 end if;
2169 else
2170 --
2171 -- The maternity may have been deleted. Remove any element entries associated
2172 -- with it (the absences, stoppages and medicals are handled by constraints).
2173 --
2174 for obsolete in csr_entries LOOP
2175 hr_utility.trace (l_proc||' Deleting element entry_id '||
2176 to_char (obsolete.element_entry_id));
2177 hr_utility.trace (l_proc||'-------------------------------------------');
2178 --
2179 hr_entry_api.delete_element_entry (
2180 p_dt_delete_mode => 'ZAP',
2181 p_session_date => obsolete.effective_start_date,
2182 p_element_entry_id => obsolete.element_entry_id);
2183 end loop;
2184 end if;
2185 --
2186 g_smp_update := 'N';
2187 --
2188 hr_utility.set_location (l_proc,100);
2189 --
2190 end SMP_control;
2191 --
2192 --------------------------------------------------------------------------------
2193 procedure ins_ssp_temp_affected_rows_mat(p_maternity_id in number,
2194 p_deleting in boolean ) is
2195 --
2196 -- Inserts a row in ssp_temp_affected_rows for the maternity, if not there
2197 --
2198 l_proc varchar2 (72) := g_package||'ins_ssp_temp_affected_rows_mat';
2199 l_deleting_ch varchar2(1);
2200 --
2201 begin
2202 --
2203 hr_utility.set_location('Entering:'||l_proc,1);
2204 if p_deleting then
2205 l_deleting_ch := 'Y';
2206 else
2207 l_deleting_ch := 'N';
2208 end if;
2209 --
2210 if p_maternity_id is not null then
2211 hr_utility.trace (l_proc||' Saving maternity_id #' || p_maternity_id ||
2212 ' for recalculation (p_del = '||l_deleting_ch||').');
2213 --
2214 insert into ssp_temp_affected_rows (MATERNITY_ID, p_deleting, locked)
2215 select p_maternity_id, l_deleting_ch, userenv('sessionid')
2216 from sys.dual
2217 where not exists
2218 (select null
2219 from ssp_temp_affected_rows t2
2220 where t2.maternity_id = p_maternity_id);
2221 end if;
2222 --
2223 hr_utility.set_location('Leaving :'||l_proc,100);
2224 --
2225 end ins_ssp_temp_affected_rows_mat;
2226 --
2227 --------------------------------------------------------------------------------
2228 procedure absence_control (p_maternity_id in number,
2229 p_deleting in boolean ) is
2230 --
2231 -- Handle the event of DML on per_absence_attendances
2232 --
2233 l_proc varchar2 (72) := g_package||'absence_control';
2234 --
2235 begin
2236 --
2237 hr_utility.set_location (l_proc,1);
2238 --
2239 g_smp_update := 'N';
2240 --
2241 if p_maternity_id is not null then
2242 ins_ssp_temp_affected_rows_mat(p_maternity_id, p_deleting);
2243 end if;
2244 --
2245 hr_utility.set_location (l_proc,100);
2246 --
2247 end absence_control;
2248 --------------------------------------------------------------------------------
2249 procedure maternity_control (p_maternity_id in number) is
2250 --
2251 l_proc varchar2 (72) := g_package||'maternity_control';
2252 --
2253 begin
2254 --
2255 hr_utility.set_location (l_proc,1);
2256 --
2257 g_smp_update := 'Y';
2258 --
2259 ins_ssp_temp_affected_rows_mat(p_maternity_id, p_deleting => FALSE);
2260 --
2261 hr_utility.set_location (l_proc,100);
2262 --
2263 end maternity_control;
2264 --------------------------------------------------------------------------------
2265 procedure medical_control (p_maternity_id in number) is
2266 --
2267 l_proc varchar2 (72) := g_package||'medical_control';
2268 --
2269 begin
2270 --
2271 hr_utility.set_location (l_proc,1);
2272 --
2273 if p_maternity_id is not null -- the medical is for a maternity
2274 then
2275 ins_ssp_temp_affected_rows_mat(p_maternity_id, p_deleting => FALSE);
2276 end if;
2277 --
2278 hr_utility.set_location (l_proc,100);
2279 --
2280 end medical_control;
2281 --
2282 --------------------------------------------------------------------------------
2283 procedure earnings_control (
2284 p_person_id in number,
2285 p_effective_date in date) is
2286 --
2287 cursor csr_maternity is
2288 --
2289 -- Find any maternity whose SMP figures rely on the earnings
2290 -- calculation.
2291 --
2292 select mat.maternity_id
2293 from ssp_maternities mat
2294 where mat.person_id = p_person_id
2295 and p_effective_date = decode(mat.leave_type,
2296 'AD',ssp_sap_pkg.MATCHING_WEEK_OF_ADOPTION(mat.matching_date),
2297 'PA',ssp_pad_pkg.MATCHING_WEEK_OF_ADOPTION(mat.matching_date),
2298 'PB',ssp_pab_pkg.QUALIFYING_WEEK(mat.due_date),
2299 ssp_smp_pkg.QUALIFYING_WEEK(mat.due_date))
2300 and exists (select 1
2301 from per_absence_attendances abs
2302 where abs.person_id = p_person_id
2303 and abs.maternity_id = mat.maternity_id);
2304 --
2305 l_maternity_id number := null;
2306 l_proc varchar2(72) := g_package||'earnings_control';
2307 --
2308 begin
2309 --
2310 hr_utility.set_location (l_proc,1);
2311 --
2312 open csr_maternity;
2313 fetch csr_maternity into l_maternity_id;
2314 --
2315 if csr_maternity%found
2316 then
2317 ins_ssp_temp_affected_rows_mat(l_maternity_id, p_deleting => FALSE);
2318 else
2319 hr_utility.trace(l_proc||' No maternities affected by change in earnings');
2320 end if;
2321 --
2322 close csr_maternity;
2323 --
2324 hr_utility.set_location (l_proc,100);
2325 --
2326 end earnings_control;
2327 --
2328 --------------------------------------------------------------------------------
2329 procedure person_control (
2330 p_person_id in number,
2331 p_date_of_death in date) is
2332 --
2333 cursor csr_maternity is
2334 --
2335 -- Get any maternity which may be affected by the death of the person,
2336 -- where the date of death falls within the MPP and leave is recorded.
2337 --
2338 select maternity.maternity_id
2339 from ssp_maternities MATERNITY,
2340 pay_element_types_f ELEMENT
2341 where maternity.person_id = p_person_id
2342 and element.legislation_code = 'GB'
2343 and element.element_name = c_SMP_element_name
2344 and maternity.due_date between element.effective_start_date
2345 and element.effective_end_date
2346 and p_date_of_death <= maternity.MPP_start_date
2347 + (element.element_information6 * 7)
2348 and EXISTS (
2349 select 1
2350 from per_absence_attendances ABSENCE
2351 where ABSENCE.maternity_id = MATERNITY.maternity_id
2352 );
2353 --
2354 l_maternity_id number := null;
2355 l_proc varchar2(72) := g_package||'person_control';
2356 --
2357 begin
2358 --
2359 hr_utility.set_location (l_proc,1);
2360 --
2361 open csr_maternity;
2362 fetch csr_maternity into l_maternity_id;
2363 --
2364 if csr_maternity%found
2365 then
2366 ins_ssp_temp_affected_rows_mat(l_maternity_id, p_deleting => FALSE);
2367 end if;
2368 --
2369 close csr_maternity;
2370 --
2371 ssp_smp_support_pkg.recalculate_ssp_and_smp(p_deleting => FALSE);
2372 --
2373 hr_utility.set_location (l_proc,100);
2374 --
2375 end person_control;
2376 --
2377 --------------------------------------------------------------------------------
2378 procedure stoppage_control (p_maternity_id in number) is
2379 --
2380 -- Because stoppages are the result of the SMP entitlement check, if the user
2381 -- modifies these stoppages, then there is no point in rerunning the check on
2382 -- entitlement. However, the alteration of stoppage information will almost
2383 -- certainly have an effect on the SMP payments and so we must regenerate them.
2384 --
2385 l_proc varchar2 (72) := g_package||'stoppage_control';
2386 --
2387 begin
2388 --
2389 hr_utility.set_location (l_proc,1);
2390 --
2391 if p_maternity_id is not null
2392 then
2393 ins_ssp_temp_affected_rows_mat(p_maternity_id, p_deleting => FALSE);
2394 end if;
2395 --
2396 hr_utility.set_location (l_proc,100);
2397 --
2398 end stoppage_control;
2399 --
2400 --------------------------------------------------------------------------------
2401 function get_max_SMP_date(p_maternity_id in number) return date is
2402 l_due_date date;
2403 l_mpp_date date;
2404 l_max_mpp number;
2405
2406 cursor get_person_details is
2407 select mpp_start_date, due_date
2408 from ssp_maternities
2409 where maternity_id = p_maternity_id;
2410
2411 cursor get_maximum_mpp is
2412 select to_number(element_information4)
2413 from pay_element_types_f
2414 where element_name = c_SMP_element_name
2415 and l_due_date between effective_start_date and effective_end_date;
2416 begin
2417 open get_person_details;
2418 fetch get_person_details into l_mpp_date, l_due_date;
2419 close get_person_details;
2420
2421 open get_maximum_mpp;
2422 fetch get_maximum_mpp into l_max_mpp;
2423 close get_maximum_mpp;
2424
2425 if l_mpp_date is not null then
2426 return trunc(l_mpp_date + (l_max_mpp * 7));
2427 else
2428 return l_due_date;
2429 end if;
2430 end;
2431 --------------------------------------------------------------------------------
2432 function get_max_SMP_date(p_maternity_id in number,
2433 p_due_date in date,
2434 p_mpp_date in date) return date is
2435 l_max_mpp number;
2436
2437 cursor get_maximum_mpp is
2438 select to_number(element_information4)
2439 from pay_element_types_f
2440 where element_name = c_SMP_element_name
2441 and p_due_date between effective_start_date and effective_end_date;
2442 begin
2443 open get_maximum_mpp;
2444 fetch get_maximum_mpp into l_max_mpp;
2445 close get_maximum_mpp;
2446
2447 if p_mpp_date is not null then
2448 return trunc(p_mpp_date + (l_max_mpp * 7));
2449 else
2450 return p_due_date;
2451 end if;
2452 end;
2453 --------------------------------------------------------------------------------
2454 end ssp_SMP_pkg;