DBA Data[Home] [Help]

PACKAGE BODY: APPS.HXC_TIMECARD_BLOCK_UTILS

Source


1 PACKAGE BODY hxc_timecard_block_utils AS
2 /* $Header: hxctcbkut.pkb 120.8 2011/08/23 13:11:26 bbayragi ship $ */
3 
4 g_debug 	     boolean 	  := hr_utility.debug_enabled;
5 
6 g_package        varchar2(25) := 'hxc_timecard_block_utils.';
7 g_timecard_index number;
8 
9 e_no_existing_block exception;
10 
11 Function any_new_blocks
12           (p_blocks in hxc_block_table_type)
13           return varchar2 is
14 
15 l_new   varchar2(3) := 'NO';
16 l_index number;
17 l_found boolean := false;
18 
19 Begin
20 
21 l_index := p_blocks.first;
22 Loop
23   Exit when ((not p_blocks.exists(l_index)) OR (l_found));
24 
25   if(
26      (p_blocks(l_index).new = 'Y')
27     AND
28      (is_active_block(p_blocks(l_index)))
29     AND
30      (p_blocks(l_index).time_building_block_id > 0)
31     ) then
32 
33     l_new := 'YES';
34     l_found := true;
35 
36   end if;
37 
38   l_index := p_blocks.next(l_index);
39 End Loop;
40 
41 return l_new;
42 
43 End;
44 
45 Procedure initialize_timecard_index is
46 
47 Begin
48 
49 g_timecard_index := null;
50 
51 End initialize_timecard_index;
52 
53 FUNCTION find_active_timecard_index
54           (p_blocks in hxc_block_table_type)
55          RETURN number is
56 
57 l_tc_index NUMBER := null;
58 l_index NUMBER;
59 
60 l_proc varchar2(55) := g_package||'find_active_timecard_index';
61 
62 BEGIN
63 
64 if(g_timecard_index is not null) then
65    if(p_blocks.exists(g_timecard_index)) then
66       if(p_blocks(g_timecard_index).scope in (hxc_timecard.c_timecard_scope, hxc_timecard.c_template_scope))then
67 	 l_tc_index := g_timecard_index;
68       else
69 	 g_timecard_index := null;
70       end if;
71    else
72       g_timecard_index := null;
73    end if;
74 end if;
75 
76 if(g_timecard_index is null) then
77 
78   l_index := p_blocks.first;
79 
80   LOOP
81     EXIT WHEN ((NOT p_blocks.exists(l_index)) OR (l_tc_index is NOT NULL));
82 
83     if(
84        (p_blocks(l_index).scope in (hxc_timecard.c_timecard_scope, hxc_timecard.c_template_scope))
85        AND
86         (date_value(p_blocks(l_index).date_to) = hr_general.end_of_time)
87        ) then
88 
89       l_tc_index := l_index;
90 
91     end if;
92 
93     l_index := p_blocks.next(l_index);
94 
95   END LOOP;
96 
97   g_timecard_index := l_tc_index;
98 
99 end if; -- can we use the cached value?
100 
101 if(l_tc_index is null) then
102 --
103 -- Most likely we are deleting the timecard.
104 -- just find the index corresponding to the
105 -- timecard scope or timecard template scope
106 -- block
107 
108   l_index := p_blocks.first;
109 
110   LOOP
111     EXIT WHEN ((NOT p_blocks.exists(l_index)) OR (l_tc_index is NOT NULL));
112 
113     if(p_blocks(l_index).scope in (hxc_timecard.c_timecard_scope, hxc_timecard.c_template_scope))then
114 
115       l_tc_index := l_index;
116 
117     end if;
118 
119     l_index := p_blocks.next(l_index);
120 
121   END LOOP;
122 
123   g_timecard_index := l_tc_index;
124 
125 end if;
126 
127 return l_tc_index;
128 
129 END find_active_timecard_index;
130 
131 FUNCTION convert_to_dpwr_blocks
132            (p_blocks in hxc_block_table_type
133            ) return hxc_self_service_time_deposit.timecard_info is
134 
135 l_blocks hxc_self_service_time_deposit.timecard_info;
136 l_index  NUMBER;
137 
138 BEGIN
139 
140 l_index := p_blocks.first;
141 
142 LOOP
143 
144  EXIT WHEN NOT p_blocks.exists(l_index);
145 
146  l_blocks(l_index).TIME_BUILDING_BLOCK_ID := p_blocks(l_index).TIME_BUILDING_BLOCK_ID;
147  l_blocks(l_index).TYPE := p_blocks(l_index).TYPE;
148  l_blocks(l_index).MEASURE := p_blocks(l_index).MEASURE;
149  l_blocks(l_index).UNIT_OF_MEASURE := p_blocks(l_index).UNIT_OF_MEASURE;
150  l_blocks(l_index).START_TIME := date_value(p_blocks(l_index).START_TIME);
151  l_blocks(l_index).STOP_TIME := date_value(p_blocks(l_index).STOP_TIME);
152  l_blocks(l_index).PARENT_BUILDING_BLOCK_ID := p_blocks(l_index).PARENT_BUILDING_BLOCK_ID;
153  l_blocks(l_index).PARENT_IS_NEW := p_blocks(l_index).PARENT_IS_NEW;
154  l_blocks(l_index).SCOPE := p_blocks(l_index).SCOPE;
155  l_blocks(l_index).OBJECT_VERSION_NUMBER := p_blocks(l_index).OBJECT_VERSION_NUMBER;
156  l_blocks(l_index).APPROVAL_STATUS := p_blocks(l_index).APPROVAL_STATUS;
157  l_blocks(l_index).RESOURCE_ID := p_blocks(l_index).RESOURCE_ID;
158  l_blocks(l_index).RESOURCE_TYPE := p_blocks(l_index).RESOURCE_TYPE;
159  l_blocks(l_index).APPROVAL_STYLE_ID := p_blocks(l_index).APPROVAL_STYLE_ID;
160  l_blocks(l_index).DATE_FROM := date_value(p_blocks(l_index).DATE_FROM);
161  l_blocks(l_index).DATE_TO := date_value(p_blocks(l_index).DATE_TO);
162  l_blocks(l_index).COMMENT_TEXT := p_blocks(l_index).COMMENT_TEXT;
163  l_blocks(l_index).PARENT_BUILDING_BLOCK_OVN := p_blocks(l_index).PARENT_BUILDING_BLOCK_OVN;
164  l_blocks(l_index).NEW := p_blocks(l_index).NEW;
165  l_blocks(l_index).CHANGED := p_blocks(l_index).CHANGED;
166  l_blocks(l_index).PROCESS := p_blocks(l_index).PROCESS;
167 
168  l_index := p_blocks.next(l_index);
169 
170 END LOOP;
171 
172 return l_blocks;
173 
174 END convert_to_dpwr_blocks;
175 
176 Function is_new_block
177           (p_block in HXC_BLOCK_TYPE)
178            return BOOLEAN is
179 
180 Begin
181 
182 if(p_block.new = 'Y') then
183   return true;
184 else
185   return false;
186 end if;
187 
188 End is_new_block;
189 
190 Function is_active_block
191           (p_block in HXC_BLOCK_TYPE)
192            return BOOLEAN is
193 
194 Begin
195 
196 if(fnd_date.canonical_to_date(p_block.date_to) = hr_general.end_of_time) then
197   return true;
198 else
199   return false;
200 end if;
201 
202 End is_active_block;
203 
204 Function is_timecard_block
205           (p_block in HXC_BLOCK_TYPE)
206            return BOOLEAN is
207 Begin
208 
209 if(
210    (p_block.scope = hxc_timecard.c_timecard_scope)
211   OR
212    (p_block.scope = hxc_timecard.c_template_scope)
213   )then
214   return true;
215 else
216   return false;
217 end if;
218 
219 End is_timecard_block;
220 
221 Function is_day_block
222           (p_block in HXC_BLOCK_TYPE)
223            return BOOLEAN is
224 Begin
225 
226 if(p_block.scope = hxc_timecard.c_day_scope) then
227   return true;
228 else
229   return false;
230 end if;
231 
232 End is_day_block;
233 
234 Function is_existing_block
235            (p_block in HXC_BLOCK_TYPE)
236            return BOOLEAN is
237 
238 cursor c_existing
239          (p_block_id in hxc_time_building_blocks.time_building_block_id%type
240          ,p_block_ovn in hxc_time_building_blocks.object_version_number%type
241          ) is
242   select 'Y'
243     from hxc_time_building_blocks tbb
244    where tbb.time_building_block_id = p_block_id
245      and tbb.object_version_number = p_block_ovn;
246 
247 l_dummy varchar2(1);
248 
249 Begin
250 
251 open c_existing(p_block.time_building_block_id,p_block.object_version_number);
252 fetch c_existing into l_dummy;
253 if(c_existing%notfound) then
254   close c_existing;
255   return false;
256 else
257   close c_existing;
258   return true;
259 end if;
260 
261 End is_existing_block;
262 
263 Function is_detail_block
264           (p_block in HXC_BLOCK_TYPE)
265            return BOOLEAN is
266 Begin
267 
268 if(p_block.scope = hxc_timecard.c_detail_scope)then
269   return true;
270 else
271   return false;
272 end if;
273 
274 End is_detail_block;
275 
276 Function is_parent_block
277           (p_block      in HXC_BLOCK_TYPE
278           ,p_parent_id  in hxc_time_building_blocks.time_building_block_id%type
279           ,p_parent_ovn in hxc_time_building_blocks.object_version_number%type
280           ,p_check_id   in boolean
281           ) return pls_integer is
282 Begin
283 
284 if(
285    (p_block.parent_building_block_id = p_parent_id)
286   AND
287    (p_block.parent_building_block_ovn = p_parent_ovn)
288   ) then
289    return 0;
290 elsif(p_block.parent_building_block_id = p_parent_id) then
291    return 1;
292 else
293   return 2;
294 end if;
295 
296 End is_parent_block;
297 
298 Function is_parent_block
299           (p_block      in HXC_BLOCK_TYPE
300           ,p_parent_id  in hxc_time_building_blocks.time_building_block_id%type
301           ,p_parent_ovn in hxc_time_building_blocks.object_version_number%type
302           ) return BOOLEAN is
303 
304 Begin
305    if(is_parent_block(p_block,p_parent_id,p_parent_ovn,true)=0) then
306       return true;
307    else
308       return false;
309    end if;
310 End is_parent_block;
311 
312 Function is_updated_block
313           (p_block in HXC_BLOCK_TYPE)
314           return BOOLEAN is
315 
316 l_prev_block hxc_block_type;
317 
318 Begin
319 
320 if(is_new_block(p_block)) then
321   if(p_block.changed = 'Y') then
322     return true;
323   else
324     return false;
325   end if;
326 else
327   l_prev_block := build_block(p_block.time_building_block_id,p_block.object_version_number);
328   if(blocks_are_different(p_block,l_prev_block)) then
329     return true;
330   else
331     -- 115.5 Change
332     -- We might be processing this block due to a change in the
333     -- attributes, so we should check the process flag as well
334     if(process_block(p_block)) then
335       return true;
336     else
337       return false;
338     end if;
339     -- end 115.5 Change
340   end if;
341 end if;
342 
343 End is_updated_block;
344 
345 Function parent_has_changed
346            (p_blocks in HXC_BLOCK_TABLE_TYPE
347            ,p_parent_block_id in hxc_time_building_blocks.time_building_block_id%type
348            ) return BOOLEAN is
349 
350 l_index number;
351 l_parent_changed boolean := false;
352 l_parent_found boolean := false;
353 
354 Begin
355 
356 l_index := p_blocks.first;
357 
358 Loop
359   Exit when ((not p_blocks.exists(l_index)) or (l_parent_found));
360   if(p_blocks(l_index).time_building_block_id = p_parent_block_id) then
361     if((p_blocks(l_index).changed = 'Y')OR(process_block(p_blocks(l_index)))) then
362       l_parent_changed := true;
363     end if;
364     l_parent_found := true;
365   end if;
366   l_index := p_blocks.next(l_index);
367 End loop;
368 
369 return l_parent_changed;
370 
371 End parent_has_changed;
372 
373 Function process_block
374           (p_block in HXC_BLOCK_TYPE
375           ) return BOOLEAN is
376 
377 Begin
378 
379 if(p_block.process = hxc_timecard.c_process) then
380  return true;
381 else
382  return false;
383 end if;
384 
385 End process_block;
386 
387 Function can_process_block
388           (p_block in hxc_block_type
389           ) return boolean is
390 
391 Begin
392 
393 if(process_block(p_block)) then
394   return true;
395 else
396   if(is_new_block(p_block)) then
397     return false;
398   else
399     return true;
400   end if;
401 end if;
402 
403 End can_process_block;
404 
405 Function date_value
406           (p_block_value in varchar2
407           ) return date is
408 
409 Begin
410 
411 return fnd_date.canonical_to_date(p_block_value);
412 
413 end date_value;
414 
415 Function build_block
416           (p_time_building_block_id in HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE
417           ,p_time_building_block_ovn in HXC_TIME_BUILDING_BLOCKS.OBJECT_VERSION_NUMBER%TYPE
418           ) return HXC_BLOCK_TYPE is
419 
420 cursor c_block
421         (p_time_building_block_id in HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE
422         ,p_time_building_block_ovn in HXC_TIME_BUILDING_BLOCKS.OBJECT_VERSION_NUMBER%TYPE
423         ) is
424 select *
425   from hxc_time_building_blocks
426  where time_building_block_id = p_time_building_block_id
427    and object_version_number = p_time_building_block_ovn;
428 
429 
430 l_block     c_block%ROWTYPE;
431 l_new_block HXC_BLOCK_TYPE;
432 
433 BEGIN
434 
435 open c_block(p_time_building_block_id,p_time_building_block_ovn);
436 fetch c_block into l_block;
437 
438 if(c_block%FOUND) then
439 
440   close c_block;
441 
442   -- Convert to the type
443 
444   l_new_block :=
445     HXC_BLOCK_TYPE
446      (l_block.TIME_BUILDING_BLOCK_ID
447      ,l_block.TYPE
448      ,l_block.MEASURE
449      ,l_block.UNIT_OF_MEASURE
450      ,fnd_date.date_to_canonical(l_block.START_TIME)
451      ,fnd_date.date_to_canonical(l_block.STOP_TIME)
452      ,l_block.PARENT_BUILDING_BLOCK_ID
453      ,'N' --l_block.PARENT_IS_NEW
454      ,l_block.SCOPE
455      ,l_block.OBJECT_VERSION_NUMBER
456      ,l_block.APPROVAL_STATUS
457      ,l_block.RESOURCE_ID
458      ,l_block.RESOURCE_TYPE
459      ,l_block.APPROVAL_STYLE_ID
460      ,fnd_date.date_to_canonical(l_block.DATE_FROM)
461      ,fnd_date.date_to_canonical(l_block.DATE_TO)
462      ,l_block.COMMENT_TEXT
463      ,l_block.PARENT_BUILDING_BLOCK_OVN
464      ,'N' --l_block.NEW
465      ,'N' --l_block.CHANGED
466      ,'N' --l_block.process
467      ,l_block.application_set_id
468      ,l_block.translation_display_key
469      );
470 
471 else
472   --
473   -- No block with this id and ovn
474   --
475   close c_block;
476   raise e_no_existing_block;
477 
478 end if;
479 
480 
481 return l_new_block;
482 
483 END build_block;
484 
485 Function blocks_are_different
486           (p_block1 in HXC_BLOCK_TYPE
487           ,p_block2 in HXC_BLOCK_TYPE
488           ) return boolean is
489 
490 l_proc varchar2(70) := 'block_utils.blocks_are_different';
491 
492 Begin
493 
494 IF g_debug THEN
495   hr_utility.trace(' In hxc_timecard_block_utilis.blocks_are_different ..');
496 END IF;
497 
498 if(p_block1.scope = 'DETAIL') then
499 
500 --
501 -- There is only a subset of things that
502 -- can be changed in the block, we
503 -- look for these things
504 --
505 -- 1. Measure
506 -- 2029550 Implementation
507 -- We need to consider 3 cases
508 -- compare a none null measure with a none null measure
509 -- compare a null measure with a none null measure
510 -- compare a none null measure with a null measure
511    if(p_block1.type='MEASURE' AND p_block2.type='MEASURE') then
512       if p_block1.measure <> p_block2.measure then
513        hxc_block_attribute_update.g_tc_api_flag := 'N';
514        return true;
515       end if;
516       if nvl(p_block1.measure,0) <> p_block2.measure then
517        hxc_block_attribute_update.g_tc_api_flag := 'N';
518        return true;
519       end if;
520       if p_block1.measure <> nvl(p_block2.measure,0) then
521        hxc_block_attribute_update.g_tc_api_flag := 'N';
522        return true;
523       end if;
524     end if;
525     if(p_block1.type='RANGE' AND p_block2.type = 'RANGE') then
526   -- 2. Start Time
527     if(nvl(p_block1.start_time,'NULL') <> nvl(p_block2.start_time,'NULL')) then
528       hxc_block_attribute_update.g_tc_api_flag := 'N';
529       return true;
530     end if;
531   -- 3. Stop Time
532     if(nvl(p_block1.stop_time,'NULL') <> nvl(p_block2.stop_time,'NULL')) then
533       hxc_block_attribute_update.g_tc_api_flag := 'N';
534       return true;
535     end if;
536   end if;
537 -- 4. Comment
538   if(nvl(p_block1.comment_text,'NULL') <> nvl(p_block2.comment_text,'NULL')) then
539     hxc_block_attribute_update.g_tc_api_flag := 'N';
540     return true;
541   end if;
542 -- 5. Approval Status
543   if(nvl(p_block1.approval_status,'NULL') <> nvl(p_block2.approval_status,'NULL')) then
544     hxc_block_attribute_update.g_tc_api_flag := 'N';
545     return true;
546   end if;
547 -- 6. Unit of measure
548   if(nvl(p_block1.unit_of_measure,'NULL') <> nvl(p_block2.unit_of_measure,'NULL')) then
549     hxc_block_attribute_update.g_tc_api_flag := 'N';
550     return true;
551   end if;
552 -- 7. Parent Building block OVN
553 -- Actually, this one won't work, since the parent OVN isn't updated yet.
554 -- Is this a problem?
555   if(nvl(p_block1.parent_building_block_ovn,0) <> nvl(p_block2.parent_building_block_ovn,0)) then
556     hxc_block_attribute_update.g_tc_api_flag := 'N';
557     return true;
558   end if;
559 -- 8. Date to
560   if(nvl(p_block1.date_to,hr_general.end_of_time) <> nvl(p_block2.date_to,hr_general.end_of_time)) then
561     hxc_block_attribute_update.g_tc_api_flag := 'N';
562     return true;
563   end if;
564 -- 9. Type
565   if(nvl(p_block1.type,'RANGE') <> nvl(p_block2.type,'RANGE')) then
566     hxc_block_attribute_update.g_tc_api_flag := 'N';
567     return true;
568   end if;
569 -- 10. Approval style id
570   if(nvl(p_block1.approval_style_id,1) <> nvl(p_block2.approval_style_id,1)) then
571     hxc_block_attribute_update.g_tc_api_flag := 'N';
572     return true;
573   end if;
574 -- 11. Translation Display Key
575   if(nvl(p_block1.translation_display_key,'NULL') <> nvl(p_block2.translation_display_key,'NULL')) then
576 
577 	 hr_utility.trace(' p_block1.translation_display_key ::'||
578                         p_block1.translation_display_key);
579      hr_utility.trace(' p_block2.translation_display_key ::'||
580                         p_block2.translation_display_key);
581      if ((p_block1.translation_display_key IS NULL and p_block2.translation_display_key IS NOT NULL)
582          OR
583          (p_block1.translation_display_key IS NOT NULL and p_block2.translation_display_key IS NULL))
584      then
585         -- Bug 9448458
586         -- blocks are same. Translation display key is null when initially created from API/TK
587         --                  when resubmitted from ss translation display key is not null
588      	hr_utility.trace('OTL: HXC_TIMECARD_BLOCK_UTILS:FALSE');
589 
590       -- Added for Bug 12774447
591       hr_utility.trace(' hxc_block_attribute_update.g_tc_api_flag ::'||hxc_block_attribute_update.g_tc_api_flag);
592 
593       if hxc_block_attribute_update.g_tc_api_flag is null then
594      	  hxc_block_attribute_update.g_tc_api_flag := 'Y';
595       elsif hxc_block_attribute_update.g_tc_api_flag <> 'N' then
596         hxc_block_attribute_update.g_tc_api_flag := 'Y';
597       end if;
598 
599       hr_utility.trace(' hxc_block_attribute_update.g_tc_api_flag ::'||hxc_block_attribute_update.g_tc_api_flag);
600 
601      	return true;
602      else
603         hxc_block_attribute_update.g_tc_api_flag := 'N';
604         hr_utility.trace('OTL: HXC_TIMECARD_BLOCK_UTILS:TRUE');
605 	      return true;
606      end if;
607   end if;
608 elsif((p_block1.scope=hxc_timecard.c_timecard_scope)OR(p_block1.scope=hxc_timecard.c_template_scope)) then
609 -- 1. Comment
610   if(nvl(p_block1.comment_text,'NULL') <> nvl(p_block2.comment_text,'NULL')) then
611     hxc_block_attribute_update.g_tc_api_flag := 'N';
612     return true;
613   end if;
614 -- 2. Approval Status
615   if(nvl(p_block1.approval_status,'NULL') <> nvl(p_block2.approval_status,'NULL')) then
616     hxc_block_attribute_update.g_tc_api_flag := 'N';
617     return true;
618   end if;
619 -- 3. Date to
620   if(nvl(p_block1.date_to,hr_general.end_of_time) <> nvl(p_block2.date_to,hr_general.end_of_time)) then
621     hxc_block_attribute_update.g_tc_api_flag := 'N';
622     return true;
623   end if;
624 -- 4. Approval style id
625   if(nvl(p_block1.approval_style_id,1) <> nvl(p_block2.approval_style_id,1)) then
626     hxc_block_attribute_update.g_tc_api_flag := 'N';
627     return true;
628   end if;
629 elsif(p_block1.scope='DAY') then
630 -- 1. Approval Status
631   if(nvl(p_block1.approval_status,'NULL') <> nvl(p_block2.approval_status,'NULL')) then
632     hxc_block_attribute_update.g_tc_api_flag := 'N';
633     return true;
634   end if;
635 -- 2. Date to
636   if(nvl(p_block1.date_to,hr_general.end_of_time) <> nvl(p_block2.date_to,hr_general.end_of_time)) then
637     hxc_block_attribute_update.g_tc_api_flag := 'N';
638     return true;
639   end if;
640 -- 3. Approval style id
641   if(nvl(p_block1.approval_style_id,1) <> nvl(p_block2.approval_style_id,1)) then
642     hxc_block_attribute_update.g_tc_api_flag := 'N';
643     return true;
644   end if;
645 end if;
646 
647 --
648 -- If we get here, the blocks are (at least in terms of the user) the same
649 --
650   return false;
651 
652 End blocks_are_different;
653 
654 Procedure sort_blocks
655            (p_blocks          in            HXC_BLOCK_TABLE_TYPE
656            ,p_timecard_blocks    out nocopy HXC_TIMECARD.BLOCK_LIST
657            ,p_day_blocks         out nocopy HXC_TIMECARD.BLOCK_LIST
658            ,p_detail_blocks      out nocopy HXC_TIMECARD.BLOCK_LIST
659            ) is
660 
661 l_block    HXC_BLOCK_TYPE;
662 l_index    NUMBER;
663 
664 Begin
665 
666 l_index := p_blocks.first;
667 LOOP
668   EXIT WHEN NOT p_blocks.exists(l_index);
669   l_block := p_blocks(l_index);
670 
671   if(is_timecard_block(l_block)) then
672     --
673     -- 115.3 Change.  In cases where we have more than one
674     -- timecard block, one will always be end dated, the other
675     -- new.  In this case we must process the deleted one first
676     -- which means we must place the timecard blocks in the
677     -- sorted arrays in reverse order of id.
678     --
679     p_timecard_blocks((-1*l_block.time_building_block_id)) := l_index;
680 
681   elsif(is_day_block(l_block)) then
682 
683     p_day_blocks(l_block.time_building_block_id) := l_index;
684 
685   elsif(is_detail_block(l_block)) then
686 
687     p_detail_blocks(l_block.time_building_block_id) := l_index;
688 
689   end if;
690   l_index := p_blocks.next(l_index);
691 END LOOP;
692 
693 End sort_blocks;
694 
695 Function next_block_id
696            (p_blocks in HXC_BLOCK_TABLE_TYPE
697            ) return number is
698 
699 l_index number;
700 l_bb_id number := -2;
701 
702 Begin
703 
704 l_index := p_blocks.first;
705 
706 Loop
707   Exit when not p_blocks.exists(l_index);
708 
709   if(p_blocks(l_index).time_building_block_id < l_bb_id) then
710     l_bb_id := p_blocks(l_index).time_building_block_id;
711   end if;
712   l_index := p_blocks.next(l_index);
713 End Loop;
714 
715 -- return large negative number to work round strange Santos
716 -- issue.
717 
718 return (l_bb_id-100);
719 
720 End next_block_id;
721 
722 END hxc_timecard_block_utils;