1 package body PAY_ASG_LINK_USAGES_PKG as
2 /* $Header: pyalu.pkb 120.2.12000000.4 2007/03/05 12:22:25 swinton ship $ */
3 --------------------------------------------------------------------------------
4 --
5 -- Declare global variables
6 --
7
8 type t_num_tab is table of number
9 index by binary_integer;
10 type t_date_tab is table of date
11 index by binary_integer;
12 --
13 type t_asg_grp_rec is record
14 (people_group_id number
15 ,effective_start_date date
16 ,effective_end_date date
17 );
18 type t_asg_grp_hist_tab is table of t_asg_grp_rec
19 index by binary_integer;
20 --
21 -- Assignment cache for ALU.
22 --
23 g_alu_assignment_id number; -- Assignment ID
24 g_alu_asg_hist t_asg_grp_hist_tab; -- Asg people group history
25 g_alu_link_pg_id number; -- Link People Group ID
26 g_alu_asg_pg_hist t_asg_grp_hist_tab; -- Asg eligibility history
27 --
28 g_package constant varchar2 (32) := 'pay_asg_link_usages_pkg.';
29
30 --------------------------------------------------------------------------------
31 --
32 procedure INSERT_ALU (
33 --
34 --******************************************************************************
35 --* Inserts Assignment Link Usages for a new element link. *
36 --******************************************************************************
37 --
38 p_business_group_id number,
39 p_people_group_id number,
40 p_element_link_id number,
41 p_effective_start_date date,
42 p_effective_end_date date) is
43 --
44 v_previous_assignment_id number;
45 v_previous_start_date date;
46 v_previous_end_date date;
47 v_termination_date date;
48 v_unwanted_out_parameter date;
49 v_rows_were_found boolean;
50 --
51 -- Table variables for bulk.
52 --
53 type t_num_tab is table of number index by binary_integer;
54 type t_date_tab is table of date index by binary_integer;
55
56 v_asg_id_tab t_num_tab;
57 v_start_date_tab t_date_tab;
58 v_end_date_tab t_date_tab;
59
60 --
61 -- Cursor to fetch the info for the re1uired people group
62 --
63 cursor link_people_group is
64 select id_flex_num,
65 segment1, segment2, segment3, segment4, segment5,
66 segment6, segment7, segment8, segment9, segment10,
67 segment11, segment12, segment13, segment14, segment15,
68 segment16, segment17, segment18, segment19, segment20,
69 segment21, segment22, segment23, segment24, segment25,
70 segment26, segment27, segment28, segment29, segment30
71 from pay_people_groups link_group
72 where link_group.people_group_id = p_people_group_id;
73 --
74 type segment_table is table of varchar2(60)
75 index by binary_integer;
76 segment segment_table;
77 i number;
78 sql_curs number;
79 rows_processed integer;
80 statem varchar2(8000);
81 row_count number := 0;
82 --
83 l_assignment_id per_assignments_f.assignment_id%type;
84 l_effective_start_date per_assignments_f.effective_start_date%type;
85 l_effective_end_date per_assignments_f.effective_end_date%type;
86 --
87 -- Bug 5408395.
88 -- This sub procedure was renamed from create_alu to set_alu as this
89 -- now only sets up the ALU data and ALUs are uploaded by bulk in
90 -- upload_alus().
91 --
92 --procedure CREATE_ALU is
93 procedure set_ALU is
94 --
95 l_alu_start date;
96 l_alu_end date;
97 l_idx number;
98 begin
99 l_alu_start := greatest(p_effective_start_date, v_previous_start_date);
100 --
101 -- Get the final process date for the assignment if there is one NB.
102 -- it will return the end of time if there is not one. This is so
103 -- that the subsequent comparison will ignore the date.
104 --
105 -- Bug 5202396.
106 -- The check for termination rule caused a significant performance
107 -- issue. Since ALU is only a part of the link eligibility rules,
108 -- we can determine the end date with the link and the assignment.
109 --
110 /*****************
111 hr_entry.entry_asg_pay_link_dates(v_previous_assignment_id,
112 p_element_link_id,
113 l_alu_start,
114 v_termination_date,
115 v_unwanted_out_parameter,
116 v_unwanted_out_parameter,
117 v_unwanted_out_parameter,
118 v_unwanted_out_parameter,
119 false);
120 --
121 l_alu_end := least(p_effective_end_date,
122 v_previous_end_date,
123 v_termination_date);
124 *****************/
125 --
126 l_alu_end := least(p_effective_end_date,
127 v_previous_end_date);
128
129 --
130 if l_alu_end >= l_alu_start then
131 hr_utility.trace('ALU : ' || l_alu_start || ' ' || l_alu_end);
132
133 l_idx := v_asg_id_tab.count+1;
134 --
135 -- Set the ALU data to table variables.
136 --
137 v_asg_id_tab(l_idx) := v_previous_assignment_id;
138 v_start_date_tab(l_idx) := l_alu_start;
139 v_end_date_tab(l_idx) := l_alu_end;
140
141 end if;
142 --
143 end set_ALU;
144 --end create_ALU;
145 --
146 --
147 -- Sub procedure to upload alus by bulk.
148 --
149 procedure upload_alus
150 is
151 l_count number;
152 begin
153 l_count := v_asg_id_tab.count;
154
155 if l_count > 0 then
156
157 forall i in 1..l_count
158 insert into pay_assignment_link_usages_f
159 (assignment_link_usage_id
160 ,effective_start_date
161 ,effective_end_date
162 ,element_link_id
163 ,assignment_id)
164 values
165 (pay_assignment_link_usages_s.nextval
166 ,v_start_date_tab(i)
167 ,v_end_date_tab(i)
168 ,p_element_link_id
169 ,v_asg_id_tab(i)
170 );
171 --
172 -- Reset the table variables.
173 --
174 v_asg_id_tab.delete;
175 v_start_date_tab.delete;
176 v_end_date_tab.delete;
177
178 end if;
179
180 end upload_alus;
181 --
182 --
183 begin
184 --
185 -- Cycle through qualifying assignments. Create an ALU when the last end date
186 -- of a continuous set of date-effective rows for an assignment is found.
187 -- eg:
188 --
189 -- Assignment ID 1 +_____________+_______+_______________+___________+
190 -- Match found? YES YES NO YES
191 --
192 -- ALU ID 1 +_____________________+
193 -- ALU ID 2 +___________+
194 --
195 for lpg in link_people_group loop
196 --
197 segment(1) := lpg.segment1;
198 segment(2) := lpg.segment2;
199 segment(3) := lpg.segment3;
200 segment(4) := lpg.segment4;
201 segment(5) := lpg.segment5;
202 segment(6) := lpg.segment6;
203 segment(7) := lpg.segment7;
204 segment(8) := lpg.segment8;
205 segment(9) := lpg.segment9;
206 segment(10) := lpg.segment10;
207 segment(11) := lpg.segment11;
208 segment(12) := lpg.segment12;
209 segment(13) := lpg.segment13;
210 segment(14) := lpg.segment14;
211 segment(15) := lpg.segment15;
212 segment(16) := lpg.segment16;
213 segment(17) := lpg.segment17;
214 segment(18) := lpg.segment18;
215 segment(19) := lpg.segment19;
216 segment(20) := lpg.segment20;
217 segment(21) := lpg.segment21;
218 segment(22) := lpg.segment22;
219 segment(23) := lpg.segment23;
220 segment(24) := lpg.segment24;
221 segment(25) := lpg.segment25;
222 segment(26) := lpg.segment26;
223 segment(27) := lpg.segment27;
224 segment(28) := lpg.segment28;
225 segment(29) := lpg.segment29;
226 segment(30) := lpg.segment30;
227 --
228 statem := '
229 select assignment.assignment_id,
230 assignment.effective_start_date,
231 assignment.effective_end_date
232 from per_all_assignments_f ASSIGNMENT,
233 pay_people_groups ASSIGNMENT_GROUP
234 where assignment.assignment_type not in (''A'',''O'')
235 and assignment.business_group_id + 0 = :p_business_group_id
236 and assignment.effective_start_date <= :p_effective_end_date
237 and assignment.effective_end_date >= :p_effective_start_date
238 and assignment_group.id_flex_num = :p_id_flex_num
239 and assignment_group.people_group_id = assignment.people_group_id';
240 --
241 for i in 1..30 loop
242 if segment(i) is not null then
243 statem := statem || ' and assignment_group.segment'||i||' = :p_segment'||i;
244 end if;
245 end loop;
246 --
247 statem := statem || ' order by assignment_id, effective_start_date';
248 statem := statem || ' for update';
249 --
250 --
251 sql_curs := dbms_sql.open_cursor;
252 --
253 dbms_sql.parse(sql_curs,
254 statem,
255 dbms_sql.v7);
256 --
257 dbms_sql.bind_variable(sql_curs, 'p_business_group_id', p_business_group_id);
258 dbms_sql.bind_variable(sql_curs, 'p_effective_start_date', p_effective_start_date);
259 dbms_sql.bind_variable(sql_curs, 'p_effective_end_date', p_effective_end_date);
260 dbms_sql.bind_variable(sql_curs, 'p_id_flex_num', lpg.id_flex_num);
261 --
262 for i in 1..30 loop
263 if segment(i) is not null then
264 dbms_sql.bind_variable(sql_curs, 'p_segment'||i, segment(i));
265 end if;
266 end loop;
267 --
268 dbms_sql.define_column(sql_curs,1,l_assignment_id);
269 dbms_sql.define_column(sql_curs,2,l_effective_start_date);
270 dbms_sql.define_column(sql_curs,3,l_effective_end_date);
271 --
272 rows_processed := dbms_sql.execute(sql_curs);
273 --
274 loop
275 if dbms_sql.fetch_rows(sql_curs) > 0 then
276 --
277 row_count := row_count + 1;
278 --
279 dbms_sql.column_value(sql_curs,1,l_assignment_id);
280 dbms_sql.column_value(sql_curs,2,l_effective_start_date);
281 dbms_sql.column_value(sql_curs,3,l_effective_end_date);
282 --
283 hr_utility.trace('l_assignment_id '||l_assignment_id);
284 hr_utility.trace('l_effective_start_date '||l_effective_start_date);
285 hr_utility.trace('l_effective_end_date '||l_effective_end_date);
286 --
287 if row_count = 1 then -- Skip first row but set ID
288 --
289 v_rows_were_found := TRUE;
290 v_previous_assignment_id := l_assignment_id;
291 v_previous_start_date := l_effective_start_date;
292 v_previous_end_date := l_effective_end_date;
293 --
294 else
295 --
296 -- Check for last record or a new asignment ie. either a new
297 -- assignment_id or the same assignment_id but not contiguous records
298 --
299 if (l_assignment_id <> v_previous_assignment_id
300 or l_effective_start_date -1 <> v_previous_end_date) then
301 --
302 -- Setup the ALU data in the table variables.
303 --
304 set_ALU;
305 --create_ALU;
306 --
307 -- Upload ALUs by a reasonable amount.
308 --
309 if v_asg_id_tab.count = 200 then
310 --
311 upload_alus;
312
313 end if;
314 --
315 -- Bugfix 2364196
316 -- Always increment the v_previous_start_date when a new
317 -- assignment is detected.
318 --
319 v_previous_start_date := l_effective_start_date;
320 --
321 end if;
322 --
323 v_previous_end_date := l_effective_end_date;
324 --
325 end if;
326 --
327 v_previous_assignment_id := l_assignment_id;
328 --
329 else
330 exit;
331 end if;
332 end loop;
333 --
334 dbms_sql.close_cursor(sql_curs);
335 --
336 end loop;
337 --
338 -- Handle the last row in the cursor (loop exits before checking it)
339 --
340 if v_rows_were_found then
341 --
342 --create_ALU;
343 set_alu;
344 --
345 end if;
346 --
347 -- Upload all of the remaining ALUs.
348 --
349 upload_alus;
350 --
351 end insert_alu;
352 --------------------------------------------------------------------------------
353 procedure CASCADE_LINK_DELETION (
354 --
355 --******************************************************************************
356 --* Deletes ALUs for a deleted link. *
357 --******************************************************************************
358 --
359 p_element_link_id number,
360 p_business_group_id number,
361 p_people_group_id number,
362 p_delete_mode varchar2,
363 p_effective_start_date date,
364 p_effective_end_date date,
365 p_validation_start_date date,
366 p_validation_end_date date ) is
367 --
368 v_session_date date;
369 --
370 begin
371 --
372 if p_delete_mode = 'DELETE' then
373 --
374 v_session_date := p_validation_start_date -1;
375 --
376 delete
377 from pay_assignment_link_usages_f
378 where element_link_id = p_element_link_id
379 and effective_start_date >= p_validation_start_date;
380 --
381 if p_delete_mode = 'DELETE' then
382 --
383 update pay_assignment_link_usages_f
384 set effective_end_date = v_session_date
385 where element_link_id = p_element_link_id
386 and v_session_date between effective_start_date
387 and effective_end_date;
388 --
389 end if;
390 --
391 elsif p_delete_mode in ('ZAP', 'DELETE_NEXT_CHANGE') then
392 --
393 delete
394 from pay_assignment_link_usages_f
395 where element_link_id = p_element_link_id;
396 --
397 if p_delete_mode = 'DELETE_NEXT_CHANGE' then
398 --
399 insert_ALU (
400 p_business_group_id,
401 p_people_group_id,
402 p_element_link_id,
403 p_effective_start_date,
404 p_effective_end_date );
405 --
406 end if;
407 --
408 end if;
409 --
410 end cascade_link_deletion;
411 --------------------------------------------------------------------------------
412 --
413 function pg_eligible
414 --
415 --******************************************************************************
416 --* Returns Y if the assignment people group is eligible for *
417 --* the link people group. Otherwise returns N. *
418 --******************************************************************************
419 --
420 (p_link_people_group_id in number
421 ,p_asg_people_group_id in number
422 ) return varchar2
423 is
424 --
425 l_dummy number;
426 l_eligible varchar2(1);
427 --
428 cursor csr_pg
429 is
433 where asg_pg.people_group_id = p_asg_people_group_id
430 select 1
431 from pay_people_groups el_pg,
432 pay_people_groups asg_pg
434 and el_pg.people_group_id = p_link_people_group_id
435 and el_pg.id_flex_num = asg_pg.id_flex_num
436 and (el_pg.segment1 is null or el_pg.segment1 = asg_pg.segment1)
437 and (el_pg.segment2 is null or el_pg.segment2 = asg_pg.segment2)
438 and (el_pg.segment3 is null or el_pg.segment3 = asg_pg.segment3)
439 and (el_pg.segment4 is null or el_pg.segment4 = asg_pg.segment4)
440 and (el_pg.segment5 is null or el_pg.segment5 = asg_pg.segment5)
441 and (el_pg.segment6 is null or el_pg.segment6 = asg_pg.segment6)
442 and (el_pg.segment7 is null or el_pg.segment7 = asg_pg.segment7)
443 and (el_pg.segment8 is null or el_pg.segment8 = asg_pg.segment8)
444 and (el_pg.segment9 is null or el_pg.segment9 = asg_pg.segment9)
445 and (el_pg.segment10 is null or el_pg.segment10 = asg_pg.segment10)
446 and (el_pg.segment11 is null or el_pg.segment11 = asg_pg.segment11)
447 and (el_pg.segment12 is null or el_pg.segment12 = asg_pg.segment12)
448 and (el_pg.segment13 is null or el_pg.segment13 = asg_pg.segment13)
449 and (el_pg.segment14 is null or el_pg.segment14 = asg_pg.segment14)
450 and (el_pg.segment15 is null or el_pg.segment15 = asg_pg.segment15)
451 and (el_pg.segment16 is null or el_pg.segment16 = asg_pg.segment16)
452 and (el_pg.segment17 is null or el_pg.segment17 = asg_pg.segment17)
453 and (el_pg.segment18 is null or el_pg.segment18 = asg_pg.segment18)
454 and (el_pg.segment19 is null or el_pg.segment19 = asg_pg.segment19)
455 and (el_pg.segment20 is null or el_pg.segment20 = asg_pg.segment20)
456 and (el_pg.segment21 is null or el_pg.segment21 = asg_pg.segment21)
457 and (el_pg.segment22 is null or el_pg.segment22 = asg_pg.segment22)
458 and (el_pg.segment23 is null or el_pg.segment23 = asg_pg.segment23)
459 and (el_pg.segment24 is null or el_pg.segment24 = asg_pg.segment24)
460 and (el_pg.segment25 is null or el_pg.segment25 = asg_pg.segment25)
461 and (el_pg.segment26 is null or el_pg.segment26 = asg_pg.segment26)
462 and (el_pg.segment27 is null or el_pg.segment27 = asg_pg.segment27)
463 and (el_pg.segment28 is null or el_pg.segment28 = asg_pg.segment28)
464 and (el_pg.segment29 is null or el_pg.segment29 = asg_pg.segment29)
465 and (el_pg.segment30 is null or el_pg.segment30 = asg_pg.segment30)
466 ;
467 begin
468 if p_link_people_group_id = p_asg_people_group_id then
469 return 'Y';
470 end if;
471
472 open csr_pg;
473 fetch csr_pg into l_dummy;
474 if csr_pg%found then
475 l_eligible := 'Y';
476 else
477 l_eligible := 'N';
478 end if;
479 close csr_pg;
480
481 return l_eligible;
482 end pg_eligible;
483 --
484 --------------------------------------------------------------------------------
485 --
486 procedure deinit_alu_asg
487 --
488 --******************************************************************************
489 --* Clears the ALU assignment cache. *
490 --******************************************************************************
491 --
492 is
493 begin
494 g_alu_assignment_id := null;
495 g_alu_asg_hist.delete;
496 g_alu_link_pg_id := null;
497 g_alu_asg_pg_hist.delete;
498 end deinit_alu_asg;
499 --
500 --------------------------------------------------------------------------------
501 --
502 procedure init_alu_asg(p_assignment_id in number)
503 --
504 --******************************************************************************
505 --* initialises the ALU assignment cache. *
506 --******************************************************************************
507 is
508 --
509 l_idx number:=0;
510 l_prev_asg t_asg_grp_rec;
511 l_pg_found boolean;
512 --
513 cursor csr_asg_hist
514 is
515 select
516 people_group_id
517 ,effective_start_date
518 ,effective_end_date
519 from per_all_assignments_f
520 where assignment_id = p_assignment_id
521 and assignment_type not in ('A','O')
522 and people_group_id is not null
523 order by effective_start_date;
524 --
525 begin
526 --
527 -- Clear existing cache.
528 --
529 deinit_alu_asg;
530 --
531 g_alu_assignment_id := p_assignment_id;
532 --
533 -- Create the distinct people group histry records for this assignment.
534 --
535 -- Assignment history
536 -- PG1 PG1 PG2 PG2 PG3
537 -- |------->|------->|------->|------->|------->
538 --
539 -- People group history
540 -- PG1 PG2 PG3
541 -- |---------------->|---------------->|------->
542 --
543 for l_asg in csr_asg_hist loop
544 --
545 if l_prev_asg.people_group_id = l_asg.people_group_id
546 and l_prev_asg.effective_end_date+1 = l_asg.effective_start_date then
547 --
548 -- Extend the previous record
549 --
550 g_alu_asg_hist(l_idx).effective_end_date := l_asg.effective_end_date;
551 else
552 l_idx := l_idx +1;
553 g_alu_asg_hist(l_idx) := l_asg;
554 --
555 end if;
556 --
557 l_prev_asg := l_asg;
558 --
559 end loop;
560 --
561 end init_alu_asg;
562 --
566 --
563 --------------------------------------------------------------------------------
564 --
565 procedure init_alu_asg_pg
567 --******************************************************************************
568 --* initialises the ALU assignment cache for the specified *
569 --* link people group. *
570 --******************************************************************************
571 --
572 (p_assignment_id in number
573 ,p_link_people_group_id in number)
574 is
575 l_idx number:= 0;
576 l_prev_idx number;
577 begin
578 if g_alu_assignment_id = p_assignment_id then
579 --
580 -- Assignment level cache already exists.
581 --
582 null;
583 else
584 init_alu_asg(p_assignment_id);
585 end if;
586 --
587 g_alu_link_pg_id := p_link_people_group_id;
588 g_alu_asg_pg_hist.delete;
589 --
590 -- Create the eligible assignment histry records for the
591 -- the specified people group.
592 --
593 -- Eligibility for the link people group
594 -- PG1 PG2 PG3 PG4
595 -- ASG |------->|------->|------->|------->
596 -- Yes Yes No Yes
597 --
598 -- Eligible assignment date range
599 -- ASG |----------------> |------->
600 --
601 for i in 1..g_alu_asg_hist.count loop
602
603 if pg_eligible
604 (p_link_people_group_id
605 ,g_alu_asg_hist(i).people_group_id
606 ) = 'Y' then
607 --
608 l_prev_idx := l_idx;
609 --
610 if l_idx = 0 then
611 l_idx := l_idx+1;
612 elsif g_alu_asg_hist(i).effective_start_date
613 = g_alu_asg_pg_hist(l_idx).effective_end_date+1 then
614 --
615 -- Extend the duration
616 --
617 g_alu_asg_pg_hist(l_idx).effective_end_date
618 := g_alu_asg_hist(i).effective_end_date;
619 else
620 l_idx := l_idx+1;
621 end if;
622 --
623 if l_idx > l_prev_idx then
624 --
625 -- Create a new date range.
626 --
627 g_alu_asg_pg_hist(l_idx).effective_start_date
628 := g_alu_asg_hist(i).effective_start_date;
629 g_alu_asg_pg_hist(l_idx).effective_end_date
630 := g_alu_asg_hist(i).effective_end_date;
631 end if;
632 end if;
633 end loop;
634 end init_alu_asg_pg;
635 --
636 --------------------------------------------------------------------------------
637 --
638 procedure chk_pg_eligibility
639 --
640 --******************************************************************************
641 --* checks the eligibility of the people group criteria. *
642 --* If the assignment is eligible for the link people group, *
643 --* p_eligible_pg_exists will be set to TRUE and the eligibility history *
644 --* records will be cached for further processing. *
645 --******************************************************************************
646 --
647 (p_assignment_id in number
648 ,p_link_people_group_id in number
649 ,p_eligible_pg_exists out nocopy boolean
650 )
651 is
652 begin
653 if g_alu_assignment_id = p_assignment_id then
654 --
655 -- Asg cache already exists.
656 --
657 if g_alu_link_pg_id = p_link_people_group_id then
658 --
659 -- People group cache also exists.
660 --
661 null;
662 else
663 init_alu_asg_pg(p_assignment_id, p_link_people_group_id);
664 end if;
665 else
666 --
667 -- Initialise ALU assignment and link cache.
668 --
669 init_alu_asg(p_assignment_id);
670 init_alu_asg_pg(p_assignment_id, p_link_people_group_id);
671 end if;
672 --
676 --
673 p_eligible_pg_exists := (g_alu_asg_pg_hist.count > 0);
674 --
675 end chk_pg_eligibility;
677 --------------------------------------------------------------------------------
678 --
679 procedure create_alu_asg_pg
680 --
681 --******************************************************************************
682 --* This procedure creates ALU's of the assignment for a particular link *
683 --* people group. *
684 --******************************************************************************
685 --
686 (p_assignment_id in number
687 ,p_link_people_group_id in number
688 ,p_link_id_tab in t_num_tab
689 ,p_link_start_date_tab in t_date_tab
690 ,p_link_end_date_tab in t_date_tab
691 )
692 is
693 --
694 l_idx number:= 0;
695 l_prev_idx number:= 0;
696 --
697 -- ALU table variables
698 --
699 l_alu_start_date_tab t_date_tab;
700 l_alu_end_date_tab t_date_tab;
701 l_alu_link_id_tab t_num_tab;
702 --
703 l_alu_start_date date;
704 l_alu_end_date date;
705 l_asg_start_date date;
706 l_asg_end_date date;
707 l_link_start_date date;
708 l_link_end_date date;
709 l_link_id number;
710 --
711 l_alu_idx number:= 0;
712 l_eligible_pg_exists boolean;
713 l_dummy number;
714 l_alu_exists boolean;
715 l_asg_locked boolean;
716 --
717 cursor csr_alu_exists
718 (p_element_link_id in number)
719 is
720 select 1 from pay_assignment_link_usages_f
721 where assignment_id = p_assignment_id
722 and element_link_id = p_element_link_id;
723 --
724 l_proc varchar2(72) := g_package||'create_alu_asg_pg';
725 --
726 -- sub procedure to lock assignment.
727 --
728 procedure lock_asg
729 (p_asg_id in number
730 ,p_start_date in date
731 ,p_end_date in date)
732 is
733 --
734 cursor csr_lock_asg
735 is
736 select 1
737 from per_all_assignments_f
738 where assignment_id = p_asg_id
739 and effective_start_date <= p_end_date
740 and effective_end_date >= p_start_date
741 for update nowait
742 ;
743 --
744 l_num_tab t_num_tab;
745 --
746 begin
747 open csr_lock_asg;
748 fetch csr_lock_asg bulk collect into l_num_tab;
749 close csr_lock_asg;
750 exception
751 when hr_api.object_locked then
752 --
753 -- Failed to lock the assignment.
754 --
755 hr_utility.set_message(801, 'HR_7165_OBJECT_LOCKED');
756 hr_utility.set_message_token('TABLE_NAME', 'per_all_assignments_f');
757 hr_utility.raise_error;
758 end lock_asg;
759 --
760 begin
761
762 hr_utility.set_location('Entering: '||l_proc, 5);
763 --
764 -- Check the eligibility of the people group and
765 -- also establish the necessary cache.
766 --
767 chk_pg_eligibility
768 (p_assignment_id
769 ,p_link_people_group_id
770 ,l_eligible_pg_exists);
771
772 --
773 -- Construct the date tables for ALU
774 --
775 if l_eligible_pg_exists then
776
777 hr_utility.set_location(l_proc, 10);
778
779 l_asg_locked := false;
780 --
781 -- Setup the ALU table data
782 --
783 for i in 1..p_link_id_tab.count loop
784 --
785 l_link_id := p_link_id_tab(i);
786 l_link_start_date := p_link_start_date_tab(i);
787 l_link_end_date := p_link_end_date_tab(i);
788 --
789 -- Check if ALU exists for this element link.
790 --
791 open csr_alu_exists(l_link_id);
792 fetch csr_alu_exists into l_dummy;
793 if csr_alu_exists%found then
794 l_alu_exists := true;
795 else
796 l_alu_exists := false;
797 end if;
798 close csr_alu_exists;
799
800 if not l_alu_exists then
801 --
802 -- Create ALU records comparing the link dates and
803 -- the eligible assignment date range.
804 --
805 -- Element Link |--------------->
806 -- Eligible Assignment |----------> |-------->
807 --
808 -- ALU |-----> |---->
809 --
810 -- Note: We no longer check the termination rule for ALUs.
811 --
812 for j in 1..g_alu_asg_pg_hist.count loop
813 --
814 l_asg_start_date := g_alu_asg_pg_hist(j).effective_start_date;
815 l_asg_end_date := g_alu_asg_pg_hist(j).effective_end_date;
816 --
817 if NOT l_asg_locked then
818 --
819 -- Lock the assignment.
820 --
821 lock_asg(p_assignment_id, l_asg_start_date, l_asg_end_date);
822 end if;
823 --
824 if l_link_start_date <= l_asg_end_date
825 and l_link_end_date >= l_asg_start_date then
826 --
827 l_alu_start_date := greatest(l_link_start_date, l_asg_start_date);
828 l_alu_end_date := least(l_link_end_date, l_asg_end_date);
829 --
830 if l_alu_end_date >= l_alu_start_date then
831
832 l_alu_idx := l_alu_idx+1;
833 l_alu_start_date_tab(l_alu_idx) := l_alu_start_date;
834 l_alu_end_date_tab(l_alu_idx) := l_alu_end_date;
835 l_alu_link_id_tab(l_alu_idx) := l_link_id;
836
840 --
837 end if;
838 end if;
839 end loop;
841 -- The assignment rows have been locked.
842 --
843 l_asg_locked := true;
844 --
845 end if;
846 end loop;
847 --
848 -- Upload ALUs
849 --
850 forall i in 1..l_alu_start_date_tab.count
851 insert into pay_assignment_link_usages_f
852 (assignment_link_usage_id
853 ,effective_start_date
854 ,effective_end_date
855 ,element_link_id
856 ,assignment_id)
857 values
858 (pay_assignment_link_usages_s.nextval
859 ,l_alu_start_date_tab(i)
860 ,l_alu_end_date_tab(i)
861 ,l_alu_link_id_tab(i)
862 ,p_assignment_id
863 );
864 --
865 end if;
866 --
867 hr_utility.set_location('Leaving: '||l_proc, 100);
868 --
869 end create_alu_asg_pg;
870 --
871 --------------------------------------------------------------------------------
872 --
873 procedure create_alu_asg
874 --
875 --******************************************************************************
876 --* creates ALU's for the assignment with the specified element links. *
877 --* *
878 --* NOTE: The element link array should start with index number 1 and *
879 --* should be sorted by people group id and link effective dates must be *
880 --* min effective_start_date and max effective_end_date. *
881 --******************************************************************************
882 --
883 (p_assignment_id in number
884 ,p_pg_link_tab in t_pg_link_tab
885 )
886 is
887 l_proc varchar2(72) := g_package||'create_alu_asg';
888 --
889 type t_pg_index_rec is record
890 (people_group_id number
891 ,start_idx binary_integer
892 ,end_idx binary_integer
893 );
894 type t_pg_index_tab is table of t_pg_index_rec
895 index by binary_integer;
896 --
897 l_pg_idx_tab t_pg_index_tab;
898 l_idx number:=0;
899 l_prev_pg_id number;
900 --
901 l_eligible_pg_exists boolean;
902 l_link_id_tab t_num_tab;
903 l_link_start_date_tab t_date_tab;
904 l_link_end_date_tab t_date_tab;
905 l_link_idx number;
906 --
907 begin
908 --
909 hr_utility.set_location('Entering: '||l_proc, 5);
910 --
911 -- Check to see if the specified table variable contains
912 -- any element link data.
913 --
914 if p_pg_link_tab.count = 0 then
915 --
916 -- No element link was specified, hence exit this procedure.
917 --
918 hr_utility.set_location(l_proc, 10);
919 return;
920 end if;
921
922 --
923 -- Initialize the assignment cache.
924 --
925 init_alu_asg(p_assignment_id);
926
927 --
928 -- Check to see if the assignment is associated with any people group.
929 --
930 if g_alu_asg_hist.count = 0 then
931 --
932 -- No people group is associated with this assignment,
933 -- hence exit this procedure.
934 --
935 hr_utility.set_location(l_proc, 20);
936 return;
937 end if;
938
939 --
940 -- Derive distinct people groups from the specified table variable.
941 --
942 for i in 1..p_pg_link_tab.count loop
943 if p_pg_link_tab(i).people_group_id = l_prev_pg_id then
944 l_pg_idx_tab(l_idx).end_idx := i;
945 else
946 l_idx := l_idx+1;
947 l_prev_pg_id := p_pg_link_tab(i).people_group_id;
948 l_pg_idx_tab(l_idx).people_group_id := l_prev_pg_id;
949 l_pg_idx_tab(l_idx).start_idx := i;
950 l_pg_idx_tab(l_idx).end_idx := i;
951 end if;
952 end loop;
953 --
954 -- Loop for each people group
955 --
956 for i in 1..l_pg_idx_tab.count loop
957 --
958 -- Check the eligibility of the people group.
959 --
960 chk_pg_eligibility
961 (p_assignment_id
962 ,l_pg_idx_tab(i).people_group_id
963 ,l_eligible_pg_exists);
964
965 --
966 if l_eligible_pg_exists then
967 --
968 l_link_id_tab.delete;
969 l_link_start_date_tab.delete;
970 l_link_end_date_tab.delete;
971 l_link_idx := 0;
972 --
973 -- Prepare element link array for this people group.
974 --
975 for j in l_pg_idx_tab(i).start_idx..l_pg_idx_tab(i).end_idx loop
976 l_link_idx := l_link_idx+1;
977 l_link_id_tab(l_link_idx) := p_pg_link_tab(j).element_link_id;
978 l_link_start_date_tab(l_link_idx)
979 := p_pg_link_tab(j).effective_start_date;
980 l_link_end_date_tab(l_link_idx)
981 := p_pg_link_tab(j).effective_end_date;
982 end loop;
983 --
984 -- Create ALUs for this people group.
985 --
986 create_alu_asg_pg
987 (p_assignment_id => p_assignment_id
988 ,p_link_people_group_id => l_pg_idx_tab(i).people_group_id
989 ,p_link_id_tab => l_link_id_tab
990 ,p_link_start_date_tab => l_link_start_date_tab
991 ,p_link_end_date_tab => l_link_end_date_tab
992 );
993 --
994 end if;
995 --
996 end loop;
997 --
998 hr_utility.set_location('Leaving: '||l_proc, 100);
999 --
1000 end create_alu_asg;
1001 --
1002 --------------------------------------------------------------------------------
1003 --
1007 --* Name : rebuild_alus *
1004 procedure rebuild_alus
1005 --
1006 --******************************************************************************
1008 --* Purpose : This procedure rebuilds all ALUs for a given assignment id *
1009 --* and is used by the Generic Upgrade Mechanism. *
1010 --******************************************************************************
1011 --
1012 (p_assignment_id in number)
1013 is
1014 --
1015 -- user defined types
1016 --
1017 type t_asg_rec is record
1018 (effective_start_date date,
1019 effective_end_date date,
1020 business_group_id number,
1021 people_group_id number,
1022 id_flex_num number);
1023 --
1024 type t_alu_start_date is table of pay_assignment_link_usages_f.effective_start_date%type
1025 index by binary_integer;
1026 --
1027 type t_alu_end_date is table of pay_assignment_link_usages_f.effective_end_date%type
1028 index by binary_integer;
1029 --
1030 type t_alu_link_id is table of pay_assignment_link_usages_f.element_link_id%type
1031 index by binary_integer;
1032 --
1033 type t_alu_tab is record
1034 (start_date t_alu_start_date,
1035 end_date t_alu_end_date,
1036 link_id t_alu_link_id);
1037 --
1038 -- find all instances of the assignment that have a people group
1039 --
1040 cursor csr_assignment
1041 (
1042 p_assignment_id number
1043 ) is
1044 select asg.effective_start_date,
1045 asg.effective_end_date,
1046 asg.business_group_id,
1047 asg.people_group_id,
1048 ppg.id_flex_num
1049 from per_all_assignments_f asg,
1050 pay_people_groups ppg
1051 where asg.assignment_id = p_assignment_id
1052 and asg.assignment_type not in ('A','O')
1053 and asg.people_group_id is not null
1054 and ppg.people_group_id = asg.people_group_id
1055 order by asg.effective_start_date;
1056 --
1057 -- find all element links that are match the people group
1058 --
1059 cursor csr_link
1060 (
1061 p_id_flex_num number,
1062 p_business_group_id number,
1063 p_people_group_id number,
1064 p_effective_start_date date,
1065 p_effective_end_date date
1066 ) is
1067 select el.element_link_id,
1068 min(el.effective_start_date) effective_start_date,
1069 max(el.effective_end_date) effective_end_date
1070 from pay_element_links_f el,
1071 pay_people_groups el_pg,
1072 pay_people_groups asg_pg
1073 where asg_pg.id_flex_num = p_id_flex_num
1074 and asg_pg.people_group_id = p_people_group_id
1075 and el_pg.id_flex_num = asg_pg.id_flex_num
1076 and el.business_group_id + 0 = p_business_group_id
1077 and el.effective_start_date <= p_effective_end_date
1078 and el.effective_end_date >= p_effective_start_date
1079 and el_pg.people_group_id = el.people_group_id
1080 and (el_pg.segment1 is null or el_pg.segment1 = asg_pg.segment1)
1081 and (el_pg.segment2 is null or el_pg.segment2 = asg_pg.segment2)
1082 and (el_pg.segment3 is null or el_pg.segment3 = asg_pg.segment3)
1083 and (el_pg.segment4 is null or el_pg.segment4 = asg_pg.segment4)
1084 and (el_pg.segment5 is null or el_pg.segment5 = asg_pg.segment5)
1085 and (el_pg.segment6 is null or el_pg.segment6 = asg_pg.segment6)
1086 and (el_pg.segment7 is null or el_pg.segment7 = asg_pg.segment7)
1087 and (el_pg.segment8 is null or el_pg.segment8 = asg_pg.segment8)
1088 and (el_pg.segment9 is null or el_pg.segment9 = asg_pg.segment9)
1089 and (el_pg.segment10 is null or el_pg.segment10 = asg_pg.segment10)
1090 and (el_pg.segment11 is null or el_pg.segment11 = asg_pg.segment11)
1091 and (el_pg.segment12 is null or el_pg.segment12 = asg_pg.segment12)
1092 and (el_pg.segment13 is null or el_pg.segment13 = asg_pg.segment13)
1093 and (el_pg.segment14 is null or el_pg.segment14 = asg_pg.segment14)
1094 and (el_pg.segment15 is null or el_pg.segment15 = asg_pg.segment15)
1095 and (el_pg.segment16 is null or el_pg.segment16 = asg_pg.segment16)
1096 and (el_pg.segment17 is null or el_pg.segment17 = asg_pg.segment17)
1097 and (el_pg.segment18 is null or el_pg.segment18 = asg_pg.segment18)
1098 and (el_pg.segment19 is null or el_pg.segment19 = asg_pg.segment19)
1099 and (el_pg.segment20 is null or el_pg.segment20 = asg_pg.segment20)
1100 and (el_pg.segment21 is null or el_pg.segment21 = asg_pg.segment21)
1101 and (el_pg.segment22 is null or el_pg.segment22 = asg_pg.segment22)
1102 and (el_pg.segment23 is null or el_pg.segment23 = asg_pg.segment23)
1103 and (el_pg.segment24 is null or el_pg.segment24 = asg_pg.segment24)
1104 and (el_pg.segment25 is null or el_pg.segment25 = asg_pg.segment25)
1105 and (el_pg.segment26 is null or el_pg.segment26 = asg_pg.segment26)
1106 and (el_pg.segment27 is null or el_pg.segment27 = asg_pg.segment27)
1107 and (el_pg.segment28 is null or el_pg.segment28 = asg_pg.segment28)
1108 and (el_pg.segment29 is null or el_pg.segment29 = asg_pg.segment29)
1109 and (el_pg.segment30 is null or el_pg.segment30 = asg_pg.segment30)
1110 group by el.element_link_id;
1111 --
1112 -- local variables
1113 --
1114 v_assignment t_asg_rec;
1115 v_alu_tab t_alu_tab;
1116 v_asg_start_date date;
1117 v_asg_end_date date;
1118 v_people_group_id number;
1119 v_id_flex_num number;
1120 v_alu_start_date date;
1121 v_alu_end_date date;
1122 v_alu_term_date date;
1126 --
1123 v_counter number := 0;
1124 --
1125 begin
1127 -- Delete all the alus for the assignment
1128 --
1129 delete from pay_assignment_link_usages_f alu
1130 where alu.assignment_id = p_assignment_id;
1131 --
1132 --
1133 open csr_assignment(p_assignment_id);
1134 --
1135 -- get first assignment record to initialise variables
1136 --
1137 fetch csr_assignment into v_assignment;
1138 if csr_assignment%found then
1139 --
1140 -- set up variables for use in loop
1141 --
1142 v_asg_start_date := v_assignment.effective_start_date;
1143 v_asg_end_date := v_assignment.effective_end_date;
1144 v_people_group_id := v_assignment.people_group_id;
1145 v_id_flex_num := v_assignment.id_flex_num;
1146 --
1147 while csr_assignment%found loop
1148 --
1149 -- get next assignment record
1150 --
1151 fetch csr_assignment into v_assignment;
1152 --
1153 -- detect change of people group , non-contiguous people groups or
1154 -- that the last record has been read
1155 --
1156 if csr_assignment%notfound or not
1157 (v_assignment.people_group_id = v_people_group_id and
1158 v_assignment.effective_start_date = v_asg_end_date + 1) then
1159 --
1160 -- find all links that overlap with the assignment and have the same
1161 -- people group as the assignment
1162 --
1163 for v_link in csr_link(v_id_flex_num,
1164 v_assignment.business_group_id,
1165 v_people_group_id,
1166 v_asg_start_date,
1167 v_asg_end_date) loop
1168 --
1169 -- calculate the start date of the alu which is the greatest of
1170 -- the start dates of the link and assignment
1171 --
1172 v_alu_start_date := greatest(v_asg_start_date,
1173 v_link.effective_start_date);
1174 --
1175 -- find the termination date of the alu if the person has been
1176 -- terminated ie. taking inot account the termination processing
1177 -- rule of the element type. if no termination has taken place
1178 -- then the date returned is the end of time.
1179 -- nb. v_dummy_date is used to soak up some out parameters that
1180 -- are not required.
1181 --
1182 -- Bug 5202396.
1183 -- The check for termination rule caused a significant performance
1184 -- issue. Since ALU is only a part of the link eligibility rules,
1185 -- we can determine the end date with the link and the assignment.
1186 --
1187 /***
1188 hr_entry.entry_asg_pay_link_dates(p_assignment_id,
1189 v_link.element_link_id,
1190 v_alu_start_date,
1191 v_alu_term_date,
1192 v_dummy_date,
1193 v_dummy_date,
1194 v_dummy_date,
1195 v_dummy_date,
1196 false);
1197 ***/
1198 --
1199 -- calculate the end date of the alu which is the least of the
1200 -- end dates of the link and assignment.
1201 --
1202 v_alu_end_date := least(v_asg_end_date,
1203 v_link.effective_end_date);
1204 --
1205 -- Make sure that the alu start date is on or before the end date
1206 --
1207 if v_alu_start_date <= v_alu_end_date then
1208 --
1209 v_counter := v_counter + 1;
1210 --
1211 v_alu_tab.start_date(v_counter) := v_alu_start_date;
1212 v_alu_tab.end_date(v_counter) := v_alu_end_date;
1213 v_alu_tab.link_id(v_counter) := v_link.element_link_id;
1214 --
1215 end if;
1216 --
1217 end loop;
1218 --
1219 -- reset start and end dates
1220 --
1221 v_asg_start_date := v_assignment.effective_start_date;
1222 v_asg_end_date := v_assignment.effective_end_date;
1223 --
1224 else
1225 --
1226 -- increment end date of assignment
1227 --
1228 v_asg_end_date := v_assignment.effective_end_date;
1229 --
1230 end if;
1231 --
1232 -- save value for future comparison
1233 --
1234 v_people_group_id := v_assignment.people_group_id;
1235 v_id_flex_num := v_assignment.id_flex_num;
1236 --
1237 -- Create the ALUs in bulk
1238 --
1239 forall i in 1..v_counter
1240 insert into pay_assignment_link_usages_f
1241 (assignment_link_usage_id,
1242 effective_start_date,
1243 effective_end_date,
1244 element_link_id,
1245 assignment_id)
1246 values
1247 (
1248 pay_assignment_link_usages_s.nextval,
1249 v_alu_tab.start_date(i),
1250 v_alu_tab.end_date(i),
1251 v_alu_tab.link_id(i),
1252 p_assignment_id
1253 );
1254 --
1255 v_counter := 0;
1256 v_alu_tab.start_date.delete;
1257 v_alu_tab.end_date.delete;
1258 v_alu_tab.link_id.delete;
1259 --
1260 end loop;
1261 --
1262 end if;
1263 --
1264 close csr_assignment;
1265 --
1266 end rebuild_alus;
1267 --
1270 end PAY_ASG_LINK_USAGES_PKG;
1268 --------------------------------------------------------------------------------
1269 --