DBA Data[Home] [Help]

PACKAGE BODY: APPS.HXC_DEPOSIT_CHECKS

Source


1 PACKAGE BODY hxc_deposit_checks AS
2 /* $Header: hxcdpwrck.pkb 120.9 2006/07/13 21:29:54 arundell noship $ */
3 --
4 -- Types
5 --
6 TYPE asg_dates is RECORD
7       (start_date date
8       ,end_date   date
9       );
10 
11 Type asg_info is table of asg_dates index by binary_integer;
12 
13 Type block_list is table of number index by binary_integer;
14 
15 -- Package Variables
16 --
17 g_package  varchar2(33) := '  hxc_deposit_checks.';
18 
19 --
20 -- ----------------------------------------------------------------------------
21 -- |-------------------------< can_delete_template >--------------------------|
22 -- ----------------------------------------------------------------------------
23 -- {Start Of Comments}
24 --
25 -- Description:
26 --   This function is called by the deposit controller for self service
27 -- timecard deposit to ensure that the template the user is requesting to
28 -- delete is not set as a default template for any user.  This should only
29 -- be an issue if the user has set one of their own templates as a default
30 -- or if an administrator has created a public template.
31 --
32 -- Prerequisites:
33 --   The template must exist.
34 --
35 -- In Parameters:
36 --   Name                  Reqd Type     Description
37 --   p_template_id             Yes Number   The id of the timecard
38 --                              template
39 --
40 -- Access Status:
41 --   Internal use only.
42 --
43 -- {End Of Comments}
44 --
45 --
46 Procedure can_delete_template
47         (p_template_id in         hxc_time_building_blocks.time_building_block_id%type
48         ,p_messages    in out nocopy hxc_message_table_type) is
49 
50 cursor c_template_details
51      (p_id in hxc_time_building_blocks.time_building_block_id%type) is
52 select TEMPLATE_TYPE from hxc_template_summary
53 where template_id = p_id;
54 
55 l_exists      VARCHAR2(6);
56 l_template_type hxc_template_summary.template_type%type;
57 l_attached_public_temp_grps varchar2(1500);
58 l_pref_value  VARCHAR2(170);
59 
60 Begin
61 
62 l_attached_public_temp_grps := NULL;
63 
64 open c_template_details(p_template_id);
65 fetch c_template_details into l_template_type;
66 if c_template_details%found then
67 
68   if(l_template_type='PUBLIC') then
69   	--Check whether the public template can be deleted.
70 	l_attached_public_temp_grps := hxc_public_temp_group_comp_api.can_delete_public_template(p_template_id=>p_template_id);
71   end if;
72 
73  if(l_attached_public_temp_grps is NULL) then  --Carry out the normal operations for private/public templates.
74 
75   l_pref_value := l_template_type||'|'||p_template_id;
76 
77   l_exists := HXC_PREFERENCE_EVALUATION.num_hierarchy_occurances
78                  ('TC_W_TMPLT_DFLT_VAL_USR'
79                ,1
80                ,l_pref_value);
81   if ( l_exists <> 0 ) THEN
82     hxc_timecard_message_helper.addErrorToCollection
83       (p_messages
84       ,'HXC_CANT_DEL_TEMPL'
85       ,hxc_timecard.c_error
86       ,null
87       ,null
88       ,hxc_timecard.c_hxc
89       ,null
90       ,null
91       ,null
92       ,null
93       );
94   else
95     l_exists := HXC_PREFERENCE_EVALUATION.num_hierarchy_occurances
96                 ('TC_W_TMPLT_DFLT_VAL_ADMIN'
97                  ,1
98                  ,l_pref_value);
99     if ( l_exists <> 0 ) THEN
100       hxc_timecard_message_helper.addErrorToCollection
101      (p_messages
102      ,'HXC_CANT_DEL_TEMPL'
103      ,hxc_timecard.c_error
104      ,null
105      ,null
106      ,hxc_timecard.c_hxc
107      ,null
108      ,null
109      ,null
110      ,null
111      );
112     END if;
113    END IF;
114   else
115 
116   -- Public Template Specific
117 
118     hxc_timecard_message_helper.addErrorToCollection
119       (p_messages
120       ,'HXC_CANT_DEL_PUB_TEMPL'
121       ,hxc_timecard.c_error
122       ,null
123       ,'GROUPS&'||l_attached_public_temp_grps
124       ,hxc_timecard.c_hxc
125       ,null
126       ,null
127       ,null
128       ,null
129       );
130   end if;
131 end if;
132 close c_template_details;
133 
134 End can_delete_template;
135 --
136 -- ----------------------------------------------------------------------------
137 -- |----------------------------< check_inputs >------------------------------|
138 -- ----------------------------------------------------------------------------
139 -- {Start Of Comments}
140 --
141 -- Description:
142 --   This function is called by the deposit controller for self service
143 -- timecard deposit to ensure that the calling process has sent parameters
144 -- that make sense in terms of deposit.
145 --
146 -- Prerequisites:
147 --   None.
148 --
149 -- In Parameters:
150 --   Name                  Reqd Type     Description
151 --   p_blocks                 Yes  BLOCKS   The blocks to deposit
152 --   p_atttributes            Yes  ATTRS    The attributes to deposit
153 --   p_deposit_mode           Yes  Varchar2 The mode of deposit
154 --   p_template               Yes  Varchar2 Is this a template?
155 --   p_messages               Yes  MESSAGES The application messages
156 --
157 --
158 -- Access Status:
159 --   Internal use only.
160 --
161 -- {End Of Comments}
162 --
163 --
164 PROCEDURE check_inputs
165          (p_blocks          in         hxc_block_table_type
166          ,p_attributes      in         hxc_attribute_table_type
167          ,p_deposit_mode       in         varchar2
168          ,p_template        in         varchar2
169          ,p_messages        in out nocopy hxc_message_table_type
170          ) is
171 
172 l_proc varchar2(70) := g_package||'check_inputs';
173 
174 BEGIN
175 
176 --
177 -- We must have at least one block to deposit
178 --
179 if(p_blocks.count <1) then
180 
181   hxc_timecard_message_helper.addErrorToCollection
182     (p_messages
183     ,'HXC_XXXXX_NO_BLOCKS'
184     ,hxc_timecard.c_error
185     ,null
186     ,null
187     ,hxc_timecard.c_hxc
188     ,null
189     ,null
190     ,null
191     ,null
192     );
193 
194 end if;
195 
196 --
197 -- The deposit mode must be SUBMIT, SAVE or AUDIT
198 -- (others not currently supported)
199 --
200 if (NOT ((p_deposit_mode=hxc_timecard.c_submit) OR (p_deposit_mode=hxc_timecard.c_save) OR p_deposit_mode=hxc_timecard.c_audit)) then
201 
202   hxc_timecard_message_helper.addErrorToCollection
203     (p_messages
204     ,'HXC_XXXXX_INVALID_DEP_MODE'
205     ,hxc_timecard.c_error
206     ,null
207     ,'MODE&'||p_deposit_mode
208     ,hxc_timecard.c_hxc
209     ,null
210     ,null
211     ,null
212     ,null
213     );
214 
215 end if;
216 
217 --
218 -- We must have a Y or N value for the template
219 --
220 if (NOT ((p_template='Y') OR (p_template='N'))) then
221 
222   hxc_timecard_message_helper.addErrorToCollection
223     (p_messages
224     ,'HXC_XXXXX_INVALID_TEMPLATE'
225     ,hxc_timecard.c_error
226     ,null
227     ,'VALUE&'||p_template
228     ,hxc_timecard.c_hxc
229     ,null
230     ,null
231     ,null
232     ,null
233     );
234 
235 end if;
236 
237 if ((p_template='Y') AND (p_deposit_mode = hxc_timecard.c_save)) then
238 
239   hxc_timecard_message_helper.addErrorToCollection
240     (p_messages
241     ,'HXC_XXXXX_INVALID_DEP_MODE'
242     ,hxc_timecard.c_error
243     ,null
244     ,'MODE&'||p_deposit_mode
245     ,hxc_timecard.c_hxc
246     ,null
247     ,null
248     ,null
249     ,null
250     );
251 
252 end if;
253 
254 END check_inputs;
255 --
256 -- ----------------------------------------------------------------------------
257 -- |----------------------------< audit_checks >------------------------------|
258 -- ----------------------------------------------------------------------------
259 -- {Start Of Comments}
260 --
261 -- Description:
262 --   This procedure ensures that the user has entered all reasons required
263 -- by the instance audit requirements.
264 --
265 -- Prerequisites:
266 --   A table of audit reasons exists
267 --
268 -- In Parameters:
269 --   Name                  Reqd Type       Description
270 --   p_blocks                 Yes  BLOCKS     The blocks to deposit
271 --   p_attributes             Yes  ATTRIBUTES The attributes
272 --   p_messages               Yes  MESSAGES   The failure messages
273 --                                /Reason messages
274 --
275 --
276 -- Access Status:
277 --   Internal use only.
278 --
279 -- {End Of Comments}
280 --
281 PROCEDURE audit_checks
282         (p_blocks     in         hxc_block_table_type
283         ,p_attributes in         hxc_attribute_table_type
284         ,p_messages   in out nocopy hxc_message_table_type
285         ) is
286 
287 l_index number;
288 l_found  BOOLEAN;
289 l_att_index number;
290 l_missing_reasons hxc_message_table_type;
291 
292 BEGIN
293 
294 l_missing_reasons := hxc_message_table_type();
295 
296 l_index := p_messages.first;
297 
298 LOOP
299   EXIT WHEN NOT p_messages.exists(l_index);
300   IF(p_messages(l_index).message_level = 'REASON') THEN
301      l_found:=TRUE;
302      l_att_index:=p_attributes.first;
303      LOOP
304        EXIT WHEN ((NOT p_attributes.exists(l_att_index)) OR (NOT l_found));
305        if (
306        ( p_attributes(l_att_index).building_block_id=p_messages(l_index).time_building_block_id)
307          and (p_attributes(l_att_index).ATTRIBUTE_CATEGORY = 'REASON')
308 	    AND (p_messages(l_index).MESSAGE_TOKENS=p_attributes(l_att_index).attribute3)
309     	    AND (p_attributes(l_att_index).NEW ='Y')
310 	    AND (p_attributes(l_att_index).attribute1 is not null)
311 	  ) then
312        l_found:=FALSE;
313        end if;
314        l_att_index:=p_attributes.next(l_att_index);
315      END LOOP;
316 
317      IF l_found THEN
318        hxc_timecard_message_helper.addErrorToCollection
319      (p_messages => l_missing_reasons
320      ,p_message_name => 'HXC_REASON_NOT_ENTERED'
321      ,p_message_tokens => NULL
325      ,p_time_building_block_id => NULL
322      ,p_message_level => hxc_timecard.c_error
323      ,p_message_field => NULL
324      ,p_application_short_name => hxc_timecard.c_hxc
326      ,p_time_building_block_ovn => NULL
327      ,p_time_attribute_id => NULL
328      ,p_time_attribute_ovn => NULL
329      );
330      End if;
331    End if;
332    l_index := p_messages.next(l_index);
333 END LOOP;
334 
335 p_messages := l_missing_reasons;
336 
337 End audit_checks;
338 --
339 -- ----------------------------------------------------------------------------
340 -- |--------------------------< timecard_deleted >----------------------------|
341 -- ----------------------------------------------------------------------------
342 -- {Start Of Comments}
343 --
344 -- Description:
345 --   This function checks that if we have an existing timecard in the same
346 -- period as the one we are attempting to deposit, that the blocks we're
347 -- depositing also cause the existing time store timecard to be date effectively
348 -- deleted.  In that case, we can permit deposit.
349 --
350 -- Prerequisites:
351 --   We have found an existing timecard for this period in the time store.
352 --
353 -- In Parameters:
354 --   Name                  Reqd Type     Description
355 --   p_blocks                 Yes  BLOCKS   The blocks to deposit
356 --   p_timecard_id            Yes  NUMBER   The id of the existing
357 --                              timecard, to check that
358 --                              is being deleted with the
359 --                              deposit.
360 --
361 -- Return Values:
362 --   FALSE : The existing timecard is NOT being deleted with this submission.
363 --   TRUE  : The existing timecard is being deleted with this submission.
364 --
365 -- Access Status:
366 --   Internal use only.
367 --
368 -- {End Of Comments}
369 --
370 --
371 FUNCTION timecard_deleted
372         (p_blocks in HXC_BLOCK_TABLE_TYPE
373         ,p_timecard_id in HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE
374         ) return BOOLEAN is
375 
376 l_deleted_tc BOOLEAN := false;
377 l_block_count NUMBER;
378 
379 BEGIN
380 
381 l_block_count := p_blocks.first;
382 
383 LOOP
384   EXIT WHEN l_deleted_tc;
385   EXIT WHEN NOT p_blocks.exists(l_block_count);
386 
387   if(p_blocks(l_block_count).time_building_block_id = p_timecard_id) then
388    if(fnd_date.canonical_to_date(p_blocks(l_block_count).date_to) <> hr_general.end_of_time) then
389      l_deleted_tc := true;
390    end if;
391   end if;
392 
393   l_block_count := p_blocks.next(l_block_count);
394 
395 END LOOP;
396 
397 RETURN l_deleted_tc;
398 
399 END timecard_deleted;
400 --
401 -- Overloaded version, to call from deposit wrapper.
402 --
403 FUNCTION timecard_deleted
404         (p_blocks in hxc_self_service_time_deposit.timecard_info
405         ,p_timecard_id in HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE
406         ) return BOOLEAN is
407 
408 l_deleted_tc BOOLEAN := false;
409 l_block_count NUMBER;
410 
411 BEGIN
412 
413 l_block_count := p_blocks.first;
414 
418 
415 LOOP
416   EXIT WHEN l_deleted_tc;
417   EXIT WHEN NOT p_blocks.exists(l_block_count);
419   if(p_blocks(l_block_count).time_building_block_id = p_timecard_id) then
420    if(p_blocks(l_block_count).date_to <> hr_general.end_of_time) then
421      l_deleted_tc := true;
422    end if;
423   end if;
424 
425   l_block_count := p_blocks.next(l_block_count);
426 
427 END LOOP;
428 
429 RETURN l_deleted_tc;
430 
431 END timecard_deleted;
432 --
433 -- ----------------------------------------------------------------------------
434 -- |------------------------< chk_timecard_exists >--------------------------|
435 -- ----------------------------------------------------------------------------
436 -- {Start Of Comments}
437 --
438 -- Description:
439 --   This function checks that no current timecards exist within the time
440 --   span of the timecard we're attempting to deposit.
441 --
442 -- Prerequisites:
443 --   We have the timecard resource id, start time, stop time and id which
444 --   we are attempting to deposit.
445 --
446 -- In Parameters:
447 --   Name                  Reqd Type     Description
448 --   p_resource_id            Yes  Number   The resource id
449 --   p_start_time             Yes  Date     The proposed start time
450 --   p_stop_time              Yes  Date     The proposed stop time
451 --   p_time_building_block_id       Yes  Number   The id of this timecard
452 --
453 -- Return Values:
454 --   NULL  : A timecard does not already exist for this period.
455 -- NON-NULL: The value of the time building block id of the timecard
456 --        that already exists, for use in further checks.
457 --
458 -- Access Status:
459 --   Internal use only.
460 --
461 -- {End Of Comments}
462 --
463 --
464 FUNCTION chk_timecard_exists
465         (p_resource_id in HXC_TIME_BUILDING_BLOCKS.RESOURCE_ID%TYPE
466         ,p_start_time in HXC_TIME_BUILDING_BLOCKS.START_TIME%TYPE
467         ,p_stop_time in HXC_TIME_BUILDING_BLOCKS.STOP_TIME%TYPE
468         ,p_time_building_block_id in HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE
469         ) RETURN NUMBER is
470 
471 l_existing_timecard_id HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE;
472 
473 begin
474 
475  select tbb.time_building_block_id into l_existing_timecard_id
476    from hxc_time_building_blocks tbb
477   where tbb.resource_id = p_resource_id
478     and tbb.scope = 'TIMECARD'
479     and tbb.date_to = hr_general.end_of_time
480     and tbb.start_time <= p_stop_time
481     and tbb.stop_time >= p_start_time
482     and tbb.time_building_block_id <> p_time_building_block_id;
483 
484 
485 RETURN l_existing_timecard_id;
486 
487 EXCEPTION
488   WHEN others then
489   --
490   -- No data found error, so continue with deposit.
491   --
492     RETURN null;
493 
494 END chk_timecard_exists;
495 
496 --
497 -- ----------------------------------------------------------------------------
498 -- |------------------------< chk_timecard_deposit >--------------------------|
499 -- ----------------------------------------------------------------------------
500 -- {Start Of Comments}
501 --
502 -- Description:
503 --   This function checks that no current timecards exist within the time
504 --   span of the timecard we're attempting to deposit.
505 --
506 -- Prerequisites:
507 --   The blocks we're attempting to deposit are populated.
508 --
509 -- In Parameters:
510 --   Name                  Reqd Type     Description
511 --   p_blocks                 Yes  BLOCKS   The blocks to deposit
512 --   p_block_number           Yes  number   The number of the block
513 --                              record to check.
514 --
515 -- Return Values:
516 --   FALSE : No timecard exists within this time period, and deposit can
517 --        continue
518 --   TRUE  : A timecard exists, we should raise an error.
519 --
520 -- Access Status:
521 --   Internal use only.
522 --
523 -- {End Of Comments}
524 --
525 --
526 FUNCTION chk_timecard_deposit
527         (p_blocks in HXC_BLOCK_TABLE_TYPE
528         ,p_block_number in NUMBER
529         ) return BOOLEAN is
530 
531 l_test_tc_id HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE;
532 
533 l_proc varchar2(72) := g_package||'chk_timceard_deposit';
534 
535 BEGIN
536 
537 --
538 -- Check that this timecard scope building block is still
539 -- active, and has the right scope - it should do since we
540 -- checked elsewhere, but double check.
541 --
542 if (p_blocks(p_block_number).scope = 'TIMECARD') then
543 
544   if (fnd_date.canonical_to_date(p_blocks(p_block_number).date_to) = hr_general.end_of_time) then
545   --
546   -- Run the check
547   --
548     l_test_tc_id := chk_timecard_exists
549           (p_blocks(p_block_number).resource_id
550           ,fnd_date.canonical_to_date(p_blocks(p_block_number).start_time)
551           ,fnd_date.canonical_to_date(p_blocks(p_block_number).stop_time)
552           ,p_blocks(p_block_number).time_building_block_id
553           );
554 
555     if(l_test_tc_id is null) then
559     --
556     --
557     -- No existing timecard, therefore we can
558     -- continue with the deposit
560        RETURN FALSE;
561     else
562     --
563     -- There is another timecard out there that overlaps this
564     -- period.  Now we check whether this timecard is included
565     -- in the blocks that we are depositing as a deleted block
566     -- in which case this is ok, otherwise, we must stop
567     -- submission.
568     --
569        if(timecard_deleted
570         (p_blocks
571         ,l_test_tc_id
572         )) then
573        --
574        -- We are deleting the existing timecard as part of this
575        -- submission.  This is ok, and submission can continue.
576        --
577        RETURN FALSE;
578 
579        else
580        --
581        -- We aren't deleting the existing timecard
582        -- as part of this submission.  Abort this
583        -- deposit.
584        --
585       RETURN TRUE;
586 
587        end if;
588 
589     end if;
590 
591   end if; -- is the end date the end of time?
592 
593 end if; -- Is this a timecard scope block?
594 
595 --
596 -- If we get here, then we should deposit this block!
597 --
598 
599 RETURN FALSE;
600 
601 END chk_timecard_deposit;
602 --
603 -- Overloaded version for calling from deposit wrapper
604 --
605 FUNCTION chk_timecard_deposit
606         (p_blocks in hxc_self_service_time_deposit.timecard_info
607         ,p_block_number in NUMBER
608         ) return BOOLEAN is
609 
610 l_test_tc_id HXC_TIME_BUILDING_BLOCKS.TIME_BUILDING_BLOCK_ID%TYPE;
611 
612 BEGIN
613 
614 --
615 -- Check that this timecard scope building block is still
616 -- active, and has the right scope - it should do since we
617 -- checked elsewhere, but double check.
618 --
619 if (p_blocks(p_block_number).scope = 'TIMECARD') then
620 
621   if (p_blocks(p_block_number).date_to = hr_general.end_of_time) then
622   --
623   -- Run the check
624   --
625     l_test_tc_id := chk_timecard_exists
626           (p_blocks(p_block_number).resource_id
627           ,p_blocks(p_block_number).start_time
628           ,p_blocks(p_block_number).stop_time
629           ,p_blocks(p_block_number).time_building_block_id
630           );
631 
632     if(l_test_tc_id is null) then
633     --
634     -- No existing timecard, therefore we can
635     -- continue with the deposit
636     --
637        RETURN FALSE;
638     else
639     --
640     -- There is another timecard out there that overlaps this
641     -- period.  Now we check whether this timecard is included
642     -- in the blocks that we are depositing as a deleted block
643     -- in which case this is ok, otherwise, we must stop
647         (p_blocks
644     -- submission.
645     --
646        if(timecard_deleted
648         ,l_test_tc_id
649         )) then
650        --
651        -- We are deleting the existing timecard as part of this
652        -- submission.  This is ok, and submission can continue.
653        --
654        RETURN FALSE;
655 
656        else
657        --
658        -- We aren't deleting the existing timecard
659        -- as part of this submission.  Abort this
660        -- deposit.
661        --
662       RETURN TRUE;
663 
664        end if;
665 
666     end if;
667 
668   end if; -- is the end date the end of time?
669 
670 end if; -- Is this a timecard scope block?
671 
672 --
673 -- If we get here, then we should deposit this block!
674 --
675 
676 RETURN FALSE;
677 
678 END chk_timecard_deposit;
679 
680 Function inactive_detail
681        (p_dates in asg_info
682        ,p_date  in date
683        ) return BOOLEAN is
684 
685 l_inactive  boolean := true;
686 l_index     number;
687 
688 Begin
689 
690 l_index := p_dates.first;
691 Loop
692   Exit when ((NOT p_dates.exists(l_index)) OR (NOT l_inactive));
693 
694   if(p_date between p_dates(l_index).start_date and p_dates(l_index).end_date) then
695 
696     l_inactive := false;
697 
698   end if;
699 
700   l_index := p_dates.next(l_index);
701 End Loop;
702 
703 return l_inactive;
704 
705 End inactive_detail;
706 
707 Procedure check_start_stop_time
708         (p_blocks       	in         hxc_block_table_type
709         ,p_details      	in         hxc_timecard.block_list
710         ,p_messages     	in out nocopy hxc_message_table_type
711         ,p_validate_on_save  in 	      hxc_pref_hierarchies.attribute1%type
712         ) is
713 l_index       number;
714 
715 BEGIN
716 
717 l_index := p_details.first;
718 Loop
719   Exit When Not p_details.exists(l_index);
720   if(hxc_timecard_block_utils.is_active_block(p_blocks(p_details(l_index)))) then
721 
722       IF p_blocks(p_details(l_index)).start_time is not null and
723       p_blocks(p_details(l_index)).stop_time is null  and
724 	 (p_blocks(p_details(l_index)).approval_status = hxc_timecard.c_submitted_status
725 	 or
726 	  p_validate_on_save = hxc_timecard.c_yes
727 	  )
728 	  THEN
729 
730        hxc_timecard_message_helper.addErrorToCollection
731      (p_messages => p_messages
732      ,p_message_name => 'HXC_NULL_STOP_SUBMIT'
733      ,p_message_tokens => NULL
734      ,p_message_level => hxc_timecard.c_error
735      ,p_message_field => NULL
736      ,p_application_short_name => hxc_timecard.c_hxc
737      ,p_time_building_block_id => p_blocks(p_details(l_index)).time_building_block_id
738      ,p_time_building_block_ovn => NULL
739      ,p_time_attribute_id => NULL
740      ,p_time_attribute_ovn => NULL
741      );
742       END IF;
743   end if; -- is this an active detail
744   l_index := p_details.next(l_index);
745 End Loop;
746 
747 END check_start_stop_time;
748 
749 
750 Procedure find_detail_date_extremes
751         (p_blocks       in         hxc_block_table_type
752         ,p_days      in         hxc_timecard.block_list
753         ,p_details      in         hxc_timecard.block_list
754         ,p_early_detail in out nocopy date
755         ,p_late_detail  in out nocopy date
756         ) is
757 l_index       number;
758 l_detail_date date;
759 
760 Begin
761 
762 l_index := p_details.first;
763 
764 Loop
765   Exit When Not p_details.exists(l_index);
766   if(hxc_timecard_block_utils.is_active_block(p_blocks(p_details(l_index)))) then
767     l_detail_date := trunc(
768                  hxc_timecard_block_utils.date_value(
769                 p_blocks(
770                   p_days(
771                     p_blocks(p_details(l_index)).parent_building_block_id
772                       )
773                       ).start_time
774                  ));
775 
776     if(l_detail_date < p_early_detail) then
777       p_early_detail := l_detail_date;
778     end if;
779     if(l_detail_date > p_late_detail) then
780       p_late_detail := l_detail_date;
781     end if;
782   end if; -- is this an active detail
783   l_index := p_details.next(l_index);
784 End Loop;
785 
789        (p_blocks     in         hxc_block_table_type
786 End find_detail_date_extremes;
787 
788 Procedure chk_inactive_details
790        ,p_props      in         hxc_timecard_prop_table_type
791        ,p_days       in         hxc_timecard.block_list
792        ,p_details    in         hxc_timecard.block_list
793        ,p_block_idxs    out nocopy block_list
794        ) is
795 
796 l_early_detail  date := hr_general.end_of_time;
797 l_late_detail   date := hr_general.start_of_time;
798 l_detail_date   date;
799 l_asg_info      asg_info;
800 l_index      number;
801 l_block_index   number;
802 
803 l_all_active    boolean;
804 
805 l_proc       varchar2(70) := g_package||'chk_inactive_details';
806 
807 Begin
808 --
809 -- Calculate earliest and latest detail dates
810 --
811 
812 find_detail_date_extremes
813  (p_blocks       => p_blocks
814  ,p_days      => p_days
815  ,p_details      => p_details
816  ,p_early_detail => l_early_detail
817  ,p_late_detail  => l_late_detail
818  );
819 
820 --
821 -- So 99% Case, check to see if the earliest detail
822 -- and latest detail lie within an active assignment
823 -- period.  Loop over the
824 --
825 
826 l_all_active := false;
827 
828 l_index := p_props.first;
829 
830 Loop
831   Exit When ((Not p_props.exists(l_index)) or l_all_active);
832 
833   if(p_props(l_index).property_name = 'ResourceAssignmentId') then
834     --
835     -- Check to see if the details are contained within this assignment
836     --
837     if((p_props(l_index).date_from <= l_early_detail)
838      AND
839       (p_props(l_index).date_to >= l_late_detail)) then
840 
841       l_all_active := true;
842 
843     end if;
844     --
845     -- Keep a record of the dates, in case we need to do the other
846     -- check
847     --
848     l_asg_info(l_index).start_date := p_props(l_index).date_from;
849     l_asg_info(l_index).end_date := p_props(l_index).date_to;
850 
851   end if;
852 
853   l_index := p_props.next(l_index);
854 End Loop;
855 
856 if(NOT l_all_active) then
857 --
858 -- Ok, not all the details corresponded to one
859 -- active assignment.  Now look across
860 -- assignments.  This is much less likely.
861 --
862 l_all_active := true;
863 
864 l_block_index := p_details.first;
865 
866 Loop
867   Exit When Not p_details.exists(l_block_index);
868   if(hxc_timecard_block_utils.is_active_block(p_blocks(p_details(l_block_index)))) then
869     l_detail_date := trunc(
870                hxc_timecard_block_utils.date_value(
871                  p_blocks(
872                 p_days(
873                   p_blocks(p_details(l_block_index)).parent_building_block_id
874                     )
875                     ).start_time
879 
876                ));
877 
878     if(inactive_detail(l_asg_info,l_detail_date)) then
880       l_all_active := false;
881       p_block_idxs(l_block_index) := l_block_index;
882 
883     end if;
884   end if;
885 
886   l_block_index := p_details.next(l_block_index);
887 End Loop;
888 
889 end if;
890 
891 End chk_inactive_details;
892 
893 --
894 -- ----------------------------------------------------------------------------
895 -- |---------------------------< perform_checks >-----------------------------|
896 -- ----------------------------------------------------------------------------
897 -- {Start Of Comments}
898 --
899 -- Description:
900 --   This procedure performs all the basic checks on the timecard information
901 -- pre-deposit.
902 --
903 -- Prerequisites:
904 --   Middle tier has sent some blocks, attributes.  I.e. we've passed
905 -- check inputs.
906 --
907 -- In Parameters:
908 --   Name                  Reqd Type     Description
909 --   p_blocks                 Yes  BLOCKS   The blocks to deposit
910 --   p_atttributes            Yes  ATTRS    The attributes to deposit
911 --   p_messages               Yes  MESSAGES The application messages
912 --
913 -- Access Status:
914 --   Internal use only.
915 --
916 -- {End Of Comments}
917 --
918 --
919 PROCEDURE perform_checks
920         (p_blocks      in         hxc_block_table_type
921         ,p_attributes     in         hxc_attribute_table_type
922         ,p_timecard_props in         hxc_timecard_prop_table_type
923         ,p_days        in         hxc_timecard.block_list
924         ,p_details     in         hxc_timecard.block_list
925         ,p_messages       in out nocopy hxc_message_table_type
926         ) IS
927 
928 l_tc_index NUMBER;
929 l_index    NUMBER;
930 l_idx      NUMBER;
931 
932 l_inactive_detail_id  hxc_time_building_blocks.time_building_block_id%type;
933 l_inactive_detail_ovn hxc_time_building_blocks.object_version_number%type;
934 l_block_idxs       block_list;
935 
936 l_proc     varchar2(72) := g_package||'perform_checks';
937 
938 l_validate_on_save    hxc_pref_hierarchies.attribute1%type := hxc_timecard.c_no;
939 
940 
941 BEGIN
942 
943 --
944 -- First find the "active" timecard scope building block
945 -- index.
946 --
947 
948 l_tc_index := hxc_timecard_block_utils.find_active_timecard_index
949           (p_blocks => p_blocks);
950 
951 
952 l_validate_on_save := hxc_timecard_properties.find_property_value
953                 (p_timecard_props
954                 ,'TsPerValidateOnSaveValidateOnSave'
955                 ,null
956                 ,null
957                 ,fnd_date.canonical_to_date(p_blocks(l_tc_index).start_time)
958                 ,fnd_date.canonical_to_date(p_blocks(l_tc_index).stop_time)
959                 );
960 
961 
962 --
963 -- 1. Check that we're allowed to deposit this timecard
964 --
965 
966   if (chk_timecard_deposit
967        (p_blocks
968        ,l_tc_index
969        )
970      ) then
971      --
972      -- There is an existing timecard, stop processing.
973      --
974      hxc_timecard_message_helper.addErrorToCollection
975       (p_messages
976       ,'HXC_366333_TIMECARD_EXISTS'
977       ,hxc_timecard.c_error
978       ,null
979       ,null
980       ,hxc_timecard.c_hxc
981       ,null
982       ,null
983       ,null
984       ,null
985       );
986 
987   end if;
988 
989 --
990 -- 2. Check that all the details have start_time and stop_time in submission
991 --
992     check_start_stop_time
993      (p_blocks       		=> p_blocks
994      ,p_details      		=> p_details
995      ,p_messages    		=> p_messages
996      ,p_validate_on_save 	=> l_validate_on_save
997      );
998 
999 --
1000 -- 3. Check that all the details lie within a valid primary
1001 -- assignment range.
1002 --
1003 
1004   chk_inactive_details(p_blocks,p_timecard_props,p_days,p_details,l_block_idxs);
1005 
1006   if(l_block_idxs.count > 0) then
1007 
1008      l_idx := l_block_idxs.first;
1009      Loop
1010        Exit When not l_block_idxs.exists(l_idx);
1011 
1012        hxc_timecard_message_helper.addErrorToCollection
1013      (p_messages
1014      ,'HXC_DETAIL_NON_ACTIVE'
1015      ,hxc_timecard.c_error
1016      ,null
1017      ,null
1018      ,hxc_timecard.c_hxc
1019      ,p_blocks(p_details(l_idx)).time_building_block_id
1020      ,p_blocks(p_details(l_idx)).object_version_number
1021      ,null
1022      ,null
1023      );
1024        l_idx := l_block_idxs.next(l_idx);
1025      End Loop;
1026 
1027   end if;
1028 
1029 END perform_checks;
1030 
1031 Function prohibitedAttributeChange
1032         (p_block      in hxc_block_type,
1033          p_attributes in hxc_attribute_table_type)
1034    Return Boolean is
1035 
1039       where time_attribute_id = p_id;
1036    cursor c_old_attribute(p_id in hxc_time_attributes.time_attribute_id%type) is
1037      select *
1038        from hxc_time_attributes
1040 
1041    l_old_attribute c_old_attribute%rowtype;
1042 
1043    l_prohibited boolean;
1044    l_index pls_integer;
1045 
1046 Begin
1047 
1048    l_prohibited := false;
1049    l_index := p_attributes.first;
1050    Loop
1051       Exit when not p_attributes.exists(l_index);
1052 
1053 
1054       Exit when (
1055             (not p_attributes.exists(l_index))
1056            OR
1057             (l_prohibited)
1058            );
1059       if(p_attributes(l_index).building_block_id = p_block.time_building_block_id) then
1060 
1061       open c_old_attribute(p_attributes(l_index).time_attribute_id);
1062       fetch c_old_attribute into l_old_attribute;
1063       close c_old_attribute;
1064 
1065       if(l_old_attribute.time_attribute_id is null) then
1066          -- A new attribute.  Not allowed.
1067          l_prohibited := true;
1068       else
1069          -- Check for changes.
1070          if(l_old_attribute.attribute_category <> p_attributes(l_index).attribute_category) then
1071             l_prohibited := true;
1072          elsif(nvl(l_old_attribute.attribute1,'A') <> nvl(p_attributes(l_index).attribute1,'A')) then
1073             l_prohibited := true;
1074          elsif(nvl(l_old_attribute.attribute2,'A') <> nvl(p_attributes(l_index).attribute2,'A')) then
1075             l_prohibited := true;
1076          elsif(nvl(l_old_attribute.attribute3,'A') <> nvl(p_attributes(l_index).attribute3,'A')) then
1077             l_prohibited := true;
1078          elsif(nvl(l_old_attribute.attribute4,'A') <> nvl(p_attributes(l_index).attribute4,'A')) then
1079             l_prohibited := true;
1080          elsif(nvl(l_old_attribute.attribute5,'A') <> nvl(p_attributes(l_index).attribute5,'A')) then
1081             l_prohibited := true;
1082          elsif(nvl(l_old_attribute.attribute6,'A') <> nvl(p_attributes(l_index).attribute6,'A')) then
1083             l_prohibited := true;
1084          elsif(nvl(l_old_attribute.attribute7,'A') <> nvl(p_attributes(l_index).attribute7,'A')) then
1085             l_prohibited := true;
1086          elsif(nvl(l_old_attribute.attribute8,'A') <> nvl(p_attributes(l_index).attribute8,'A')) then
1087             l_prohibited := true;
1088          elsif(nvl(l_old_attribute.attribute9,'A') <> nvl(p_attributes(l_index).attribute9,'A')) then
1089             l_prohibited := true;
1090          elsif(nvl(l_old_attribute.attribute10,'A') <> nvl(p_attributes(l_index).attribute10,'A')) then
1091             l_prohibited := true;
1092          elsif(nvl(l_old_attribute.attribute11,'A') <> nvl(p_attributes(l_index).attribute11,'A')) then
1093             l_prohibited := true;
1094          elsif(nvl(l_old_attribute.attribute12,'A') <> nvl(p_attributes(l_index).attribute12,'A')) then
1098          elsif(nvl(l_old_attribute.attribute14,'A') <> nvl(p_attributes(l_index).attribute14,'A')) then
1095             l_prohibited := true;
1096          elsif(nvl(l_old_attribute.attribute13,'A') <> nvl(p_attributes(l_index).attribute13,'A')) then
1097             l_prohibited := true;
1099             l_prohibited := true;
1100          elsif(nvl(l_old_attribute.attribute15,'A') <> nvl(p_attributes(l_index).attribute15,'A')) then
1101             l_prohibited := true;
1102          elsif(nvl(l_old_attribute.attribute16,'A') <> nvl(p_attributes(l_index).attribute16,'A')) then
1103             l_prohibited := true;
1104          elsif(nvl(l_old_attribute.attribute17,'A') <> nvl(p_attributes(l_index).attribute17,'A')) then
1105             l_prohibited := true;
1106          elsif(nvl(l_old_attribute.attribute18,'A') <> nvl(p_attributes(l_index).attribute18,'A')) then
1107             l_prohibited := true;
1108          elsif(nvl(l_old_attribute.attribute19,'A') <> nvl(p_attributes(l_index).attribute19,'A')) then
1109             l_prohibited := true;
1110          elsif(nvl(l_old_attribute.attribute20,'A') <> nvl(p_attributes(l_index).attribute20,'A')) then
1111             l_prohibited := true;
1112          elsif(nvl(l_old_attribute.attribute21,'A') <> nvl(p_attributes(l_index).attribute21,'A')) then
1113             l_prohibited := true;
1114          elsif(nvl(l_old_attribute.attribute22,'A') <> nvl(p_attributes(l_index).attribute22,'A')) then
1115             l_prohibited := true;
1116          elsif(nvl(l_old_attribute.attribute23,'A') <> nvl(p_attributes(l_index).attribute23,'A')) then
1117             l_prohibited := true;
1118          elsif(nvl(l_old_attribute.attribute24,'A') <> nvl(p_attributes(l_index).attribute24,'A')) then
1119             l_prohibited := true;
1120          elsif(nvl(l_old_attribute.attribute25,'A') <> nvl(p_attributes(l_index).attribute25,'A')) then
1121             l_prohibited := true;
1122          elsif(nvl(l_old_attribute.attribute26,'A') <> nvl(p_attributes(l_index).attribute26,'A')) then
1123             l_prohibited := true;
1124          elsif(nvl(l_old_attribute.attribute27,'A') <> nvl(p_attributes(l_index).attribute27,'A')) then
1125             l_prohibited := true;
1126          elsif(nvl(l_old_attribute.attribute28,'A') <> nvl(p_attributes(l_index).attribute28,'A')) then
1127             l_prohibited := true;
1128          elsif(nvl(l_old_attribute.attribute29,'A') <> nvl(p_attributes(l_index).attribute29,'A')) then
1129             l_prohibited := true;
1130          elsif(nvl(l_old_attribute.attribute30,'A') <> nvl(p_attributes(l_index).attribute30,'A')) then
1131             l_prohibited := true;
1132          end if;
1133       end if;
1134       end if;
1135       l_index := p_attributes.next(l_index);
1136    End Loop;
1137 
1138    return l_prohibited;
1139 
1140 End prohibitedAttributeChange;
1141 
1142 Function prohibitedBlockChange
1143            (p_block      in hxc_block_type,
1144             p_attributes in hxc_attribute_table_type)
1145    Return Boolean is
1146 
1147    cursor c_old_block
1148             (p_id in hxc_time_building_blocks.time_building_block_id%type,
1149              p_ovn in hxc_time_building_blocks.object_version_number%type) is
1150      select *
1151        from hxc_time_building_blocks
1152       where time_building_block_id = p_id
1153         and object_version_number = p_ovn;
1154 
1155    l_old_block c_old_block%rowtype;
1156    l_prohibited boolean;
1157 
1158 Begin
1159    if(p_block.process = 'N') then
1160      l_prohibited := false;
1161    else
1162       open c_old_block
1163              (p_block.time_building_block_id,
1164               p_block.object_version_number);
1165       fetch c_old_block into l_old_block;
1166       close c_old_block;
1167 
1168       if(l_old_block.time_building_block_id is null) then
1169          -- How did we get here, must be a new block!
1170          l_prohibited := false;
1171       else
1172          -- Check all user updateable attributes, except
1173          -- approval style id, which Santos do not want
1174          -- included in this check.
1175          if(l_old_block.TYPE <> p_block.TYPE) then
1176             l_prohibited := true;
1177          else
1178             if(round(l_old_block.MEASURE,3) <> round(p_block.MEASURE,3)) then
1179                l_prohibited := true;
1180             else
1181                if(l_old_block.UNIT_OF_MEASURE <> p_block.UNIT_OF_MEASURE) then
1182                   l_prohibited := true;
1183                else
1184                   if(l_old_block.START_TIME <> fnd_date.canonical_to_date(p_block.START_TIME)) then
1185                      l_prohibited := true;
1186                   else
1187                      if(l_old_block.STOP_TIME <> fnd_date.canonical_to_date(p_block.STOP_TIME)) then
1188                         l_prohibited := true;
1189                      else
1190                         if(l_old_block.APPROVAL_STATUS <> p_block.APPROVAL_STATUS) then
1191                            l_prohibited := true;
1192                         else
1193                            if(l_old_block.DATE_TO <> fnd_date.canonical_to_date(p_block.DATE_TO)) then
1194                               l_prohibited := true;
1195                            else
1196                               if(nvl(l_old_block.COMMENT_TEXT,'COMMENT') <> nvl(p_block.COMMENT_TEXT,'COMMENT')) then
1197                                  l_prohibited := true;
1198                                  --
1199                                  -- Ok, all the block attributes are the same
1200                                  -- Are the attributes the same?
1201                                else
1205                                    l_prohibited := false;
1202                                  if(prohibitedAttributeChange(p_block,p_attributes)) then
1203                                    l_prohibited := true;
1204                                  else
1206                                  end if;
1207                               end if;
1208                            end if;
1209                         end if;
1210                      end if;
1211                   end if;
1212                end if;
1213             end if;
1214          end if;
1215       end if;
1216    end if;
1217 
1218    return l_prohibited;
1219 
1220 End prohibitedBlockChange;
1221 
1222 Function never_locked
1223        (p_timecard_props in hxc_timecard_prop_table_type
1224        ,p_early_date     in date
1225        ,p_late_date      in date
1226        ) return boolean is
1227 
1228 l_index     number;
1229 l_found     boolean := false;
1230 l_day_found    boolean := false;
1231 l_detail_found boolean := false;
1232 l_day       boolean := false;
1233 l_detail       boolean := false;
1234 l_result       boolean := false;
1235 l_proc      varchar2(30) := 'never_locked';
1236 Begin
1237 
1238 
1239 l_index := p_timecard_props.first;
1240 Loop
1241   Exit when ((not p_timecard_props.exists(l_index)) or (l_found));
1242 
1243   if(p_timecard_props(l_index).property_name = 'TcWTcrdStAlwEditsModifyApprovedTcDetails') then
1244     if(p_timecard_props(l_index).date_from < p_early_date) then
1245       if(p_timecard_props(l_index).date_to > p_late_date) then
1246      l_detail_found := true;
1247      if((p_timecard_props(l_index).property_value <> 'N') OR (p_timecard_props(l_index).property_value is null))then
1248        l_detail := true;
1249      end if;
1250       end if;
1251     end if;
1252   end if;
1253 
1254   if(p_timecard_props(l_index).property_name = 'TcWTcrdStAlwEditsModifyApprovedTcDays') then
1255     if(p_timecard_props(l_index).date_from < p_early_date) then
1256       if(p_timecard_props(l_index).date_to > p_late_date) then
1257      l_day_found := true;
1258      if((p_timecard_props(l_index).property_value <> 'N') OR (p_timecard_props(l_index).property_value is null))then
1259        l_day := true;
1260      end if;
1261       end if;
1262     end if;
1263   end if;
1264 
1265   if(l_day_found) AND (l_detail_found) then
1266     l_found := true;
1267     if(l_day) and (l_detail) then
1268       l_result := true;
1269     end if;
1270   end if;
1271 
1272   l_index := p_timecard_props.next(l_index);
1273 End Loop;
1274 
1275 --
1276 -- 115.6 Change: Bug 2888528
1277 --
1278 
1279 if(not l_found) then
1280 
1281   if((l_day_found) AND (NOT l_day)) then
1282     l_result := false;
1283   elsif((l_detail_found) AND (NOT l_detail)) then
1284     l_result := false;
1285   else
1286     l_result := true;
1287   end if;
1288 
1289 end if;
1290 
1291 return l_result;
1292 
1293 End never_locked;
1294 
1295 Function find_locking_preference
1296        (p_timecard_props in hxc_timecard_prop_table_type
1297        ,p_date        in date
1298        ,p_preference     in varchar2
1299        ) return varchar2 is
1300 
1301 l_preference varchar2(2) := 'Y';
1302 l_index      number;
1303 l_found      boolean := false;
1304 Begin
1305 
1306 l_index := p_timecard_props.first;
1307 Loop
1308   Exit when ((not p_timecard_props.exists(l_index)) or (l_found));
1309   if(p_preference = 'DAY') then
1310     if(p_timecard_props(l_index).property_name = 'TcWTcrdStAlwEditsModifyApprovedTcDays') then
1311       if(p_date between p_timecard_props(l_index).date_from and p_timecard_props(l_index).date_to) then
1312      l_preference := p_timecard_props(l_index).property_value;
1313      l_found := true;
1314       end if;
1315     end if;
1316   else
1317     if(p_timecard_props(l_index).property_name = 'TcWTcrdStAlwEditsModifyApprovedTcDetails') then
1318       if(p_date between p_timecard_props(l_index).date_from and p_timecard_props(l_index).date_to) then
1319      l_preference := p_timecard_props(l_index).property_value;
1320      l_found := true;
1321       end if;
1322     end if;
1323   end if;
1324   l_index := p_timecard_props.next(l_index);
1325 End Loop;
1326 
1327 return l_preference;
1328 
1329 End find_locking_preference;
1330 
1331 Function day_approved
1332        (p_resource_id    in hxc_time_building_blocks.resource_id%type
1333        ,p_date        in date
1334        ) return boolean is
1335 
1336 cursor c_approved_day
1337      (p_resource_id    in hxc_time_building_blocks.resource_id%type
1338      ,p_date        in date) is
1339   select ap.approval_status
1340     from hxc_time_building_blocks ap, hxc_time_building_blocks tc
1341    where ap.resource_id = p_resource_id
1342      and ap.scope = 'APPLICATION_PERIOD'
1343      and ap.approval_status = 'APPROVED'
1344      and p_date between ap.start_time and ap.stop_time
1345      and ap.resource_id = tc.resource_id
1346      and ap.creation_date >= tc.creation_date
1347      and tc.date_to = hr_general.end_of_time
1348      and tc.scope = 'TIMECARD'
1349      and tc.start_time <= ap.stop_time
1353        from hxc_time_building_blocks
1350      and tc.stop_time >= ap.start_time
1351      and NOT exists
1352      (select 'Y'
1354    where resource_id = p_resource_id
1355      and scope = 'APPLICATION_PERIOD'
1356      and date_to = hr_general.end_of_time
1357      and approval_status = 'REJECTED'
1358      and p_date between start_time and stop_time
1359      );
1360 
1361 l_dummy hxc_time_building_blocks.approval_status%type;
1362 
1363 Begin
1364 
1365 open c_approved_day(p_resource_id,p_date);
1366 fetch c_approved_day into l_dummy;
1367 if(c_approved_day%found) then
1368   close c_approved_day;
1369   return true;
1370 else
1371   close c_approved_day;
1372   return false;
1373 end if;
1374 
1375 End day_approved;
1376 --
1377 -- Added detail_with_day in version 115.115.  This is for the
1378 -- santos locking of approved days functionality.
1379 --
1380 FUNCTION detail_with_day
1381   (p_date IN DATE,
1382    p_resource_id IN hxc_time_building_blocks.resource_id%TYPE
1383    ) RETURN BOOLEAN IS
1384 
1385 CURSOR c_detail_exists
1386   (p_date IN DATE,
1387    p_resource_id IN hxc_time_building_blocks.resource_id%TYPE
1388    ) IS
1389        SELECT 'Y'
1390 	FROM hxc_time_building_blocks detail,
1391 	     hxc_time_building_blocks day,
1392 	     hxc_time_building_blocks parent
1393 	WHERE detail.parent_building_block_id = day.time_building_block_id
1394 	AND detail.parent_building_block_ovn = day.object_version_number
1395 	AND detail.date_to = hr_general.end_of_time
1396 	AND detail.resource_id = p_resource_id
1397 	AND detail.scope = 'DETAIL'
1398 	AND detail.creation_date <=(select max(ap.creation_date)
1399 	    from hxc_time_building_blocks ap
1400 	    where ap.resource_id = p_resource_id
1401 	     and ap.scope = 'APPLICATION_PERIOD'
1402 	     and ap.approval_status = 'APPROVED'
1403 	     and p_date between ap.start_time and ap.stop_time
1404 	     and ap.resource_id = parent.resource_id
1405 	     and ap.creation_date >= parent.creation_date
1406 	     and parent.date_to = hr_general.end_of_time
1407 	     and parent.start_time <= ap.stop_time
1408 	     and parent.stop_time >= ap.start_time)
1409 	AND day.scope = 'DAY'
1410 	AND Trunc(day.start_time) = Trunc(p_date)
1411 	AND day.date_to = hr_general.end_of_time
1412 	AND day.resource_id = p_resource_id
1413      and parent.time_building_block_id=day.parent_building_block_id
1414 	and parent.object_version_number=day.parent_building_block_ovn
1415 	and parent.scope='TIMECARD'
1416 	AND parent.date_to = hr_general.end_of_time
1417 	AND parent.resource_id = p_resource_id;
1418 
1419 l_dummy varchar2(1);
1420 
1421 BEGIN
1422    OPEN c_detail_exists(p_date,p_resource_id);
1423    FETCH c_detail_exists INTO l_dummy;
1424    IF(c_detail_exists%found) THEN
1425       CLOSE c_detail_exists;
1426       RETURN TRUE;
1427     ELSE
1428       CLOSE c_detail_exists;
1429       RETURN FALSE;
1430    END IF;
1431 END detail_with_day;
1432 
1433 Function day_locked
1434        (p_timecard_props in hxc_timecard_prop_table_type
1435        ,p_resource_id    in hxc_time_building_blocks.resource_id%type
1436        ,p_date        in date
1437        ) return boolean is
1438 
1439 l_locked boolean := false;
1440 l_pref   varchar2(2);
1441 
1442 Begin
1443 
1444 l_pref := find_locking_preference
1445         (p_timecard_props
1446         ,p_date
1447         ,'DAY'
1448         );
1449 if(l_pref = 'N') then
1450   if(day_approved(p_resource_id,p_date)) then
1451      IF(detail_with_day(p_date,p_resource_id)) then
1452 	l_locked := true;
1453       ELSE
1454 	l_locked := FALSE;
1455      END IF;
1456   else
1457     l_locked := false;
1458   end if;
1459 else
1460   l_locked := false;
1461 end if;
1462 
1463 return l_locked;
1464 
1465 End day_locked;
1466 
1467    Function detail_locked
1468       (p_timecard_props in hxc_timecard_prop_table_type,
1469        p_resource_id    in hxc_time_building_blocks.resource_id%type,
1470        p_date           in date,
1471        p_detail_id      in hxc_ap_detail_links.time_building_block_id%type,
1472        p_detail_ovn     in hxc_ap_detail_links.time_building_block_ovn%type
1473        ) return boolean is
1474 
1475       cursor c_detail_approved
1476          (p_detail_id in hxc_ap_detail_links.time_building_block_id%type,
1477           p_detail_ovn in hxc_ap_detail_links.time_building_block_ovn%type) is
1478         select 'Y'
1479           from hxc_ap_detail_links adl,
1480                hxc_app_period_summary aps
1481          where adl.time_building_block_id = p_detail_id
1482            and adl.time_building_block_ovn = p_detail_ovn
1483            and adl.application_period_id = aps.application_period_id
1484        and aps.approval_status = hxc_timecard.c_approved_status
1485            and not exists(select 1
1486                             from hxc_ap_detail_links adl2,
1487                                  hxc_app_period_summary aps2
1488                            where adl2.time_building_block_id = adl.time_building_block_id
1489                              and adl2.time_building_block_ovn = adl.time_building_block_ovn
1490                              and adl2.application_period_id <> adl.application_period_id
1494       l_locked boolean := false;
1491                              and adl2.application_period_id = aps2.application_period_id
1492                              and aps2.approval_status <> hxc_timecard.c_approved_status);
1493 
1495       l_pref   varchar2(2);
1496       l_dummy  varchar2(1);
1497 
1498    Begin
1499 
1500       l_pref := find_locking_preference
1501          (p_timecard_props,
1502           p_date,
1503           'DETAIL'
1504           );
1505 
1506       if(l_pref = 'N') then
1507          open c_detail_approved(p_detail_id,p_detail_ovn);
1508          fetch c_detail_approved into l_dummy;
1509          if(c_detail_approved%notfound) then
1510             l_locked := false;
1511          else
1512             l_locked := true;
1513          end if;
1514          close c_detail_approved;
1515       else
1516          l_locked := false;
1517       end if;
1518 
1519       return l_locked;
1520 
1521    End detail_locked;
1522 --
1523 -- ----------------------------------------------------------------------------
1524 -- |----------------------< chk_approved_locked_days >------------------------|
1525 -- ----------------------------------------------------------------------------
1526 -- {Start Of Comments}
1527 --
1528 -- Description:
1529 --   This procedure performs all the basic checks on the timecard information
1530 -- pre-deposit, but once the processing state of the blocks in known.  At the
1531 -- the moment, this is simply the implementation of the Santos-built approval
1532 -- locking of days.
1533 --
1534 -- Prerequisites:
1535 --   Middle tier has sent some blocks, attributes.  I.e. we've passed
1536 -- check inputs.
1537 --
1538 -- In Parameters:
1539 --   Name                  Reqd Type      Description
1540 --   p_blocks                 Yes  BLOCKS    The blocks to deposit
1541 --   p_timecard_props            Yes  PROPS     The preferences
1542 --   p_days                Yes  BlockList The Day building blocks
1543 --   p_details                Yes  Blocklist The detail building blocks
1544 --   p_messages               Yes  MESSAGES  The application messages
1545 --
1546 -- Access Status:
1547 --   Internal use only.
1548 --
1549 -- {End Of Comments}
1550 --
1551 --
1552 PROCEDURE chk_approved_locked_days
1553         (p_blocks      in         hxc_block_table_type,
1554          p_attributes     in         hxc_attribute_table_type
1555         ,p_timecard_props in         hxc_timecard_prop_table_type
1556         ,p_days        in         hxc_timecard.block_list
1557         ,p_details     in         hxc_timecard.block_list
1558         ,p_messages       in out nocopy hxc_message_table_type
1559         ) IS
1563 l_detail_date    date;
1560 
1561 l_modify_days    varchar2(2) := 'N';
1562 l_modify_details varchar2(2) := 'N';
1564 l_detail_index   number;
1565 l_early_detail   date := hr_general.end_of_time;
1566 l_late_detail    date := hr_general.start_of_time;
1567 l_proc        varchar2(72) := g_package||'chk_approved_locked_days';
1568 Begin
1569 
1570 find_detail_date_extremes
1571  (p_blocks       => p_blocks
1572  ,p_days      => p_days
1573  ,p_details      => p_details
1574  ,p_early_detail => l_early_detail
1575  ,p_late_detail  => l_late_detail
1576  );
1577 
1578 if(never_locked(p_timecard_props, l_early_detail, l_late_detail)) then
1579   --
1580   -- No need to check, since the preferences are not set.
1581   --
1582   null;
1583 else
1584   --
1585   -- Check each detail to see if allowed to change.
1586   --
1587   l_detail_index := p_details.first;
1588   Loop
1589     Exit when not p_details.exists(l_detail_index);
1590 
1591     if(((prohibitedBlockChange
1592            (p_blocks(p_details(l_detail_index)),
1593             p_attributes
1594             )
1595          )
1596         OR
1597          (hxc_timecard_block_utils.is_new_block(p_blocks(p_details(l_detail_index)))))
1598       --AND
1599        --(hxc_timecard_block_utils.is_active_block(p_blocks(p_details(l_detail_index))))
1600       )then
1601 
1602       l_detail_date := trunc(hxc_timecard_block_utils.date_value
1603                                (p_blocks(p_days(p_blocks(p_details(l_detail_index)).parent_building_block_id)).start_time
1604                              ));
1605       if(day_locked(p_timecard_props, p_blocks(p_details(l_detail_index)).resource_id,l_detail_date)) then
1606         hxc_timecard_message_helper.addErrorToCollection
1607           (p_messages
1608            ,'HXC_NO_MODIFY_APPROVED_DETAIL'
1609            ,hxc_timecard.c_error
1610            ,null
1611            ,null
1612            ,hxc_timecard.c_hxc
1613            ,p_blocks(p_details(l_detail_index)).time_building_block_id
1614            ,null
1615            ,null
1616            ,null
1617            );
1618       else
1619         if(hxc_timecard_block_utils.is_new_block(p_blocks(p_details(l_detail_index)))) then
1620           --
1621           -- It is ok, this entry is allowed, the day is not locked, and it is a new
1622           -- building block
1623           --
1624           null;
1625         else
1626           if(detail_locked
1627                (p_timecard_props,
1628                 p_blocks(p_details(l_detail_index)).resource_id,
1629                 l_detail_date,
1630                 p_blocks(p_details(l_detail_index)).time_building_block_id,
1631                 p_blocks(p_details(l_detail_index)).object_version_number
1632                 )) then
1633             hxc_timecard_message_helper.addErrorToCollection
1634               (p_messages
1635                ,'HXC_NO_MODIFY_APPROVED_DETAIL'
1636                ,hxc_timecard.c_error
1637                ,null
1638                ,null
1639                ,hxc_timecard.c_hxc
1640                ,p_blocks(p_details(l_detail_index)).time_building_block_id
1641                ,null
1642                ,null
1643                ,null
1644                );
1645           end if;
1646         end if;
1647       end if;
1648     end if; -- is the block new or changed?
1649     l_detail_index := p_details.next(l_detail_index);
1650   End Loop;
1651 end if;
1652 
1653 End chk_approved_locked_days;
1654 --
1655 -- ----------------------------------------------------------------------------
1656 -- |-----------------------< perform_process_checks >-------------------------|
1657 -- ----------------------------------------------------------------------------
1658 -- {Start Of Comments}
1659 --
1660 -- Description:
1661 --       This procedure checks that if the deposit mode is submit, then we're
1662 -- going to process at least one or more block or attribute.  If not, then the
1663 -- approval workflow will not be started, and we should not show the
1664 -- confirmation page to the user.
1665 --
1666 -- Prerequisites:
1667 --   Middle tier has sent some blocks, attributes.  I.e. we've passed
1668 -- check inputs.
1669 --
1670 -- In Parameters:
1671 --   Name                  Reqd Type      Description
1672 --   p_blocks                 Yes  BLOCKS    The blocks to deposit
1673 --   p_atttributes            Yes  ATTRS     The attributes to deposit
1674 --   p_messages               Yes  MESSAGES  The application messages
1675 --
1676 -- Access Status:
1677 --   Internal use only.
1678 --
1679 -- {End Of Comments}
1680 --
1681 --
1682 PROCEDURE chk_some_processing
1683         (p_blocks      in         hxc_block_table_type
1684         ,p_attributes     in         hxc_attribute_table_type
1685         ,p_messages       in out nocopy hxc_message_table_type
1686         ) is
1687 
1688 l_index number;
1689 l_found boolean := false;
1690 
1691 l_proc varchar2(70) := g_package||'chk_some_processing';
1692 
1693 Begin
1694 
1695 l_index := p_blocks.first;
1696 LOOP
1697   Exit When ((Not p_blocks.exists(l_index)) or (l_found));
1698   if(hxc_timecard_block_utils.process_block(p_blocks(l_index))) then
1699     l_found := true;
1700   end if;
1701   l_index := p_blocks.next(l_index);
1702 END LOOP;
1703 
1704 if (not l_found) then
1705   l_index := p_attributes.first;
1706   LOOP
1707     Exit When ((Not p_attributes.exists(l_index)) or (l_found));
1708     if(hxc_timecard_attribute_utils.process_attribute(p_attributes(l_index))) then
1709       l_found := true;
1710     end if;
1711     l_index := p_attributes.next(l_index);
1712   END LOOP;
1713 end if;
1714 
1715 if (not l_found) then
1716   hxc_timecard_message_helper.addErrorToCollection
1717     (p_messages
1718     ,'HXC_TIMECARD_NOT_SUBMITTED'
1719     ,hxc_timecard.c_error
1723     ,null
1720     ,null
1721     ,null
1722     ,hxc_timecard.c_hxc
1724     ,null
1725     ,null
1726     ,null
1727     );
1728 end if;
1729 
1730 End chk_some_processing;
1731 --
1732 -- ----------------------------------------------------------------------------
1733 -- |-----------------------< perform_process_checks >-------------------------|
1734 -- ----------------------------------------------------------------------------
1735 -- {Start Of Comments}
1736 --
1737 -- Description:
1738 --   This procedure performs all the basic checks on the timecard information
1739 -- pre-deposit, but once the processing state of the blocks in known.  At the
1740 -- the moment, this is simply the implementation of the Santos-built approval
1741 -- locking of days.
1742 --
1743 -- Prerequisites:
1744 --   Middle tier has sent some blocks, attributes.  I.e. we've passed
1745 -- check inputs.
1746 --
1747 -- In Parameters:
1748 --   Name                  Reqd Type      Description
1749 --   p_blocks                 Yes  BLOCKS    The blocks to deposit
1750 --   p_atttributes            Yes  ATTRS     The attributes to deposit
1751 --   p_timecard_props            Yes  PROPS     The preferences
1752 --   p_days                Yes  BlockList The Day building blocks
1753 --   p_details                Yes  Blocklist The detail building blocks
1754 --   p_template               Yes  VARCHAR2  Is this a template?
1755 --   p_deposit_mode           Yes  VARCHAR2  The current deposit mode
1756 --   p_messages               Yes  MESSAGES  The application messages
1757 --
1758 -- Access Status:
1759 --   Internal use only.
1760 --
1761 -- {End Of Comments}
1762 --
1763 --
1764 PROCEDURE perform_process_checks
1765         (p_blocks      in         hxc_block_table_type
1766         ,p_attributes     in         hxc_attribute_table_type
1767         ,p_timecard_props in         hxc_timecard_prop_table_type
1768         ,p_days        in         hxc_timecard.block_list
1769         ,p_details     in         hxc_timecard.block_list
1770         ,p_template       in         varchar2
1771         ,p_deposit_mode   in         varchar2
1772         ,p_messages       in out nocopy hxc_message_table_type
1773         ) IS
1774 
1775 l_modify_days    varchar2(2) := 'N';
1776 l_modify_details varchar2(2) := 'N';
1777 l_detail_date    date;
1778 l_detail_index   number;
1779 
1780 Begin
1781 
1782 if(p_template <> 'Y') then
1783 
1784   chk_approved_locked_days
1785    (p_blocks      => p_blocks
1786    ,p_attributes     => p_attributes
1787    ,p_timecard_props => p_timecard_props
1788    ,p_days        => p_days
1789    ,p_details     => p_details
1790    ,p_messages       => p_messages
1791    );
1792 
1793   if(p_deposit_mode = 'SUBMIT') then
1794    chk_some_processing
1795     (p_blocks     => p_blocks
1796     ,p_attributes    => p_attributes
1797     ,p_messages      => p_messages
1798     );
1799   end if;
1800 end if;
1801 
1802 End perform_process_checks;
1803 
1804 END hxc_deposit_checks;