1 package body per_fr_termination as
2 /* $Header: pefrterm.pkb 120.5 2011/08/16 05:59:44 rsahai ship $ */
3 --
4 g_package varchar2(30) := 'per_fr_termination';
5 g_person_id number;
6 g_validation number := 0;
7 --
8 /* --------------------------------------------------------------------
9 Local procedure to retrieve the Person ID from the period of service ID
10 -------------------------------------------------------------------- */
11 procedure initiate(p_period_of_service_id number) is
12 --
13 cursor c_get_pds is
14 select person_id
15 from per_periods_of_service
16 where period_of_service_id = p_period_of_service_id;
17 --
18 l_proc varchar2(72) := g_package || '.intiate';
19 begin
20 hr_utility.set_location(l_proc,10);
21 open c_get_pds;
22 fetch c_get_pds into g_person_id;
23 close c_get_pds;
24 end initiate;
25 --
26 /* --------------------------------------------------------------------
27 Local function to determine whether the Leaving Reason has a corresponding
28 value in FR_ENDING_REASON and CONTRACT_END_REASON
29 -------------------------------------------------------------------- */
30 function validate_leaving_reason
31 (p_lookup_type varchar2
32 ,p_lookup_code varchar2) return boolean is
33 --
34 l_dummy varchar2(1);
35 --
36 cursor c_get_lkp is
37 select null
38 from hr_lookups
39 where lookup_type = p_lookup_type
40 and lookup_code = p_lookup_code;
41 --
42 l_proc varchar2(72) := g_package || '.validate_leaving_reason';
43 begin
44 hr_utility.set_location(l_proc,10);
45 open c_get_lkp;
46 fetch c_get_lkp into l_dummy;
47 if c_get_lkp%found then
48 close c_get_lkp;
49 hr_utility.set_location(l_proc,20);
50 return TRUE;
51 else
52 close c_get_lkp;
53 hr_utility.set_location(l_proc,30);
54 return FALSE;
55 end if;
56 end validate_leaving_reason;
57 --
58 /* --------------------------------------------------------------------
59 Local procedure to perform validation of French specific columns.
60 -------------------------------------------------------------------- */
61 procedure validate
62 (p_actual_termination_date date
63 ,p_actual_termination_date_o date
64 ,p_notice_period_start_date date
65 ,p_notice_period_start_date_o date
66 ,p_notice_period_end_date date
67 ,p_notice_period_end_date_o date
68 ,p_last_day_worked varchar2
69 ,p_last_day_worked_o varchar2
70 ,p_final_process_date date -- for bug#5191942
71 ) is
72 --
73 l_exists varchar2(1);
74 --
75 cursor c_future_contracts is
76 select null
77 from per_contracts_f
78 where person_id = g_person_id
79 and effective_start_date > p_actual_termination_date + 1
80 and substrb(status,1,2) = 'A-';
81 --
82 l_nps_changed boolean :=
83 (p_notice_period_start_date is not null
84 and (p_notice_period_start_date_o is null
85 or (p_notice_period_start_date <> p_notice_period_start_date_o
86 and p_notice_period_start_date_o is not null
87 )));
88 l_npe_changed boolean :=
89 (p_notice_period_end_date is not null
90 and (p_notice_period_end_date_o is null
91 or (p_notice_period_end_date <> p_notice_period_end_date_o
92 and p_notice_period_end_date_o is not null
93 )));
94 l_lwd_changed boolean :=
95 (p_last_day_worked is not null
96 and (p_last_day_worked_o is null
97 or (p_last_day_worked <> p_last_day_worked_o
98 and p_last_day_worked_o is not null
99 )));
100 --
101 l_proc varchar2(72) := g_package || '.validate';
102 begin
103 hr_utility.set_location(l_proc,10);
104 --
105 -- Added for bug#5191942
106 -- if final process date is on or before actual termination date
107 -- then raise an error
108 hr_utility.set_location(l_proc, 10);
109 /*if p_final_process_date is not null
110 and p_actual_termination_date is not null then
111 if p_final_process_date < p_actual_termination_date
112 or p_final_process_date = p_actual_termination_date then
113 --
114 hr_utility.set_message(800, 'PER_75099_FINAL_CLOSE_ATD');
115 hr_utility.raise_error;
116 --
117 end if;
118 end if;*/
119 --
120 -- If either the NPS or NPE have changed and if either is NOT NULL then
121 -- validate that NPS is not after NPE
122 --
123 hr_utility.set_location(l_proc,20);
124 if l_nps_changed or l_npe_changed then
125 if p_notice_period_start_date > p_notice_period_end_date then
126 hr_utility.set_message(800,'PER_75013_NOTICE_PERIOD_DATES');
127 hr_utility.raise_error;
128 end if;
129 end if;
130 --
131 -- If NPS has changed or LWD has changed then ensure that
132 -- Notice period start is not later than LWD
133 --
134 hr_utility.set_location(l_proc,30);
135 if l_nps_changed or l_lwd_changed then
136 if p_notice_period_start_date > p_last_day_worked then
137 hr_utility.set_message(800,'PER_75014_NPS_LWD_DATES');
138 hr_utility.raise_error;
139 end if;
140 end if;
141 --
142 -- If NPE has changed or LWD has changed then ensure that
143 -- Notice period end is not earlier than LWD
144 --
145 hr_utility.set_location(l_proc,40);
146 if l_npe_changed or l_lwd_changed then
147 if p_notice_period_end_date < p_last_day_worked then
148 hr_utility.set_message(800,'PER_75015_NPE_LWD_DATES');
149 hr_utility.raise_error;
150 end if;
151 end if;
152 --
153 -- If NPE is not null then NPS must also be not null
154 --
155 hr_utility.set_location(l_proc,50);
156 if p_notice_period_start_date is null
157 and p_notice_period_end_date is not null then
158 hr_utility.set_message(800,'PER_75016_NPS_NPE_DATES');
159 hr_utility.raise_error;
160 end if;
161 --
162 -- If ATD is not null then it must be on or after NPS and
163 -- on or before NPE
164 --
165 hr_utility.set_location(l_proc,60);
166 if p_actual_termination_date is not null
167 and p_notice_period_start_date is not null
168 and p_notice_period_end_date is not null then
169 if p_notice_period_start_date > p_actual_termination_date
170 or p_notice_period_end_date < p_actual_termination_date then
171 hr_utility.set_message(800,'PER_75017_NPS_ATD_DATES');
172 hr_utility.raise_error;
173 end if;
174 end if;
175 --
176 -- If ATD is not null and LWD is not null then LWD must be on or
177 -- before ATD
178 --
179 hr_utility.set_location(l_proc,70);
180 if p_actual_termination_date is not null
181 and p_last_day_worked is not null then
182 if p_last_day_worked > p_actual_termination_date then
183 hr_utility.set_message(800,'PER_75018_LWD_ATD_DATES');
184 hr_utility.raise_error;
185 end if;
186 end if;
187 --
188 -- If ATD is not null then LWD must be entered
189 --
190 hr_utility.set_location(l_proc,80);
191
192 IF per_per_bus.g_global_transfer_in_process IS NULL --12394469
193 OR per_per_bus.g_global_transfer_in_process = false --12394469
194 THEN
195 if p_actual_termination_date is not null
196 and p_last_day_worked is null then
197 hr_utility.set_message(800,'PER_75019_LWD_ATD_NULL');
198 hr_utility.raise_error;
199 end if;
200 END IF; --12394469
201 --
202 hr_utility.set_location(l_proc,90);
203 end validate;
204 --
205 /* -------------------------------------------------------------------------
206 Local procedure to delete and create the element entry
207 FR_LAST_DAY_WORKED on LWD.
208 This is called from Terminate and Revers.
209 In the case of Reverse only the delete is performed.
210 ----------------------------------------------------------------------- */
211 procedure last_day_worked_entry
212 (p_last_day_worked date
213 ,p_actual_termination_date date) is
214 --
215 l_assignment_id number;
216 l_effective_date date;
217 l_element_type_id number;
218 l_element_link_id number;
219 l_element_entry_id number;
220 l_effective_start_date date;
221 l_effective_end_date date;
222 l_element_name pay_element_types_f.element_name%Type;
223 l_input_value_id Number;
224 --
225 cursor c_get_asg is
226 select assignment_id
227 from per_all_assignments_f
228 where person_id = g_person_id
229 and l_effective_date
230 between effective_start_date and effective_end_date
231 and primary_flag = 'Y';
232 --
233 cursor c_element is
234 select element_type_id, element_name
235 from pay_element_types_f
236 where l_effective_date
237 between effective_start_date and effective_end_date
238 and element_name IN ('FR_LAST_DAY_WORKED', 'FR_TERMINATION_INFORMATION')
239 and legislation_code = 'FR';
240 --
241
242 cursor c_input_value is
243 select input_value_id
244 from pay_input_values_f
245 where l_effective_date
246 between effective_start_date and effective_end_date
247 and legislation_code = 'FR'
248 and element_type_id = l_element_type_id
249 and name = 'Proration';
250
251 cursor c_entry is
252 select element_entry_id
253 from pay_element_entries_f ee
254 , pay_element_links_f l
255 where ee.assignment_id = l_assignment_id
256 and l.element_type_id = l_element_type_id
257 and l.element_link_id = ee.element_link_id
258 and p_actual_termination_date
259 between ee.effective_start_date and ee.effective_end_date
260 and p_actual_termination_date
261 between l.effective_start_date and l.effective_end_date;
262 --
263 l_proc varchar2(72) := g_package || '.last_day_worked_entry';
264 begin
265 hr_utility.set_location(l_proc,10);
266 --
267 -- Get the FR_LAST_DAY_WORKED element type ID as of Actual Termination Date
268 --
269 l_effective_date := p_actual_termination_date;
270 open c_element;
271 LOOP
272 fetch c_element into l_element_type_id, l_element_name;
273 EXIT WHEN c_element%NOTFOUND;
274 --
275 -- Get assignment ID of the primary assignment
276 --
277 if l_element_type_id is not null then
278 open c_get_asg;
279 fetch c_get_asg into l_assignment_id;
280 close c_get_asg;
281 --
282 -- Remove any existing element entry effective as of ATD
283 --
284 hr_utility.set_location(l_proc,20);
285 open c_entry;
286 fetch c_entry into l_element_entry_id;
287 if c_entry%found then
288 hr_entry_api.delete_element_entry
289 ('ZAP'
290 ,p_actual_termination_date
291 ,l_element_entry_id);
292 close c_entry;
293 else
294 close c_entry;
295 end if;
296 --
297 -- Now, if called from Terminate process, create new element entry
298 -- effective as of LWD
299 --
300 hr_utility.set_location(l_proc,30);
301 if p_last_day_worked is not null then
302 l_effective_date := p_last_day_worked;
303 open c_get_asg;
304 fetch c_get_asg into l_assignment_id;
305 close c_get_asg;
306 --
307 l_element_link_id :=
308 hr_entry_api.get_link(l_assignment_id
309 ,l_element_type_id
310 ,p_last_day_worked);
311 --
312 l_effective_start_date := p_last_day_worked;
313 --
314 if l_element_link_id is not null then
315 hr_entry_api.insert_element_entry
316 (p_effective_start_date => l_effective_start_date
317 ,p_effective_end_date => l_effective_end_date
318 ,p_element_entry_id => l_element_entry_id
319 ,p_assignment_id => l_assignment_id
320 ,p_element_link_id => l_element_link_id
321 ,p_creator_type => 'F'
322 ,p_entry_type => 'E');
323
324 --
325 -- Force DT change when ever entry is created on day after last day worked.
326 -- A dummy input value is changed so that proration will occur.
327 --
328 IF l_element_name = 'FR_LAST_DAY_WORKED' THEN
329
330 hr_utility.set_location('l_elemen_type_id'||l_element_type_id, 100);
331 hr_utility.set_location('l_assignment_id'||l_assignment_id, 100);
332 hr_utility.set_location('l_element_link_id'||l_element_link_id, 100);
333 Open c_input_value;
334 Fetch c_input_value into l_input_value_id;
335 Close c_input_value;
336 hr_utility.set_location('l_input_value_id'||l_input_value_id, 100);
337 hr_utility.set_location('LWD'|| p_last_day_worked, 100);
338 hr_utility.set_location('ATD'|| p_actual_termination_date, 100);
339 IF l_input_value_id IS NOT NULL THEN
340 hr_utility.set_location('DT Updating EE ', 100);
341 IF p_last_day_worked < p_actual_termination_date THEN
342 hr_utility.set_location('Updating EE with LWD date='|| (p_last_day_worked + 1), 100);
343 hr_entry_api.update_element_entry
344 (p_dt_update_mode => 'UPDATE'
345 ,p_session_date => p_last_day_worked + 1
346 ,p_element_entry_id => l_element_entry_id
347 ,p_comment_id => Null
348 ,p_input_value_id1 => l_input_value_id
349 ,p_entry_value1 => '2'
350 );
351 END IF;
352 -- Bug #2884200
353 hr_utility.set_location('Updating EE with ATD date='||(p_actual_termination_date + 1), 100);
354 -- Bug#6003309
355 hr_utility.set_location('Checking if ATD = FPD', 100);
356 IF p_actual_termination_date <> l_effective_end_date THEN
357 hr_entry_api.update_element_entry
358 (p_dt_update_mode => 'UPDATE'
359 ,p_session_date => p_actual_termination_date + 1
360 ,p_element_entry_id => l_element_entry_id
361 ,p_comment_id => Null
362 ,p_input_value_id1 => l_input_value_id
363 ,p_entry_value1 => '3'
364 );
365 END IF;
366 END IF; -- Input value id is not null
367 END IF; -- element is 'FR_LAST_DAY_WORKED'
368 end if;
369 end if; -- if p_last_day_worked is not null
370 end if; -- if l_element_type_id is not null
371 END LOOP;
372 CLOSE c_element;
373 --
374 hr_utility.set_location(l_proc,40);
375 --
376 end last_day_worked_entry;
377 --
378 /* -------------------------------------------------------------------------
379 local procedure to correct the assignment ending on ATD setting the
380 leaving reason to that on the period of service
381 ----------------------------------------------------------------------- */
382 procedure correct_assignment(p_period_of_service_id number
383 ,p_actual_termination_date date
384 ,p_leaving_reason varchar2) is
385 --
386 l_proc varchar2(72) := g_package||'.correct_assignment';
387 --
388 l_object_version_number number;
389 l_concatenated_segments varchar2(2000);
390 l_soft_coding_keyflex_id number;
391 l_comment_id number;
392 l_effective_start_date date;
393 l_effective_end_date date;
394 l_no_managers_warning boolean;
395 l_other_manager_warning boolean;
396 l_effective_date date;
397 l_update_mode varchar2(30);
398 l_exists varchar2(30);
399 l_contract_id number;
400 l_active_contracts number;
401 l_all_contracts number;
402 l_leaving_reason varchar2(30);
403 --
404 cursor c_get_asg is
405 select a.assignment_id
406 , a.primary_flag
407 , a.object_version_number
408 , a.soft_coding_keyflex_id
409 , scl.segment4
410 , scl.segment2
411 from per_all_assignments_f a
412 , hr_soft_coding_keyflex scl
413 , per_assignment_status_types ast
414 where a.period_of_service_id = p_period_of_service_id
415 and p_actual_termination_date = a.effective_end_date
416 and a.assignment_status_type_id = ast.assignment_status_type_id
417 and ast.per_system_status <> 'TERM_ASSIGN'
418 and a.soft_coding_keyflex_id = scl.soft_coding_keyflex_id (+);
419 --
420 begin
421 hr_utility.set_location(l_proc,10);
422 --
423 -- Process assignments ending on Actual Termination Date - set End Reason
424 --
425 if p_leaving_reason is null or
426 not validate_leaving_reason('FR_ENDING_REASON',p_leaving_reason) then
427 l_leaving_reason := null;
428 else
429 l_leaving_reason := p_leaving_reason;
430 end if;
431 --
432 for a in c_get_asg loop
433 hr_utility.trace(a.assignment_id);
434 hr_utility.trace(p_period_of_service_id);
435 hr_utility.trace(p_actual_termination_date);
436 l_object_version_number := a.object_version_number;
437 hr_assignment_api.update_emp_asg
438 (P_VALIDATE => FALSE
439 ,P_EFFECTIVE_DATE => p_actual_termination_date
440 ,P_DATETRACK_UPDATE_MODE => 'CORRECTION'
441 ,P_ASSIGNMENT_ID => a.assignment_id
442 ,P_OBJECT_VERSION_NUMBER => l_object_version_number
443 ,P_SEGMENT2 => a.segment2
444 ,P_SEGMENT4 => l_leaving_reason
445 ,P_CONCATENATED_SEGMENTS => l_concatenated_segments
446 ,P_SOFT_CODING_KEYFLEX_ID => l_soft_coding_keyflex_id
447 ,P_COMMENT_ID => l_comment_id
448 ,P_EFFECTIVE_START_DATE => l_effective_start_date
449 ,P_EFFECTIVE_END_DATE => l_effective_end_date
450 ,P_NO_MANAGERS_WARNING => l_no_managers_warning
451 ,P_OTHER_MANAGER_WARNING => l_other_manager_warning);
452 end loop;
453 --
454 hr_utility.set_location(l_proc,20);
455 end correct_assignment;
456 --
457
458 --
459 /* -------------------------------------------------------------------------
460 public procedure called from HR_EX_EMPLOYEE_BK1.ACTUAL_TERMINATION_EMP_A hook
461 to process assignments after they have been terminated to set leaving reason on
462 the record ending on ATD
463 ----------------------------------------------------------------------- */
464 procedure actual_termination(p_period_of_service_id number
465 ,p_actual_termination_date date) is
466 --
467 l_proc varchar2(72) := g_package||'.actual_termination';
468 l_leaving_reason varchar2(30);
469 --
470 cursor c_get_pds is
471 select leaving_reason
472 from per_periods_of_service
473 where period_of_service_id = p_period_of_service_id;
474 --
475 begin
476
477 --
478 /* Added for GSI Bug 5472781 */
479 IF NOT hr_utility.chk_product_install('Oracle Human Resources', 'FR') THEN
480 hr_utility.set_location('Leaving : '||l_proc , 10);
481 return;
482 END IF;
483 --
484 hr_utility.set_location(l_proc,10);
485 hr_utility.trace('Actually Terminating');
486 open c_get_pds;
487 fetch c_get_pds into l_leaving_reason;
488 close c_get_pds;
489 --
490 correct_assignment(p_period_of_service_id
491 ,p_actual_termination_date
492 ,l_leaving_reason);
493 hr_utility.set_location(l_proc,20);
494 end;
495 --
496 /* -------------------------------------------------------------------------
497 External procedure called from Termination API Row Handler After Update
498 hook call for France.
499 N.B. The Termination process as called from the form will call this procedure
500 3 times:
501 1. to update HR attributes
502 2. to maintain ATD
503 3. to maintain FPD
504
505 In 1. the ATD if changing is not available
506 In 2. the DDF segment changes are not available (both old and new values
507 are the same)
508 In 3. no hook processing is required.
509
510 Hence it is necessary to detect programatically then termination is happening
511 as opposed to just an update to the HR attributes (i.e DDF, Leaving Reason).
512 ----------------------------------------------------------------------- */
513 procedure termination
514 (p_period_of_service_id number
515 ,p_actual_termination_date date
516 ,p_leaving_reason varchar2
517 ,p_pds_information8 varchar2
518 ,p_pds_information9 varchar2
519 ,p_pds_information10 varchar2
520 ,p_actual_termination_date_o date
521 ,p_leaving_reason_o varchar2
522 ,p_pds_information8_o varchar2
523 ,p_pds_information9_o varchar2
524 ,p_pds_information10_o varchar2
525 ,p_final_process_date date -- for bug#5191942
526 ) is
527 --
528 l_proc varchar2(72) := g_package||'.termination';
529 --
530 l_notice_period_start_date date :=
531 fnd_date.canonical_to_date(p_pds_information8);
532 l_notice_period_end_date date :=
533 fnd_date.canonical_to_date(p_pds_information9);
534 l_last_day_worked date :=
535 fnd_date.canonical_to_date(p_pds_information10);
536 --
537 l_notice_period_start_date_o date :=
538 fnd_date.canonical_to_date(p_pds_information8_o);
539 l_notice_period_end_date_o date :=
540 fnd_date.canonical_to_date(p_pds_information9_o);
541 l_last_day_worked_o date :=
542 fnd_date.canonical_to_date(p_pds_information10_o);
543 --
544 l_object_version_number number;
545 l_concatenated_segments varchar2(2000);
546 l_soft_coding_keyflex_id number;
547 l_comment_id number;
548 l_effective_start_date date;
549 l_effective_end_date date;
550 l_no_managers_warning boolean;
551 l_other_manager_warning boolean;
552 l_effective_date date;
553 l_update_mode varchar2(30);
554 l_exists varchar2(30);
555 l_contract_id number;
556 l_active_contracts number;
557 l_all_contracts number;
558 l_leaving_reason varchar2(30);
559 --
560 cursor c_get_asg is
561 select a.assignment_id
562 , a.primary_flag
563 , a.object_version_number
564 , a.soft_coding_keyflex_id
565 , scl.segment4
566 , scl.segment2
567 from per_all_assignments_f a
568 , hr_soft_coding_keyflex scl
569 where a.period_of_service_id = p_period_of_service_id
570 and p_actual_termination_date = a.effective_end_date
571 and a.soft_coding_keyflex_id = scl.soft_coding_keyflex_id (+);
572 --
573 cursor c_get_ctr is
574 select contract_id
575 , person_id
576 , object_version_number
577 , reference
578 , type
579 , status
580 ,effective_start_date
581 ,effective_end_date
582 from per_contracts_f c
583 where person_id = g_person_id
584 and l_effective_date between effective_start_date and effective_end_date
585 and substrb(status,1,2) = 'A-';
586 --
587 l_atd_changed boolean :=
588 (p_actual_termination_date is not null and
589 p_actual_termination_date_o is null);
590 l_leaving_reason_changed boolean :=
591 (p_leaving_reason is not null and
592 p_leaving_reason_o is not null and
593 p_leaving_reason <> p_leaving_reason_o)
594 or
595 (p_leaving_reason is null and
596 p_leaving_reason_o is not null)
597 or
598 (p_leaving_reason_o is null and
599 p_leaving_reason is not null);
600 l_lwd_changed boolean :=
601 (l_last_day_worked is not null
602 and (l_last_day_worked_o is null
603 or (l_last_day_worked <> l_last_day_worked_o
604 and l_last_day_worked_o is not null
605 )));
606
607 begin
608 --
609 /* Added for GSI Bug 5472781 */
610 IF NOT hr_utility.chk_product_install('Oracle Human Resources', 'FR') THEN
611 hr_utility.set_location('Leaving : '||l_proc , 10);
612 return;
613 END IF;
614 --
615 hr_utility.set_location(l_proc,10);
616 --
617 -- Initiate Person ID package variable
618 --
619 initiate(p_period_of_service_id);
620 --
621 -- Perform validation of DDF segments
622 --
623 validate(p_actual_termination_date
624 ,p_actual_termination_date_o
625 ,l_notice_period_start_date
626 ,l_notice_period_start_date_o
627 ,l_notice_period_end_date
628 ,l_notice_period_end_date_o
629 ,l_last_day_worked
630 ,l_last_day_worked_o
631 ,p_final_process_date);
632 --
633 -- If Terminating (ATD not null and ATD_Old is null)
634 -- then change contract to change status to Inactive on day after
635 -- ATD
636 --
637 -- This needs to take into account future changes to contract
638 --
639 hr_utility.set_location(l_proc,20);
640 if l_atd_changed then
641 l_effective_date := p_actual_termination_date + 1;
642 for c in c_get_ctr loop
643 l_object_version_number := c.object_version_number;
644 --
645 if c.effective_start_date = l_effective_date then
646 l_update_mode := 'CORRECTION';
647 elsif c.effective_end_date < hr_general.end_of_time then
648 l_update_mode := 'UPDATE_CHANGE_INSERT';
649 else
650 l_update_mode := 'UPDATE';
651 end if;
652 --
653 -- Create or update contract on day after ATD
654 --
655 hr_utility.trace(c.contract_id||' '||l_update_mode);
656 hr_contract_api.update_contract
657 (P_VALIDATE => FALSE
658 ,P_CONTRACT_ID => c.contract_id
659 ,P_EFFECTIVE_START_DATE => l_effective_start_date
660 ,P_EFFECTIVE_END_DATE => l_effective_end_date
661 ,P_OBJECT_VERSION_NUMBER => l_object_version_number
662 ,P_PERSON_ID => c.person_id
663 ,P_REFERENCE => c.reference
664 ,P_TYPE => c.type
665 ,P_STATUS => 'T-TERMINATION'
666 ,P_EFFECTIVE_DATE => p_actual_termination_date+1
667 ,P_DATETRACK_MODE => l_update_mode);
668 --
669 end loop;
670 end if; -- if l_atd_changed
671 --
672 -- Now handle changes of Leaving Reason
673 --
674 -- If the Leaving Reason changes and ATD is not changing
675 -- the Leaving Reason is not null then default the Leaving Reason onto
676 -- the Assignment (SCL.SEGMENT4)
677 --
678 -- The record that will be updated will be the one that ends on ATD.
679 --
680 -- For this to be possible there must be the same lookup code as the Leaving
681 -- Reason in FR_ENDING_REASON
682 --
683 -- If such values do not exist then a NULL will be copied onto the SCL
684 --
685 -- N.B. This processing occurs only when ATD is set (i.e. a change of leaving
686 -- reason after termination )
687 -- It is therefore safe to assume that there will be Assignment
688 -- records ending on the ATD. These records will have a datetrack CORRECTION.
689 --
690 hr_utility.set_location(l_proc,30);
691 if p_actual_termination_date is not null and
692 (not l_atd_changed) and l_leaving_reason_changed then
693 --
694 correct_assignment(p_period_of_service_id
695 ,p_actual_termination_date
696 ,p_leaving_reason);
697 end if;
698 --
699 -- Process contracts ending on Actual Termination Date - set End Reason
700 --
701 -- If the Leaving Reason changes or ATD changes and
702 -- the Leaving Reason is not null then default the Leaving Reason onto
703 -- the Contract (END_REASON)
704 --
705 -- The record that will be updated will be the one that ends on ATD.
706 --
707 -- For this to be possible there must be the same lookup code as the Leaving
708 -- Reason in CONTRACT_END_REASON
709 --
710 -- If such values do not exist then a NULL will be copied onto the contract
711 --
712 -- N.B. This processing occurs only when ATD is set (i.e. a change of leaving
713 -- reason after termination )
714 -- It is therefore safe to assume that there will be Contract
715 -- records ending on the ATD. These records will have a datetrack CORRECTION.
716 --
717 if p_actual_termination_date is not null and
718 ((l_atd_changed and p_leaving_reason is not null) or
719 (l_leaving_reason_changed )) then
720 hr_utility.set_location(l_proc,40);
721 if p_leaving_reason is null or
722 not validate_leaving_reason('CONTRACT_END_REASON',p_leaving_reason) then
723 l_leaving_reason := null;
724 else
725 l_leaving_reason := p_leaving_reason;
726 end if;
727 --
728 l_effective_date := p_actual_termination_date;
729 for c in c_get_ctr loop
730 if p_actual_termination_date = c.effective_end_date then
731 hr_utility.trace(c.contract_id);
732 l_object_version_number := c.object_version_number;
733 hr_contract_api.update_contract
734 (P_VALIDATE => FALSE
735 ,P_CONTRACT_ID => c.contract_id
736 ,P_EFFECTIVE_START_DATE => l_effective_start_date
737 ,P_EFFECTIVE_END_DATE => l_effective_end_date
738 ,P_OBJECT_VERSION_NUMBER => l_object_version_number
739 ,P_PERSON_ID => c.person_id
740 ,P_REFERENCE => c.reference
741 ,P_TYPE => c.type
742 ,P_STATUS => c.status
743 ,P_END_REASON => l_leaving_reason
744 ,P_EFFECTIVE_DATE => p_actual_termination_date
745 ,P_DATETRACK_MODE => 'CORRECTION');
746 end if; -- p_actual_termination_date = c.effective_end_date
747 end loop;
748 end if; -- if p_actual_termination_date is not null
749 --
750 -- Now handle creation of Last Day Worked Element Entry
751 -- The element should be created if ATD is not null and LWD is not null
752 -- and either LWD has been updated or termination is taking place.
753 --
754 hr_utility.set_location(l_proc,50);
755 if p_actual_termination_date is not null
756 and l_last_day_worked is not null
757 and (l_lwd_changed or l_atd_changed) then
758 last_day_worked_entry(l_last_day_worked
759 ,p_actual_termination_date);
760 end if; -- if p_actual_termination_date is not null
761 --
762 hr_utility.set_location(l_proc,60);
763 end termination;
764 --
765 procedure reverse
766 (p_period_of_service_id number
767 ,p_actual_termination_date date
768 ,p_leaving_reason varchar2) is
769 --
770 l_proc varchar2(72) := g_package||'.reverse';
771 --
772 l_object_version_number number;
773 l_concatenated_segments varchar2(2000);
774 l_soft_coding_keyflex_id number;
775 l_comment_id number;
776 l_effective_start_date date;
777 l_effective_end_date date;
778 l_no_managers_warning boolean;
779 l_other_manager_warning boolean;
780 l_status varchar2(30);
781 --
782 l_effective_date date;
783 --
784 cursor c_get_asg is
785 select a.object_version_number
786 , a.assignment_id
787 , a.soft_coding_keyflex_id
788 , scl.segment2
789 , decode(effective_end_date
790 ,p_actual_termination_date,p_actual_termination_date
791 ,p_actual_termination_date+1) effective_date
792 from per_all_assignments_f a
793 , hr_soft_coding_keyflex scl
794 where period_of_service_id = p_period_of_service_id
795 and (effective_end_date = p_actual_termination_date
796 or effective_start_date = p_actual_termination_date+1
797 or (p_actual_termination_date >= effective_start_date and
798 effective_end_date = to_date('47121231','YYYYMMDD'))
799 )
800 and a.soft_coding_keyflex_id = scl.soft_coding_keyflex_id;
801 --
802 cursor c_get_ctr1 is
803 select contract_id
804 , person_id
805 , object_version_number
806 , reference
807 , type
808 , status
809 ,effective_start_date
810 ,effective_end_date
811 from per_contracts_f c
812 where person_id =
813 (select person_id
814 from per_periods_of_service
815 where period_of_service_id = p_period_of_service_id)
816 and p_actual_termination_date = effective_end_date;
817 --
818 cursor c_get_ctr2 (p_contract_id number
819 ,p_effective_date date) is
820 select contract_id
821 , person_id
822 , object_version_number
823 , reference
824 , type
825 , status
826 ,effective_start_date
827 ,effective_end_date
828 from per_contracts_f c
829 where contract_id = p_contract_id
830 and effective_start_date = p_effective_date;
831 --
832 ctr2 c_get_ctr2%rowtype;
833 --
834 begin
835 hr_utility.set_location(l_proc,10);
836 initiate(p_period_of_service_id);
837 --
838 -- On reversing a terination update the assignment record that ended
839 -- at ATD to set the ending reason to NULL
840 --
841 for a in c_get_asg loop
842 l_object_version_number := a.object_version_number;
843 hr_assignment_api.update_emp_asg
844 (P_VALIDATE => FALSE
845 ,P_EFFECTIVE_DATE => a.effective_date
846 ,P_DATETRACK_UPDATE_MODE => 'CORRECTION'
847 ,P_ASSIGNMENT_ID => a.assignment_id
848 ,P_OBJECT_VERSION_NUMBER => l_object_version_number
849 ,P_SEGMENT2 => a.segment2
850 ,P_SEGMENT4 => null
851 ,P_CONCATENATED_SEGMENTS => l_concatenated_segments
852 ,P_SOFT_CODING_KEYFLEX_ID => l_soft_coding_keyflex_id
853 ,P_COMMENT_ID => l_comment_id
854 ,P_EFFECTIVE_START_DATE => l_effective_start_date
855 ,P_EFFECTIVE_END_DATE => l_effective_end_date
856 ,P_NO_MANAGERS_WARNING => l_no_managers_warning
857 ,P_OTHER_MANAGER_WARNING => l_other_manager_warning);
858 end loop;
859 hr_utility.set_location(l_proc,20);
860 /*
861 --
862 -- On reversing a terination update the contract record that started
863 -- on the day after ATD, set status back to Active
864 --
865 l_effective_date := p_actual_termination_date + 1;
866 for c in c_get_ctr loop
867 l_object_version_number := c.object_version_number;
868 if c.effective_start_date = l_effective_date then
869 --
870 -- Find the status of the previous contract, if found set it on the
871 -- contract record starting on ATD+1
872 --
873 open c_get_status(c.contract_id,c.effective_start_date-1);
874 fetch c_get_status into l_status;
875 if c_get_status%found then
876 close c_get_status;
877 --
878 hr_contract_api.update_contract
879 (P_VALIDATE => FALSE
880 ,P_CONTRACT_ID => c.contract_id
881 ,P_EFFECTIVE_START_DATE => l_effective_start_date
882 ,P_EFFECTIVE_END_DATE => l_effective_end_date
883 ,P_OBJECT_VERSION_NUMBER => l_object_version_number
884 ,P_PERSON_ID => c.person_id
885 ,P_REFERENCE => c.reference
886 ,P_TYPE => c.type
887 ,P_STATUS => l_status
888 ,P_END_REASON => null
889 ,P_EFFECTIVE_DATE => l_effective_date
890 ,P_DATETRACK_MODE => 'CORRECTION');
891 else
892 close c_get_status;
893 end if;
894 end if; -- if c.effective_start_date = l_effective_date
895 end loop;
896 hr_utility.set_location(l_proc,30);
897 */
898 --
899 --
900 -- On reversing a terination update the contract record that ended
901 -- at ATD to set the ending reason to NULL
902 --
903 for c in c_get_ctr1 loop
904 l_object_version_number := c.object_version_number;
905 hr_contract_api.update_contract
906 (P_VALIDATE => FALSE
907 ,P_CONTRACT_ID => c.contract_id
908 ,P_EFFECTIVE_START_DATE => l_effective_start_date
909 ,P_EFFECTIVE_END_DATE => l_effective_end_date
910 ,P_OBJECT_VERSION_NUMBER => l_object_version_number
911 ,P_PERSON_ID => c.person_id
912 ,P_REFERENCE => c.reference
913 ,P_TYPE => c.type
914 ,P_STATUS => c.status
915 ,P_END_REASON => null
916 ,P_EFFECTIVE_DATE => p_actual_termination_date
917 ,P_DATETRACK_MODE => 'CORRECTION');
918 --
919 l_status := c.status;
920 --
921 --
922 -- On reversing a terination update the contract record that started
923 -- on the day after ATD, set status back to Active
924 --
925 open c_get_ctr2(c.contract_id,p_actual_termination_date+1);
926 fetch c_get_ctr2 into ctr2;
927 if c_get_ctr2%found then
928 close c_get_ctr2;
929 --
930 l_object_version_number := ctr2.object_version_number;
931 hr_contract_api.update_contract
932 (P_VALIDATE => FALSE
933 ,P_CONTRACT_ID => ctr2.contract_id
934 ,P_EFFECTIVE_START_DATE => l_effective_start_date
935 ,P_EFFECTIVE_END_DATE => l_effective_end_date
936 ,P_OBJECT_VERSION_NUMBER => l_object_version_number
937 ,P_PERSON_ID => ctr2.person_id
938 ,P_REFERENCE => ctr2.reference
939 ,P_TYPE => ctr2.type
940 ,P_STATUS => c.status
941 ,P_END_REASON => null
942 ,P_EFFECTIVE_DATE => p_actual_termination_date+1
943 ,P_DATETRACK_MODE => 'CORRECTION');
944 else
945 close c_get_ctr2;
946 end if;
947 end loop;
948 hr_utility.set_location(l_proc,40);
949 --
950 -- Delete the FR_LAST_DAY_WORKED element entry that exists on ATD
951 --
952 last_day_worked_entry(null
953 ,p_actual_termination_date);
954
955 hr_utility.set_location(l_proc,50);
956 end reverse;
957 --
958
959 FUNCTION npil_earnings_base_12months (p_assignment_id in Number,
960 p_last_day_worked in Date) Return Number
961 IS
962 l_bal_date_to Date;
963 l_bal_date_from Date;
964 l_rolling_balance Number;
965 BEGIN
966 -- Get the last day of the month prior to last working day
967 l_bal_date_to := LAST_DAY(ADD_MONTHS(p_last_day_worked,-1)) ;
968 -- function calculates over last 12 months
969 -- 1st day of 12 calendar months prior to above date
970 l_bal_date_from := TRUNC(ADD_MONTHS(l_bal_date_to+1,-12), 'MONTH');
971 -- Get rolling balances
972 l_rolling_balance := PAY_FR_GENERAL.FR_ROLLING_BALANCE
973 (p_assignment_id,
974 'FR_NOTICE_PERIOD_IN_LIEU_EARNINGS_BASE',
975 l_bal_date_from,
976 l_bal_date_to);
977
978 RETURN l_rolling_balance;
979 END;
980
981 end per_fr_termination;