[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;