DBA Data[Home] [Help]

PACKAGE BODY: APPS.PA_RELATIONSHIP_UTILS

Source


1 package body PA_RELATIONSHIP_UTILS as
2 /*$Header: PAXRELUB.pls 120.19.12010000.3 2009/06/22 09:11:32 paljain ship $*/
3 
4 -- API name                      : Check_Create_Link_Ok
5 -- Type                          : Private Procedure
6 -- Pre-reqs                      : None
7 -- Return Value                  : S if ok
8 --                                 E if error.
9 -- Parameters
10 --  p_element_version_id_from IN NUMBER
11 --  p_element_version_id_to   IN NUMBER
12 --  x_return_status           OUT VARCHAR2
13 --  x_error_message_code      OUT VARCHAR2
14 --
15 --
16 --  History
17 --
18 --  24-JAN-02   HSIU             -Modified
19 --                                  Added logic for linking within project from
20 --                                  costing to workplan structure in
21 --                                  check_create_link_ok api.
22 --  19-DEC-01   HSIU             -Modified
23 --                                  Sutask is always created if task can be created.
24 --  25-JUN-01   HSIU             -Created
25 --
26 --
27 
28 
29   procedure Check_Create_Link_Ok
30   (
31     p_element_version_id_from IN NUMBER
32    ,p_element_version_id_to   IN NUMBER
33    ,x_return_status           OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
34    ,x_error_message_code      OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
35   )
36   IS
37     l_create_new_task VARCHAR2(1);
38     l_dummy           VARCHAR2(1);
39     l_err_code        NUMBER        := 0;
40     l_err_stack       VARCHAR2(630);
41     l_err_stage       VARCHAR2(80);
42     l_element_id      NUMBER;
43     l_object_type     VARCHAR2(30);
44 
45     l_project_id_from NUMBER;
46     l_project_id_to   NUMBER;
47 
48     cursor Get_Element_Id(c_element_version_id NUMBER) IS
49       select proj_element_id, object_type
50         from pa_proj_element_versions
51        where element_version_id = c_element_version_id;
52 
53     cursor Is_linked(c_element_version_id NUMBER) IS
54       select '1'
55         from pa_object_relationships
56        where object_id_from1 = c_element_version_id
57          and object_type_from = 'PA_TASKS'
58          and relationship_type = 'L';
59 
60     cursor Is_structure(c_element_version_id NUMBER) IS
61       select '1'
62         from pa_object_relationships
63        where object_id_from1 = c_element_version_id
64          and object_type_from = 'PA_STRUCTURES';
65 
66     cursor Get_Struc_Ver_Id(c_element_version_id NUMBER) IS
67       select parent_structure_version_id, project_id
68         from pa_proj_element_versions
69        where element_version_id = c_element_version_id;
70     l_from_struc_ver_id           NUMBER;
71 
72     cursor Check_PA_TASKS_Exists(c_task_id NUMBER) IS
73       select '1'
74         from PA_TASKS
75        where task_id = c_task_id;
76 
77     cursor Is_Same_Struc(c_elem_ver_from NUMBER, c_elem_ver_to NUMBER) IS
78       select '1'
79         from pa_proj_elements pe1,
80              pa_proj_element_versions pev1a,
81              pa_proj_element_versions pev1b,
82              pa_proj_element_versions pev2a,
83              pa_proj_element_versions pev2b
84        where pev1b.element_version_id = c_elem_ver_from
85          and pev1b.parent_structure_version_id = pev1a.element_version_id
86          and pev1a.proj_element_id = pe1.proj_element_id
87          and pev2b.element_version_id = c_elem_ver_to
88          and pev2b.parent_structure_version_id = pev2a.element_version_id
89          and pev2a.proj_element_id = pe1.proj_element_id;
90 
91 /* Bug 2680486 -- Performance changes -- Commented the following cursor definition. Restructured it to
92                                         avoid  Non-mergable view issue and use EXISTS rather than IN */
93 
94 /*    cursor Is_Diff_Version_Linked(c_elem_ver_from NUMBER, c_elem_ver_to NUMBER) IS
95       select '1'
96         from pa_proj_elements pe1,
97              pa_proj_element_versions pev1a,
98              pa_proj_element_versions pev1b,
99              pa_object_relationships r
100        where pev1a.element_version_id = c_elem_ver_from
101          and pev1a.proj_element_id = pe1.proj_element_id
102          and pe1.project_id = pev1b.project_id
103          and pe1.proj_element_id = pev1b.proj_element_id
104          and pev1b.element_version_id = r.object_id_to1
105          and r.object_id_from1 IN
106        (select pev2b.element_version_id
107           from pa_proj_elements pe2,
108                pa_proj_element_versions pev2a,
109                pa_proj_element_versions pev2b
110          where pev2a.element_version_id = c_elem_ver_to
111            and pev2a.proj_element_id = pe2.proj_element_id
112            and pe2.project_id = pev2b.project_id
113            and pe2.proj_element_id = pev2b.proj_element_id);
114 */
115 
116     cursor Is_Diff_Version_Linked(c_elem_ver_from NUMBER, c_elem_ver_to NUMBER) IS
117       select '1'
118         from pa_proj_elements pe1,
119              pa_proj_element_versions pev1a,
120              pa_proj_element_versions pev1b,
121              pa_object_relationships r
122        where pev1a.element_version_id = c_elem_ver_from
123          and pev1a.proj_element_id = pe1.proj_element_id
124          and pe1.project_id = pev1b.project_id
125          and pe1.proj_element_id = pev1b.proj_element_id
126          and pev1b.element_version_id = r.object_id_to1
127          and EXISTS
128        (select pev2b.element_version_id
129           from pa_proj_elements pe2,
130                pa_proj_element_versions pev2a,
131                pa_proj_element_versions pev2b
132          where pev2a.element_version_id = c_elem_ver_to
133            and pev2a.proj_element_id = pe2.proj_element_id
134            and pe2.project_id = pev2b.project_id
135            and pe2.proj_element_id = pev2b.proj_element_id
136        and r.object_id_from1 = pev2b.element_version_id);
137 
138     cursor Is_Circular_Link(c_from NUMBER, c_to NUMBER) IS
139       select '1'
140         from pa_proj_element_versions a,
141              pa_proj_element_versions b
142        where a.element_version_id = c_from
143          and a.proj_element_id = b.proj_element_id
144          and a.project_id = b.project_id
145          and b.element_version_id IN (
146              select object_id_to1
147                from pa_object_relationships
148               start with object_id_from1 IN (
149                     select b.element_version_id
150                       from pa_proj_element_versions a,
151                            pa_proj_element_versions b
152                      where a.element_version_id = c_to
153                        and a.proj_element_id = b.proj_element_id
154                        and a.project_id = b.project_id
155                           )
156                 and object_type_from IN ('PA_TASKS','PA_STRUCTURES')
157                 and object_type_to IN ('PA_TASKS','PA_STRUCTURES')
158                 and relationship_type IN ('S','L')
159          connect by prior object_id_to1 = object_id_from1
160                 and object_type_from IN ('PA_TASKS','PA_STRUCTURES')
161                 and prior object_type_to IN ('PA_TASKS','PA_STRUCTURES')
162                 and prior relationship_type IN ('S','L')
163              );
164 
165 
166     cursor Get_Top_Nodes(c_element_version_id NUMBER) IS
167       select a.object_id_from1
168         from pa_object_relationships a
169        where NOT EXISTS (select '1' from pa_object_relationships b
170                                    where b.object_id_to1 = a.object_id_from1)
171        start with a.object_id_to1 = c_element_version_id
172               and a.object_type_to IN ('PA_STRUCTURES','PA_TASKS')
173        connect by prior a.object_id_from1 = a.object_id_to1
174               and a.relationship_type IN ('S','L')
175        union
176       select a.object_id_from1
177         from pa_object_relationships a
178        where a.object_id_from1 = c_element_version_id
179          and object_type_from IN ('PA_STRUCTURES', 'PA_TASKS')
180          and relationship_type = 'S';
181     l_top_node_id         NUMBER;
182 
183     cursor Is_Version_Exist(c_top_node_id NUMBER, c_linking_node_id NUMBER) IS
184       select object_id_to1
185         from pa_object_relationships
186        where relationship_type IN ('S', 'L')
187        start with object_id_from1 = c_top_node_id
188               and object_type_from IN ('PA_STRUCTURES','PA_TASKS')
189        connect by object_id_from1 = prior object_id_to1
190               and relationship_type IN ('L','S')
191       intersect
192       (
193         select pev1b.element_version_id
194           from pa_proj_element_versions pev1b,
195                pa_proj_elements pe1,
196                pa_proj_element_versions pev1a
197          where pev1b.project_id = pe1.project_id
198            and pev1b.proj_element_id = pe1.proj_element_id
199            and pev1a.proj_element_id = pe1.proj_element_id
200            and pev1a.element_version_id IN
201          ( select object_id_to1
202              from pa_object_relationships
203             where relationship_type IN ('S','L')
204             start with object_id_from1 = c_linking_node_id
205                    and object_type_from IN ('PA_STRUCTURES','PA_TASKS')
206             connect by object_id_from1 = prior object_id_to1
207                    and relationship_type IN('L','S')
208 --           UNION
209 --           select object_id_from1
210 --             from pa_object_relationships
211 --            where relationship_type IN ('S','L')
212 --            start with object_id_to1 = c_linking_node_id
213 --                   and object_type_to IN ('PA_STRUCTURES','PA_TASKS')
214 --            connect by prior object_id_from1 = object_id_to1
215 --                   and relationship_type IN ('S','L')
216            UNION
217            select element_version_id
218              from pa_proj_element_versions
219             where element_version_id = c_linking_node_id
220          )
221       );
222     l_existing_elem_ver_id         NUMBER;
223 
224     l_struc_ver_id_from            NUMBER;
225     l_struc_ver_id_to              NUMBER;
226 
227     l_workplan_from                VARCHAR2(1);
228     l_workplan_to                  VARCHAR2(1);
229     l_financial_from                 VARCHAR2(1);
230     l_financial_to                   VARCHAR2(1);
231   BEGIN
232     x_return_status := FND_API.G_RET_STS_SUCCESS;
233 
234     --1 Check if need to create new task.
235 
236     --1a. check if link exist for this task
237     --    if yes, error.
238 --    If (x_return_status = FND_API.G_RET_STS_SUCCESS) THEN
239       OPEN Is_linked(p_element_version_id_from);
240       FETCH Is_linked into l_dummy;
241       IF Is_linked%FOUND THEN
242         x_return_status := FND_API.G_RET_STS_ERROR;
243         x_error_message_code := 'PA_PS_LINK_EXISTS';
244         CLOSE Is_linked;
245         return;
246       END IF;
247       CLOSE Is_linked;
248 --    END IF;
249 
250     --Removed, since subtask is always created now.
251     --1b. check if the from element version is a structure
252     --    if yes, create new task.
253 --    IF (x_return_status = FND_API.G_RET_STS_SUCCESS) THEN
254 --      OPEN Is_structure(p_element_version_id_from);
255 --      FETCH Is_structure into l_dummy;
256 --      IF Is_structure%FOUND THEN
257 --        x_return_status := 'T';
258 --      END IF;
259 --      CLOSE Is_structure;
260 --    END IF;
261 
262 --    IF (x_return_status = FND_API.G_RET_STS_SUCCESS) THEN
263       --1c. check if from object is lowest task.
264       --    if no, create new task.
265 
266 --      IF (PA_PROJ_ELEMENTS_UTILS.IS_LOWEST_TASK(p_element_version_id_from) = 'N') THEN
267 --        --check if there is transaction to this task.
268 --        --if transaction exists, return error.
269 --        x_return_status := 'T';
270 --      ELSE
271 
272         --1d. Lowest task. Check if lowest task has transaction
273         --    if yes, error.
274         --Get structure version id
275 
276         OPEN Get_Struc_Ver_Id(p_element_version_id_from);
277         FETCH Get_Struc_Ver_id into l_from_struc_ver_id, l_project_id_from;
278         CLOSE Get_Struc_Ver_id;
279         OPEN Get_Element_Id(p_element_version_id_from);
280         FETCH Get_Element_Id into l_element_id, l_object_type;
281         CLOSE Get_Element_Id;
282         --Check if it has costing/billing structure type.
283         --changed to financial
284 --dbms_output.put_line('l_element_id = '||l_element_id);
285 
286         If (PA_PROJECT_STRUCTURE_UTILS.Get_Struc_Type_For_Version(
287                    l_from_struc_ver_id, 'FINANCIAL') = 'Y') THEN
288           --Check for transaction for this task
289 
290 
291           IF (l_object_type = 'PA_TASKS') THEN
292 --Bug 2183974
293 --Check if this task is valid in PA_TASKS first
294             OPEN Check_PA_TASKS_Exists(l_element_id);
295             FETCH Check_PA_TASKS_Exists into l_dummy;
296             IF Check_PA_TASKS_Exists%NOTFOUND THEN
297               CLOSE Check_PA_TASKS_Exists;
298               x_error_message_code := 'PA_PS_PA_TASKS_NOT_EXISTS';
299               x_return_status := FND_API.G_RET_STS_ERROR;
300               return;
301             ELSE
302               --Task exists
303               CLOSE Check_PA_TASKS_Exists;
304               PA_TASK_UTILS.CHECK_CREATE_SUBTASK_OK(x_task_id => l_element_id,
305                                                   x_err_code => l_err_code,
306                                                   x_err_stack => l_err_stack,
310 
307                                                   x_err_stage => l_err_stage
308                                                   );
309               IF (l_err_code <> 0) THEN
311                 --There is transaction, error.
312                 x_error_message_code := substrb(l_err_stage,0,30); -- 4537865 : Changed substr usage to substrb
313                 x_return_status := FND_API.G_RET_STS_ERROR;
314                 return;
315               END IF;
316             END IF;
317           END IF;
318         END IF;
319 --      END IF;
320 --    END IF;
321 
322     --Check if ok to link elements from two different structures (structure types)
323     -- Get From Structure Version Id
324     OPEN get_struc_ver_id(p_element_version_id_from);
325     FETCH get_struc_ver_id into l_struc_ver_id_from, l_project_id_from;
326     CLOSE get_struc_ver_id;
327     l_financial_from := PA_PROJECT_STRUCTURE_UTILS.Get_Struc_Type_For_Version(
328                                                           l_struc_ver_id_from,
329                                                           'FINANCIAL');
330     l_workplan_from := PA_PROJECT_STRUCTURE_UTILS.Get_Struc_Type_For_Version(
331                                                           l_struc_ver_id_from,
332                                                           'WORKPLAN');
333 
334     -- Get To Structure Version Id
335     OPEN get_struc_ver_id(p_element_version_id_to);
336     FETCH get_struc_ver_id into l_struc_ver_id_to, l_project_id_to;
337     CLOSE get_struc_ver_id;
338     l_financial_to := PA_PROJECT_STRUCTURE_UTILS.Get_Struc_Type_For_Version(
339                                                           l_struc_ver_id_to,
340                                                           'FINANCIAL');
341     l_workplan_to := PA_PROJECT_STRUCTURE_UTILS.Get_Struc_Type_For_Version(
342                                                           l_struc_ver_id_to,
343                                                           'WORKPLAN');
344     --Compare structure types
345     If (l_workplan_from = 'Y') and
346        (l_financial_from = 'N') and
347        (l_workplan_to = 'N') and
348        (l_financial_to = 'Y') THEN
349       x_return_status := FND_API.G_RET_STS_ERROR;
350       x_error_message_code := 'PA_PS_LINK_WP_TO_FIN_ERR';
351       return;
352     END IF;
353 
354     If (l_financial_from = 'Y') and
355        (l_workplan_to = 'Y') and
356        (l_financial_to = 'N') THEN
357       If (l_workplan_from = 'N') THEN
358         IF (l_project_id_from <> l_project_id_to) THEN
359           x_return_status := FND_API.G_RET_STS_ERROR;
360           x_error_message_code := 'PA_PS_LINK_FIN_TO_WP_ERR';
361           return;
362         END IF;
363       ELSE
364         x_return_status := FND_API.G_RET_STS_ERROR;
365         x_error_message_code := 'PA_PS_LINK_FIN_TO_WP_ERR';
366         return;
367       END IF;
368     END IF;
369 
370 --dbms_output.put_line('checking linking within program:'||p_element_version_id_from||','||p_element_version_id_to);
371     --Check if linking within structure
372     OPEN Is_Same_Struc(p_element_version_id_from, p_element_version_id_to);
373     FETCH Is_Same_Struc into l_dummy;
374     If Is_Same_Struc%FOUND THEN
375       CLOSE Is_Same_Struc;
376       x_return_status := FND_API.G_RET_STS_ERROR;
377       x_error_message_code := 'PA_PS_LINK_WITHIN_STRUCTURE';
378       return;
379     END IF;
380     CLOSE Is_Same_Struc;
381 --dbms_output.put_line('done checking linking within program');
382 
383     --Check if a version of object A is linked to object B, not any version of object B
384     --  should be linked to any version of object A.
385 --dbms_output.put_line('checking linking versions');
386     OPEN Is_Diff_Version_Linked(p_element_version_id_from, p_element_version_id_to);
387     FETCH Is_Diff_Version_Linked into l_dummy;
388     IF Is_Diff_Version_Linked%FOUND THEN
389       CLOSE Is_Diff_Version_Linked;
390       x_return_status := FND_API.G_RET_STS_ERROR;
391       x_error_message_code := 'PA_PS_DIFF_VER_LINKED';
392       return;
393     END IF;
394     CLOSE Is_Diff_Version_Linked;
395 
396     OPEN Is_Circular_Link(p_element_version_id_from, p_element_version_id_to);
397     FETCH Is_Circular_Link into l_dummy;
398     IF Is_Circular_Link%FOUND THEN
399       CLOSE Is_Circular_Link;
400       x_return_status := FND_API.G_RET_STS_ERROR;
401       x_error_message_code := 'PA_PS_DIFF_VER_LINKED';
402       return;
403     END IF;
404     CLOSE Is_Circular_Link;
405 --dbms_output.put_line('done checking linking versions');
406 
407     --Check if any linking objects or its versions exist in the hierarchy.
408     --  needs to be enhanced in the future.
409 --dbms_output.put_line('Top node from => '||p_element_version_id_from);
410     OPEN Get_Top_Nodes(p_element_version_id_from);
411     LOOP
412       FETCH Get_Top_Nodes INTO l_top_node_id;
413 --dbms_output.put_line('top node = '||l_top_node_id);
414       EXIT WHEN Get_Top_Nodes%NOTFOUND;
415 
416 --dbms_output.put_line('checking anything/version exists in hierarchy');
417       OPEN Is_Version_Exist(l_top_node_id, p_element_version_id_to);
418       FETCH Is_Version_Exist into l_existing_elem_ver_id;
419       IF Is_Version_Exist%FOUND THEN
420         CLOSE Is_Version_Exist;
421         CLOSE Get_Top_Nodes;
422         x_return_status := FND_API.G_RET_STS_ERROR;
423         x_error_message_code := 'PA_PS_LINK_ELEM_EX_IN_HIER';
424         return;
425       END IF;
426       CLOSE Is_Version_Exist;
427 --dbms_output.put_line('done checking anything/version exists in hierarchy');
428     END LOOP;
429     CLOSE Get_Top_Nodes;
430 
431   -- 4537865
432   EXCEPTION
433     WHEN OTHERS THEN
434     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR ;
435     x_error_message_code := SQLCODE ;
436 
437     fnd_msg_pub.add_exc_msg(p_pkg_name       => 'PA_RELATIONSHIP_UTILS',
438                               p_procedure_name => 'CHECK_CREATE_LINK_OK',
439                               p_error_text     => SUBSTRB(SQLERRM,1,240));
440     RAISE;
441   END CHECK_CREATE_LINK_OK;
442 
443 -- API name                      : Check_Create_Dependency_Ok
444 -- Type                          : Private Procedure
445 -- Pre-reqs                      : None
446 -- Return Value                  : N/A
447 -- Parameters
448 --  p_element_version_id_from IN NUMBER
449 --  p_element_version_id_to   IN NUMBER
450 --  x_return_status           OUT VARCHAR2
451 --  x_error_message_code      OUT VARCHAR2
452 --
453 --
454 --  History
455 --
456 --  25-JUN-01   HSIU             -Created
457 --
458 --
459 
460 
461   procedure Check_Create_Dependency_Ok
462   (
463     p_element_version_id_from IN NUMBER
464    ,p_element_version_id_to   IN NUMBER
465    ,x_return_status           OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
466    ,x_error_message_code      OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
467   )
468   IS
469   BEGIN
470     x_return_status := FND_API.G_RET_STS_SUCCESS;
471   END CHECK_CREATE_DEPENDENCY_OK;
472 
473 
474 -- API name                      : Check_Create_Association_Ok
475 -- Type                          : Private Procedure
476 -- Pre-reqs                      : None
477 -- Return Value                  : N/A
478 -- Parameters
479 --  p_element_version_id_from IN NUMBER
480 --  p_element_version_id_to   IN NUMBER
481 --  x_return_status           OUT VARCHAR2
482 --  x_error_message_code      OUT VARCHAR2
483 --
484 --
485 --  History
486 --
487 --  25-JUN-01   HSIU             -Created
488 --
489 --
490 
491 
492   procedure Check_Create_Association_Ok
493   (
494     p_element_version_id_from IN NUMBER
495    ,p_element_version_id_to   IN NUMBER
496    ,x_return_status           OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
497    ,x_error_message_code      OUT NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
498   )
499   IS
500   BEGIN
501     x_return_status := FND_API.G_RET_STS_SUCCESS;
502   END CHECK_CREATE_ASSOCIATION_OK;
503 
504 
505 -- API name                      : parent_LP_link_exists
506 -- Type                          : Private Function
507 -- Pre-reqs                      : None
508 -- Return Value                  : Y or N
509 -- Parameters
510 --  p_parent_project_id IN NUMBER
511 --  p_sub_project_id   IN NUMBER
512 --
513 --
514 --  History
515 --
516 --  05-DEC-03   Maansari             -Created
517 --
518 --  Description
519 --
520 -- This fucntion returns 'Y' if there exists a Link from parent latest published version to the
521 -- subproject.  This is used in view PA_STRUCTURES_LINKS_V to select working version if there is no
522 -- link from the parent latest published version to the subproject.
523 --
524 --
525 
526 
527   Function parent_LP_link_exists
528   (
529     p_parent_project_id IN NUMBER
530    ,p_sub_project_id   IN NUMBER
531   ) RETURN VARCHAR2 IS
532 
533     CURSOR cur_parent_lp_link
534     IS
535       SELECT 'Y'
536         FROM pa_proj_elements ppe
537             ,pa_proj_element_versions ppv1    /* to get link task version id */
538             ,pa_proj_element_versions ppv2    /* to get sub project structure version ids */
539             ,pa_object_relationships por
540        WHERE ppe.project_id = p_parent_project_id
541          AND ppe.link_task_flag = 'Y'
542          AND ppe.project_id = ppv1.project_id
543          AND ppe.proj_element_id = ppv1.proj_element_id
544          AND ppv1.parent_structure_version_id IN ( SELECT ppevs.element_version_id
545                                                     FROM pa_proj_elem_ver_structure ppevs
546                                                    WHERE ppevs.project_id = p_parent_project_id
547                                                      AND ppevs.status_code = 'STRUCTURE_PUBLISHED'
548                                                      AND ppevs.latest_eff_published_flag = 'Y' )
549          AND ppv2.project_id = p_sub_project_id
550          AND ppv2.object_type = 'PA_STRUCTURES'
551          AND ppv1.element_version_id = por.object_id_from1
552          AND por.relationship_type in ( 'LW', 'LF' ) -- ( 'WL', 'FL' ) -- Bug # 4760126.
553          AND ppv2.element_version_id = por.object_id_to1
554 	 AND object_type_from = 'PA_TASKS'                  --Bug 6429264
555 	 AND object_type_to = 'PA_STRUCTURES'               --Bug 6429264
556          ;
557      l_return_value    VARCHAR2(1) := 'N';
558   BEGIN
559 
560        OPEN cur_parent_lp_link;
561        FETCH cur_parent_lp_link INTO l_return_value;
562        CLOSE cur_parent_lp_link;
563 
564        RETURN l_return_value;
565   END parent_LP_link_exists;
566 
567 -- API name                      : check_create_intra_dep_ok
568 -- Type                          : Private Check procedure
569 -- Pre-reqs                      : None
570 -- Return Value                  : Returns error status
571 -- Parameters
572 --  p_pre_project_id    IN NUMBER
573 --  p_pre_task_ver_id   IN NUMBER
574 --  p_project_id        IN NUMBER
575 --  p_task_ver_id       IN NUMBER
576 --
577 --
578 --  History
579 --
580 --  19-DEC-03   Maansari             -Created
581 --
582 --  Description
583 --
584 -- This check procedure check s the following business rules and returns status 'E' with proper
585 -- error message if any of the rules fails.
586 --a.    No duplicates.
587 --b.    No circular dependencies between two or more tasks.
588 --c.    A task cannot depend on itself.
589 --d.    You cannot create a dependency from an object (predecessor) to you (successor) if that object has
590 --      subtasks (successor) that depend on you (predecessor).
591 --e.    You cannot create a dependency between objects that are in the same direct path from lowest
592 --      node to the top node.
593 --
594 -- Notes:  The p_pre_<> paramaters are for predecessor tasks and stored in object_id_to1 colunmn
595 --         of pa_object_relationships.
596 
597   procedure check_create_intra_dep_ok(
598    p_pre_project_id    IN NUMBER
599   ,p_pre_task_ver_id   IN NUMBER
600   ,p_project_id        IN NUMBER
601   ,p_task_ver_id       IN NUMBER
602   ,x_return_status                     OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
603   ,x_msg_count                         OUT  NOCOPY NUMBER --File.Sql.39 bug 4440895
604   ,x_msg_data                          OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
605   ) IS
606 
607     CURSOR cur_a
608     IS
609       SELECT 'x'
610         FROM pa_object_relationships
611        WHERE object_id_from1 = p_task_ver_id
612          AND object_id_from2 = p_project_id
613          AND object_id_to1 = p_pre_task_ver_id
614          AND object_id_to2 = p_pre_project_id
615          AND relationship_type = 'D'
616        ;
617 
618     CURSOR cur_b
619     IS
620       SELECT 'x'
621                       FROM (
622                         SELECT object_id_to1
623                         FROM pa_object_relationships por2
624                         WHERE relationship_type = 'D'
625                         AND   por2.object_id_from2 = por2.object_id_to2                --Bug 3629024
626                         START WITH por2.object_id_from1 = p_pre_task_ver_id
627                         AND        relationship_type    = 'D'                          --bug 3944567
628                         CONNECT BY por2.object_id_from1 = PRIOR por2.object_id_to1
629                         AND        relationship_type    = PRIOR relationship_type
630                         AND        relationship_type    = 'D'
631                         AND        por2.object_id_from2 = PRIOR por2.object_id_from2 ) --Bug 3629024
632                       where object_id_to1 = p_task_ver_id;
633 
634    /* the successor is a prdecessor of the sub-tasks of the predecessor.*/
635 /*Commented out for bug 3629024
636    CURSOR cur_d
637    IS
638     SELECT 'x'
639       FROM pa_object_relationships por1
643         ( SELECT por2.object_id_to1
640      WHERE por1.relationship_type = 'D'
641        AND por1.object_id_to1 = p_task_ver_id
642        AND por1.object_id_from1 IN
644                FROM pa_object_relationships por2
645               START WITH por2.object_id_from1 = p_pre_task_ver_id
646             CONNECT BY por2.object_id_from1 = prior por2.object_id_to1
647                 AND por2.relationship_type = prior por2.relationship_type
648                 AND por2.relationship_type = 'S')
649     ;
650 */
651    CURSOR cur_e1_get_parent( c_child_task_ver_id NUMBER )
652    IS
653     SELECT object_id_from1
654       FROM pa_object_relationships
655      where object_id_to1 = c_child_task_ver_id
656      and relationship_type = 'S'
657       ;
658 
659    l_dummy_char          VARCHAR2(1);
660    l_child_task_ver_id   NUMBER;
661    l_parent_task_ver_id  NUMBER;
662 BEGIN
663 
664     IF p_pre_project_id IS NULL OR
665        p_pre_task_ver_id IS NULL OR
666        p_project_id IS NULL OR
667        p_task_ver_id   IS NULL
668     THEN
669         x_return_status := FND_API.G_RET_STS_ERROR;
670         x_msg_count := FND_MSG_PUB.count_msg;
671         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
672                              ,p_msg_name       => 'PA_PS_PARAMS_NULL');
673         raise FND_API.G_EXC_ERROR;
674     END IF;
675 
676     IF p_pre_project_id <> p_project_id
677     THEN
678         x_return_status := FND_API.G_RET_STS_ERROR;
679         x_msg_count := FND_MSG_PUB.count_msg;
680         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
681                              ,p_msg_name       => 'PA_PS_NOT_INTRA_DEPND');
682         raise FND_API.G_EXC_ERROR;
683     END IF;
684 
685     --c) a task cannot depend on it-self
686     IF p_pre_task_ver_id = p_task_ver_id
687     THEN
688         x_return_status := FND_API.G_RET_STS_ERROR;
689         x_msg_count := FND_MSG_PUB.count_msg;
690         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
691                              ,p_msg_name       => 'PA_PS_NO_SELF_DEPDN');
692         raise FND_API.G_EXC_ERROR;
693     END IF;
694 
695     OPEN cur_a;
696     FETCH cur_a INTO l_dummy_char;
697     IF cur_a%FOUND
698     THEN
699         x_return_status := FND_API.G_RET_STS_ERROR;
700         x_msg_count := FND_MSG_PUB.count_msg;
701         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
702                              ,p_msg_name       => 'PA_PS_DEPND_EXISTS');
703         raise FND_API.G_EXC_ERROR;
704     END IF;
705     CLOSE cur_a;
706 
707     OPEN cur_b;
708     FETCH cur_b INTO l_dummy_char;
709     IF cur_b%FOUND
710     THEN
711         x_return_status := FND_API.G_RET_STS_ERROR;
712         x_msg_count := FND_MSG_PUB.count_msg;
713         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
714                              ,p_msg_name       => 'PA_PS_CIRCLR_DEPND_EXISTS');
715         raise FND_API.G_EXC_ERROR;
716     END IF;
717     CLOSE cur_b;
718 
719 /*  Following code commented out for bug 3629024
720     OPEN cur_d;
721     FETCH cur_d INTO l_dummy_char;
722     IF cur_d%FOUND
723     THEN
724         x_return_status := FND_API.G_RET_STS_ERROR;
725         x_msg_count := FND_MSG_PUB.count_msg;
726         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
727                              ,p_msg_name       => 'PA_PS_SUBTASKS_DEPND_EXISTS');
728         raise FND_API.G_EXC_ERROR;
729     END IF;
730     CLOSE cur_d;
731 */
732     --Bug 3629024 : Check for the existence of a closed path
733     --This bug fix is for rule D
734     IF get_parents_childs(p_pre_task_ver_id, p_task_ver_id) = TRUE THEN
735         x_return_status := FND_API.G_RET_STS_ERROR;
736         x_msg_count     := FND_MSG_PUB.count_msg;
737         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
738                              ,p_msg_name       => 'PA_PS_SUBTASKS_DEPND_EXISTS');
739         raise FND_API.G_EXC_ERROR;
740     END IF;
741 
742 /*    --check if predecessor is parent in the same line of hierarchy.
743     OPEN cur_e1;
744     FETCH cur_e1 INTO l_dummy_char;
745     IF cur_e1%FOUND
746     THEN
747         x_return_status := FND_API.G_RET_STS_ERROR;
748         x_msg_count := FND_MSG_PUB.count_msg;
749         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
750                              ,p_msg_name       => 'PA_PS_NO_PARENT_PRED');
751         raise FND_API.G_EXC_ERROR;
752     END IF;
753     CLOSE cur_e1;
754 
755     --check if predecessor is child in the same line of hierarchy.
756     OPEN cur_e2;
757     FETCH cur_e2 INTO l_dummy_char;
758     IF cur_e2%FOUND
759     THEN
760         x_return_status := FND_API.G_RET_STS_ERROR;
761         x_msg_count := FND_MSG_PUB.count_msg;
762         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
763                              ,p_msg_name       => 'PA_PS_NO_CHILD_PRED');
764         raise FND_API.G_EXC_ERROR;
765     END IF;
766     CLOSE cur_e2;
767 */
768 
769   /* check for predecessor is parent */
770   l_child_task_ver_id := p_task_ver_id;
771   WHILE ( l_child_task_ver_id IS NOT NULL ) LOOP
772        OPEN cur_e1_get_parent( l_child_task_ver_id);
773        FETCH cur_e1_get_parent INTO l_parent_task_ver_id; /* predecessor is parent */
774        IF cur_e1_get_parent%NOTFOUND THEN
775          close cur_e1_get_parent;
776          exit;
777        END IF;
778        CLOSE cur_e1_get_parent;
779 
783           x_return_status := FND_API.G_RET_STS_ERROR;
780        IF l_parent_task_ver_id IS NOT NULL AND
781           l_parent_task_ver_id = p_pre_task_ver_id
782        THEN
784           x_msg_count := FND_MSG_PUB.count_msg;
785           PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
786                                ,p_msg_name       => 'PA_PS_NO_PARENT_PRED');
787           raise FND_API.G_EXC_ERROR;
788        ELSE
789           l_child_task_ver_id := l_parent_task_ver_id;
790        END IF;
791   END LOOP;
792 
793 
794   /* check for predecessor is child or successor is a parent */
795   /* starting from predecessor, find out the parent up the hierarchy and compare the
796      successor with the parent found. if successor is same as the parent found then it means
797      the predecessor is a child of the succeesor down the line in the hierarchy */
798   /* it is not possible to traverse down the hierarchy to find out whether the predecessor is a
799      child in the same line of successsor starting from the suceesor therefore traversing up
800      the hierarchy starting from predecessor*/
801 
802   l_child_task_ver_id := p_pre_task_ver_id;
803   WHILE ( l_child_task_ver_id IS NOT NULL ) LOOP
804        OPEN cur_e1_get_parent( l_child_task_ver_id);
805        FETCH cur_e1_get_parent INTO l_parent_task_ver_id;
806        IF cur_e1_get_parent%NOTFOUND THEN
807          close cur_e1_get_parent;
808          exit;
809        END IF;
810        CLOSE cur_e1_get_parent;
811 
812        IF l_parent_task_ver_id IS NOT NULL AND
813           l_parent_task_ver_id = p_task_ver_id  /* is succssor a parent in the same line of hierarcgy*/
814        THEN
815           x_return_status := FND_API.G_RET_STS_ERROR;
816           x_msg_count := FND_MSG_PUB.count_msg;
817           PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
818                                ,p_msg_name       => 'PA_PS_NO_CHILD_PRED');
819           raise FND_API.G_EXC_ERROR;
820        ELSE
821           l_child_task_ver_id := l_parent_task_ver_id;
822        END IF;
823   END LOOP;
824 
825 
826   EXCEPTION
827     when FND_API.G_EXC_ERROR then
828       x_return_status := FND_API.G_RET_STS_ERROR;
829       x_msg_count := FND_MSG_PUB.count_msg;
830     when OTHERS then
831       x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
832       x_msg_count := 1;     -- 4537865 : RESET OUT param
833       x_msg_data := SUBSTRB(SQLERRM,1,240);     -- 4537865 : RESET OUT PARAM
834       fnd_msg_pub.add_exc_msg(p_pkg_name       => 'PA_RELATIONSHIOP_UTILS',
835                               p_procedure_name => 'check_create_intra_dep_ok',
836                               p_error_text     => x_msg_data ); -- 4537865
837       raise;
838 
839 END check_create_intra_dep_ok;
840 
841 -- API name                      : check_create_intra_dep_ok
842 -- Type                          : Private Check procedure
843 -- Pre-reqs                      : None
844 -- Return Value                  : Returns error status
845 -- Parameters
846 --  p_pre_project_id    IN NUMBER
847 --  p_pre_task_ver_id   IN NUMBER
848 --  p_project_id        IN NUMBER
849 --  p_task_ver_id       IN NUMBER
850 --
851 --
852 --  History
853 --
854 --  19-DEC-03   Maansari             -Created
855 --
856 --  Description
857 --
858 -- This check procedure check s the following business rules and returns status 'E' with proper
859 -- error message if any of the rules fails.
860 --a.    No duplicates.
861 -- Notes:  The p_pre_<> paramaters are for predecessor tasks and stored in object_id_to1 colunmn
862 --         of pa_object_relationships.
863 
864   procedure check_create_inter_dep_ok(
865    p_pre_project_id    IN NUMBER
866   ,p_pre_task_ver_id   IN NUMBER
867   ,p_project_id        IN NUMBER
868   ,p_task_ver_id       IN NUMBER
869   ,x_return_status                     OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
870   ,x_msg_count                         OUT  NOCOPY NUMBER --File.Sql.39 bug 4440895
871   ,x_msg_data                          OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
872   ) IS
873 
874     CURSOR cur_a
875     IS
876       SELECT 'x'
877         FROM pa_object_relationships
878        WHERE object_id_from1 = p_task_ver_id
879          AND  object_id_from2 = p_project_id
880          AND object_id_to1 = p_pre_task_ver_id
881          AND object_id_to2 = p_pre_project_id
882          AND relationship_type = 'D'
883        ;
884 
885    CURSOR CUR_valid_sucsr_proj_task
886    IS
887     SELECT 'x'
888       FROM pa_proj_element_versions
889      WHERE project_id = p_project_id
890       AND element_version_id = p_task_ver_id
891      ;
892 
893 
894    CURSOR CUR_valid_pred_proj_task
895    IS
896     SELECT 'x'
897       FROM pa_proj_element_versions
898      WHERE project_id = p_pre_project_id
899       AND element_version_id = p_pre_task_ver_id
900      ;
901 
902    l_dummy_char   VARCHAR2(1);
903 
904 -- Begin fix for Bug # Bug # 4256435.
905 
906 cursor cur_sub_proj_hierarchy(c_pre_project_id NUMBER) is
907 -- This query selects all the parent projects of the predecessor project.
908 select por.object_id_from1 task_ver_id, por.object_id_from2 project_id
909 from pa_object_relationships por
910 where por.relationship_type in ('LW', 'LF')
911 start with por.object_id_to2 = c_pre_project_id
912 connect by prior por.object_id_from2 = por.object_id_to2
913 and prior por.relationship_type = por.relationship_type
914 and por.relationship_type in ('LW', 'LF')
915 AND object_type_from = 'PA_TASKS'                  --Bug 6429264
916 AND object_type_to = 'PA_STRUCTURES'               --Bug 6429264
917 union all
918 -- This query selects all the child projects of the predecessor project.
919 select por.object_id_to1 task_ver_id, por.object_id_to2 project_id
920 from pa_object_relationships por
921 where por.relationship_type in ('LW', 'LF')
922 start with por.object_id_from2 = c_pre_project_id
923 connect by prior por.object_id_to2 = por.object_id_from2
924 and prior por.relationship_type = por.relationship_type
925 and por.relationship_type in ('LW', 'LF')
926 AND object_type_from = 'PA_TASKS'                  --Bug 6429264
927 AND object_type_to = 'PA_STRUCTURES'               --Bug 6429264
928 ;
929 
930 rec_sub_proj_hierarchy cur_sub_proj_hierarchy%ROWTYPE;
931 
932 cursor cur_linking_task(c_task_ver_id NUMBER, c_linking_task_ver_id NUMBER) is
933 select 'Y'
934 from pa_object_relationships por
935 where por.object_id_from1 = c_task_ver_id
936 and por.object_id_to1 = c_linking_task_ver_id
937 and por.relationship_type = 'S';
938 
939 l_link_exists   VARCHAR2(1) := 'N';
940 
941 -- End fix for Bug # Bug # 4256435.
942 
943 BEGIN
944 
945     x_return_status := FND_API.G_RET_STS_SUCCESS;
946 
947     --check valid for null parameters
948     IF p_pre_project_id IS NULL OR
949        p_pre_task_ver_id IS NULL OR
950        p_project_id IS NULL OR
951        p_task_ver_id   IS NULL
952     THEN
953         x_return_status := FND_API.G_RET_STS_ERROR;
954         x_msg_count := FND_MSG_PUB.count_msg;
955         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
956                              ,p_msg_name       => 'PA_PS_PARAMS_NULL');
957         raise FND_API.G_EXC_ERROR;
958     END IF;
959 
960     --check for inter projects. The successor project and predecssor projects should be different.
961     IF p_pre_project_id = p_project_id
962     THEN
963         x_return_status := FND_API.G_RET_STS_ERROR;
964         x_msg_count := FND_MSG_PUB.count_msg;
965         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
966                              ,p_msg_name       => 'PA_PS_NOT_INTER_DEPND');
967         raise FND_API.G_EXC_ERROR;
968     END IF;
969 
970 -- Begin fix for Bug # Bug # 4256435.
971 
972         for rec_sub_proj_hierarchy in cur_sub_proj_hierarchy(p_pre_project_id)
973         loop
974 
975                 if (rec_sub_proj_hierarchy.project_id = p_project_id) then
976 
977                         open  cur_linking_task(p_task_ver_id, rec_sub_proj_hierarchy.task_ver_id);
978                         fetch cur_linking_task into l_link_exists;
979                         close cur_linking_task;
980 
981                         if (l_link_exists = 'Y') then
982 
983                                 x_return_status := FND_API.G_RET_STS_ERROR;
984                                 x_msg_count := FND_MSG_PUB.count_msg;
985 
986                                 PA_UTILS.ADD_MESSAGE(p_app_short_name  => 'PA'
987                                                      , p_msg_name       => 'PA_WP_PRGM_EXISTS_NO_DEP');
988 
989                                 raise FND_API.G_EXC_ERROR;
990 
991                         end if;
992                 end if;
993 
994         end loop;
995 
996 -- End fix for Bug # Bug # 4256435.
997 
998 /* do we really need this validation here?
999     --validate successor project id and task ver id combination.
1000     OPEN cur_valid_sucsr_proj_task;
1001     FETCH cur_valid_sucsr_proj_task INTO l_dummy;
1002     IF cur_valid_sucsr_proj_task%NOTFOUND
1003     THEN
1004         x_return_status := FND_API.G_RET_STS_ERROR;
1005         x_msg_count := FND_MSG_PUB.count_msg;
1006         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
1007                              ,p_msg_name       => 'PA_PS_INV_SUCSR_PRJ_TSK');
1008         raise FND_API.G_EXC_ERROR;
1009     END IF;
1010     CLOSE cur_valid_sucsr_proj_task;
1011 
1012     --validate predecessor project id and task ver id combination.
1013     OPEN cur_valid_pred_proj_task;
1014     FETCH cur_valid_pred_proj_task INTO l_dummy;
1015     IF cur_valid_pred_proj_task%NOTFOUND
1016     THEN
1017         x_return_status := FND_API.G_RET_STS_ERROR;
1018         x_msg_count := FND_MSG_PUB.count_msg;
1019         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
1020                              ,p_msg_name       => 'PA_PS_INV_PRED_PRJ_TSK');
1021         raise FND_API.G_EXC_ERROR;
1022     END IF;
1023     CLOSE cur_valid_pred_proj_task;
1024 */
1025 
1026     --check for duplicate dependency.
1027     OPEN cur_a;
1028     FETCH cur_a INTO l_dummy_char;
1029     IF cur_a%FOUND
1030     THEN
1031         x_return_status := FND_API.G_RET_STS_ERROR;
1032         x_msg_count := FND_MSG_PUB.count_msg;
1033         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
1034                              ,p_msg_name       => 'PA_PS_DEPND_EXISTS');
1035         raise FND_API.G_EXC_ERROR;
1036     END IF;
1037     CLOSE cur_a;
1038 
1039   EXCEPTION
1040     when FND_API.G_EXC_ERROR then
1041       x_return_status := FND_API.G_RET_STS_ERROR;
1042       x_msg_count := FND_MSG_PUB.count_msg;
1043     when OTHERS then
1044       x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1045       x_msg_count := 1;         -- 4537865 : RESET OUT param
1046       x_msg_data := SUBSTRB(SQLERRM,1,240);     -- 4537865 : RESET OUT PARAM
1047       fnd_msg_pub.add_exc_msg(p_pkg_name       => 'PA_RELATIONSHIOP_UTILS',
1048                               p_procedure_name => 'check_create_inter_dep_ok',
1049                               p_error_text     => x_msg_data); -- 4537865
1050       raise;
1051 
1052 END check_create_inter_dep_ok;
1053 
1054 
1055 FUNCTION DISPLAY_PREDECESSORS
1056   ( p_element_version_id IN NUMBER)
1057   RETURN  VARCHAR2 IS
1058 --
1059 -- To modify this template, edit file FUNC.TXT in TEMPLATE
1060 -- directory of SQL Navigator
1061 --
1062 -- Purpose: Briefly explain the functionality of the function
1063 --
1064 -- MODIFICATION HISTORY
1065 -- Person      Date    Comments
1066 -- ---------   ------  -------------------------------------------
1067 -- SMUKKA      01/28/2004   Initial Version
1068 
1069    l_task_name_list                 VARCHAR2(1220):=NULL; --bug 4141897
1070    l_task_count                     NUMBER:=0;
1071 CURSOR cur_task_names( c_element_version_id NUMBER )
1072   IS
1073     SELECT ppe.name task_name
1074       FROM pa_proj_element_versions ppev,
1075            pa_proj_elements ppe
1076      WHERE ppev.proj_element_id = ppe.proj_element_id
1077        and ppev.project_id = ppe.project_id
1078        AND ppev.element_version_id IN (SELECT object_id_to1
1079                                          FROM pa_object_relationships por
1080                                         WHERE por.object_id_from1   = c_element_version_id
1081     --Bug8534395: Commented below predicate to allow tasks from other project to be shown as predecessors.
1082                                           --AND por.object_id_from2   = por.object_id_to2
1083                                           AND por.object_type_from  = 'PA_TASKS' --4141109 Replaced LIKE with Equijoin
1084                                           AND por.object_type_to    = 'PA_TASKS' --4141109 Replaced LIKE with Equijoin
1085                                           AND por.relationship_type = 'D');  --4141109 Replaced LIKE with Equijoin
1086     l_cur_task_names_rec  cur_task_names%ROWTYPE;
1087 BEGIN
1088    OPEN cur_task_names(p_element_version_id);
1089    LOOP
1090       FETCH cur_task_names into l_cur_task_names_rec;
1091       IF cur_task_names%NOTFOUND THEN
1092          EXIT;
1093       ELSE
1094          l_task_count:=l_task_count+1;
1095          IF l_task_count = 1 THEN
1096             l_task_name_list:= l_task_name_list||l_cur_task_names_rec.task_name;
1097          ELSIF l_task_count > 5 THEN
1098                l_task_name_list:= l_task_name_list||'...';
1099          ELSE
1100             l_task_name_list := l_task_name_list||','||l_cur_task_names_rec.task_name;
1101          END IF;
1102       END IF;
1103    END LOOP;
1104    CLOSE cur_task_names;
1105    RETURN l_task_name_list ;
1106 EXCEPTION
1107    WHEN OTHERS THEN
1108        NULL ;
1109 END DISPLAY_PREDECESSORS;
1110 
1111 
1112 FUNCTION ChecK_dep_exists(p_element_version_id IN NUMBER)
1113   RETURN VARCHAR2
1114 IS
1115   CURSOR get_dependency IS
1116     SELECT 1 from pa_object_relationships
1117      where relationship_type = 'D'
1118        and (object_id_from1 = p_element_version_id OR
1119             object_id_to1 = p_element_version_id);
1120   l_dummy NUMBER;
1121 BEGIN
1122   OPEN get_Dependency;
1123   FETCH get_Dependency into l_dummy;
1124   IF get_dependency%FOUND THEN
1125     CLOSE get_dependency;
1126     return 'Y';
1127   END IF;
1128   CLOSE get_Dependency;
1129   return 'N';
1130 END CHECK_DEP_EXISTS;
1131 
1132 
1133 FUNCTION Is_Proj_Top_Program(p_project_id IN NUMBER)
1134   RETURN VARCHAR2
1135 IS
1136   --Bug No 3634315 Performance Fix, to avoid full table scan on pa_object_relationships table.
1137 /*  CURSOR c1 IS
1138     select 1
1139       from pa_object_relationships
1140      where relationship_type IN ('LW', 'LF')
1141        and object_id_to2 = p_project_id;*/
1142     CURSOR c1 IS
1143     select 1
1144       from pa_object_relationships por,
1145            pa_proj_element_versions ppev
1146      where por.relationship_type IN ('LW', 'LF')
1147        and ppev.element_version_id = por.object_id_to1
1148        and por.object_id_to2 = ppev.project_id
1149        and por.object_id_to2 = p_project_id
1150        AND object_type_from = 'PA_TASKS'                   --Bug 6429264
1151        AND object_type_to = 'PA_STRUCTURES';               --Bug 6429264
1152 
1153   CURSOR c2 IS
1154     select 1
1155       from pa_object_relationships
1156      where relationship_type IN ('LW', 'LF')
1157        and object_id_from2 = p_project_id
1158        AND object_type_from = 'PA_TASKS'                   --Bug 6429264
1159        AND object_type_to = 'PA_STRUCTURES';               --Bug 6429264
1160 
1161   l_dummy number;
1162 BEGIN
1163   OPEN c1;
1164   FETCH c1 into l_dummy;
1165   IF c1%FOUND THEN
1166     CLOSE c1;
1167     return 'N';
1168   END IF;
1169   CLOSE c1;
1170 
1171   OPEN c2;
1172   FETCH c2 into l_dummy;
1173   IF c2%NOTFOUND THEN
1174     CLOSE c2;
1175     return 'N';
1176   END IF;
1177   CLOSE c2;
1178 
1179   return 'Y';
1180 END Is_Proj_Top_Program;
1181 
1182 FUNCTION Is_Proj_Sub_Project(p_project_id IN NUMBER)
1183   RETURN VARCHAR2
1184 IS
1185   --Bug No 3634315 Performance Fix, to avoid full table scan on pa_object_relationships table.
1186 /*  CURSOR c1 IS
1187     select 1
1188       from pa_object_relationships
1189      where relationship_type IN ('LW', 'LF')
1190        and object_id_to2 = p_project_id;*/
1191     CURSOR c1 IS
1192     select 1
1193       from pa_object_relationships por,
1194            pa_proj_element_versions ppev
1195      where por.relationship_type IN ('LW', 'LF')
1196        and ppev.element_version_id = por.object_id_to1
1197        and por.object_id_to2 = ppev.project_id
1198        and por.object_id_to2 = p_project_id
1199        AND object_type_from = 'PA_TASKS'                   --Bug 6429264
1200        AND object_type_to = 'PA_STRUCTURES';               --Bug 6429264
1201 
1202   l_dummy NUMBER;
1203 BEGIN
1204   open c1;
1205   FETCH c1 into l_dummy;
1206   IF c1%NOTFOUND THEN
1207     CLOSE c1;
1208     return 'N';
1209   END IF;
1210   CLOSE c1;
1211 
1212   return 'Y';
1213 END Is_Proj_Sub_Project;
1214 
1215 FUNCTION DISABLE_SYS_PROG_OK(p_project_id NUMBER)
1216   RETURN varchar2
1217 IS
1218   CURSOR c1 IS
1219     select 1
1220     from pa_object_relationships
1221     where relationship_type IN ('LW', 'LF')
1222     and object_id_from2 = p_project_id;
1223   l_dummy NUMBER;
1224 BEGIN
1225   OPEN c1;
1226   FETCH c1 into l_dummy;
1227   IF c1%found then
1228     CLOSE c1;
1229     return 'N';
1230   END IF;
1231   CLOSE c1;
1232   return 'Y';
1233 END DISABLE_SYS_PROG_OK;
1234 
1235 FUNCTION DISABLE_MULTI_PROG_OK(p_project_id NUMBER)
1236   RETURN varchar2
1237 IS
1238   --Bug No 3634315 Performance Fix, to avoid full table scan on pa_object_relationships table.
1239 /*  CURSOR c1(c_parent_project_id NUMBER, c_child_project_id NUMBER) IS
1240     select count(1)
1241     from pa_object_relationships
1242     where relationship_type IN ('LW', 'LF')
1243     and object_id_to2 = c_child_project_id
1244     and object_id_from1 <> c_parent_project_id;*/
1245   CURSOR c1(c_parent_project_id NUMBER, c_child_project_id NUMBER) IS
1246   select count(1)
1247     from pa_object_relationships por,
1248          pa_proj_element_versions ppev
1249     where relationship_type IN ('LW', 'LF')
1250     and ppev.element_version_id = object_id_to1
1251     and por.object_id_to2 = ppev.project_id
1252     and object_id_to2 = c_child_project_id
1253     and object_id_from2 <> c_parent_project_id;--bug 4244482
1254 
1255   CURSOR c2 IS
1256     select object_id_from2, object_Id_to2
1257       from pa_object_relationships
1258      where relationship_type IN ('LW')   --bug 3962849
1259   start with object_id_from2 = p_project_id
1260          and relationship_type = 'LW'
1261   connect by prior object_id_to2 = object_id_from2
1262          and prior relationship_type = relationship_type;
1263 
1264   CURSOR c3 IS
1265     select object_id_from2, object_Id_to2
1266       from pa_object_relationships
1267      where relationship_type IN ('LF')   --bug 3962849
1268   start with object_id_from2 = p_project_id
1269          and relationship_type = 'LF'
1270   connect by prior object_id_to2 = object_id_from2
1271          and prior relationship_type = relationship_type;
1272 
1273   l_parent_proj_id NUMBER;
1274   l_child_proj_id NUMBER;
1275   l_count NUMBER;
1276 BEGIN
1277   OPEN c2;
1278   LOOP
1279     FETCH c2 into l_parent_proj_id, l_child_proj_id;
1280     EXIT WHEN C2%NOTFOUND;
1281     OPEN c1(l_parent_proj_id, l_child_proj_id);
1282     FETCH c1 INTO l_count;
1283     IF l_count > 0 THEN
1284       CLOSE c1;
1285       CLOSE c2;
1286       return 'N';
1287     END IF;
1288     CLOSE c1;
1289   END LOOP;
1290   CLOSE c2;
1291 
1292   OPEN c3;
1293   LOOP
1294     FETCH c3 into l_parent_proj_id, l_child_proj_id;
1295     EXIT WHEN C3%NOTFOUND;
1296     OPEN c1(l_parent_proj_id, l_child_proj_id);
1297     FETCH c1 INTO l_count;
1298     IF l_count > 0 THEN
1299       CLOSE c1;
1300       CLOSE c3;
1301       return 'N';
1302     END IF;
1303     CLOSE c1;
1304   END LOOP;
1305   CLOSE c3;
1306 
1307   return 'Y';
1308 END DISABLE_MULTI_PROG_OK;
1309 
1310 FUNCTION CREATE_SUB_PROJ_ASSO_OK(p_task_version_id NUMBER, p_project_id NUMBER,
1311                                  p_structure_type VARCHAR2 := 'WORKPLAN')
1312   RETURN VARCHAR2
1313 IS
1314   CURSOR get_project_id(c_element_version_id NUMBER) IS
1315     select project_id
1316       from pa_proj_element_versions
1317      where element_version_id = c_element_version_id;
1318 
1319   CURSOR get_loop1(c_project_id NUMBER) IS
1320     select object_Id_to2, object_id_from2 -- Fix for Bug # 4297715.
1321       from pa_object_relationships
1322      where relationship_type IN ('LW')
1323      start with object_id_from2 = c_project_id
1324    connect by prior object_id_to2 = object_id_from2
1325                 and prior relationship_type = relationship_type
1326                 and relationship_type = 'LW';
1327 
1328   CURSOR get_loop2(c_project_id NUMBER) IS
1329     select object_Id_to2, object_id_from2 -- Fix for Bug # 4297715.
1330       from pa_object_relationships
1331      where relationship_type IN ('LF')
1332      start with object_id_from2 = c_project_id
1333    connect by prior object_id_to2 = object_id_from2
1334                 and prior relationship_type = relationship_type
1335                 and relationship_type = 'LF';
1336 --
1337   -- Start of Bug 3621794
1338   CURSOR get_proj_prog_fl(c_project_id NUMBER) IS
1339   SELECT sys_program_flag
1340     FROM pa_projects_all
1341    WHERE project_id =c_project_id;
1342 
1343    CURSOR get_parent_sub_proj(c_project_id NUMBER) IS
1344      SELECT ppa.sys_program_flag
1345      FROM pa_proj_element_versions ppev,
1346           pa_proj_elements ppe,
1347           pa_projects_all ppa
1348     WHERE ppe.project_id = ppev.project_id
1349       AND ppe.proj_element_id = ppev.proj_element_id
1350       AND ppev.object_type = 'PA_TASKS'
1351       AND ppe.object_type = 'PA_TASKS'
1352       AND ppe.project_id = ppa.project_id
1353       AND ppev.element_version_id IN (
1354                      SELECT object_id_from1
1355                        FROM pa_object_relationships
1356                       WHERE relationship_type IN ('LW','LF')
1357                  START WITH object_id_to2 = c_project_id
1358                         AND object_type_to = 'PA_STRUCTURES'
1359                  CONNECT BY object_id_from2 = prior object_id_to2
1360                         and prior relationship_type = relationship_type
1361                         AND relationship_type IN ('LW','LF')
1362                         AND object_type_from = 'PA_TASKS');
1363   -- End of Bug 3621794
1364 --
1365   --bug 3893970
1366   CURSOR get_multi_rollup(c_project_id NUMBER) IS
1367   select nvl(ALLOW_MULTI_PROGRAM_ROLLUP,'N')
1368     from pa_projects_all
1369    where project_id = c_project_id;
1370 
1371   CURSOR get_child_links(c_project_id NUMBER, c_parent_proj_id NUMBER) IS
1372   select distinct(object_id_from2)
1373       from pa_object_relationships a
1374      where a.relationship_type IN ('LW','LF')
1375        and a.object_id_to2 = c_project_id
1376        and a.object_id_from2 <> c_parent_proj_id -- Fix for Bug # 4297715.
1377        and exists (select 1 from PA_PROJ_ELEMENT_VERSIONS elv  /* Added the exists for Bug 6148092 */
1378               where elv.element_version_id = a.object_id_from1
1379               and ((elv.PARENT_STRUCTURE_VERSION_ID =
1380                    PA_PROJECT_STRUCTURE_UTILS.get_current_working_ver_id(elv.project_id))
1381                 or (elv.PARENT_STRUCTURE_VERSION_ID =
1382                    PA_PROJECT_STRUCTURE_UTILS.get_latest_wp_version(elv.project_id))
1383                 )
1384               );
1385 
1386   l_linked_parent_proj_id NUMBER;
1387   l_multi_rollup_flag VARCHAR2(1);
1388   l_dest_multi_rollup_flag VARCHAR2(1);
1389   --end bug 3893970
1390 
1391   l_src_project_id NUMBER;
1392   l_dest_project_id NUMBER;
1393   l_proj_id NUMBER;
1394   l_proj_prog_fl  VARCHAR2(1);                 --Bug 3621794
1395 
1396 -- Begin Fix for Bug # 4297715.
1397 
1398 cursor cur_get_status_code(c_task_version_id NUMBER) is
1399 select ppevs.status_code
1400 from pa_proj_elem_ver_structure ppevs, pa_proj_element_versions ppev
1401 where ppev.element_version_id = c_task_version_id
1402 and ppev.project_id = ppevs.project_id -- Bug # 4868867.
1403 and ppev.parent_structure_version_id = ppevs.element_version_id;
1404 
1405 l_status_code   VARCHAR2(150) := NULL;
1406 
1407 l_proj_id_from  NUMBER := NULL;
1408 
1409 -- End Fix for Bug # 4297715.
1410 
1411 -- Begin fix for Bug # Bug # 4256435.
1412 
1413 cursor cur_dep_hierarchy(c_src_task_ver_id NUMBER) is
1414 -- This query selects all the successor projects of the source project.
1415 select por.object_id_from2 project_id
1416 from pa_object_relationships por
1417 where por.relationship_type = 'D'
1418 start with por.object_id_to1 = c_src_task_ver_id
1419 -- connect by prior por.object_id_from2 = por.object_id_to2 -- Fix for Bug # 4256435.
1420 connect by prior por.object_id_from1 = por.object_id_to1 -- Fix for Bug # 4256435.
1421 and prior por.relationship_type = por.relationship_type
1422 and por.relationship_type = 'D'
1423 union all
1424 -- This query selects all the predecessor projects of the source project.
1425 select por.object_id_to2 project_id
1426 from pa_object_relationships por
1427 where por.relationship_type = 'D'
1428 start with por.object_id_from1 = c_src_task_ver_id
1429 -- connect by prior por.object_id_to2 = por.object_id_from2 -- Fix for Bug # 4256435.
1430 connect by prior por.object_id_to1 = por.object_id_from1 -- Fix for Bug # 4256435.
1431 and prior por.relationship_type = por.relationship_type
1432 and por.relationship_type = 'D';
1433 
1434 rec_dep_hierarchy cur_dep_hierarchy%ROWTYPE;
1435 
1436 -- End fix for Bug # Bug # 4256435.
1437 
1438 BEGIN
1439   OPEN get_project_id(p_task_version_id);
1440   FETCH get_project_id into l_src_project_id;
1441   CLOSE get_project_id;
1442 
1443 -- Begin Fix for Bug # 4297715.
1444 
1445   open cur_get_status_code(p_task_version_id);
1446   fetch cur_get_status_code into l_status_code;
1447   close cur_get_status_code;
1448 
1449 -- End Fix for Bug # 4297715.
1450 
1451 
1452   l_dest_project_id := p_project_id;
1453 
1454   IF (l_src_project_id = l_dest_project_id) THEN
1455     return 'N';
1456   END IF;
1457 
1458 -- Begin fix for Bug # Bug # 4256435.
1459 
1460         for rec_dep_hierarchy in cur_dep_hierarchy(p_task_version_id)
1461         loop
1462 
1463                 if (rec_dep_hierarchy.project_id = l_dest_project_id) then
1464 
1465                         PA_UTILS.ADD_MESSAGE(p_app_short_name  => 'PA'
1466                                              , p_msg_name       => 'PA_WP_DEP_EXISTS_NO_PRGM');
1467 
1468                         return 'N';
1469 
1470                  end if;
1471 
1472         end loop;
1473 
1474 -- End fix for Bug # Bug # 4256435.
1475 
1476   --bug 3893970
1477   OPEN get_multi_rollup(l_src_project_id);
1478   FETCH get_multi_rollup INTO l_multi_rollup_flag;
1479   CLOSE get_multi_rollup;
1480 
1481   If l_multi_rollup_flag = 'N' THEN
1482     --need to check if new child is already linked
1483     OPEN get_child_links(l_dest_project_id, l_src_project_id);
1484     FETCH get_child_links INTO l_linked_parent_proj_id;
1485     IF get_child_links%FOUND THEN
1486       CLOSE get_child_links;
1487       return 'N';
1488     END IF;
1489     CLOSE get_child_links;
1490 
1491     --need to check all new child to see if it has multi rollup = 'Y'
1492     FOR i IN get_loop1(l_dest_project_id) LOOP
1493       OPEN get_multi_rollup(i.object_id_to2);
1494       FETCH get_multi_rollup into l_dest_multi_rollup_flag;
1495       CLOSE get_multi_rollup;
1496 
1497       IF (l_dest_multi_rollup_flag = 'Y') THEN
1498         return 'N';
1499       END IF;
1500     END LOOP;
1501 
1502     FOR i IN get_loop2(l_dest_project_id) LOOP
1503       OPEN get_multi_rollup(i.object_id_to2);
1504       FETCH get_multi_rollup into l_dest_multi_rollup_flag;
1505       CLOSE get_multi_rollup;
1506 
1507       IF (l_dest_multi_rollup_flag = 'Y') THEN
1508         return 'N';
1509       END IF;
1510     END LOOP;
1511   ELSE
1512     --If allow, need to check if new child has parent which does not allow
1513     --need to check all new child to see if its parent has multi rollup = 'N'
1514     OPEN get_child_links(l_dest_project_id, l_src_project_id);
1515     LOOP
1516       FETCH get_child_links INTO l_linked_parent_proj_id;
1517       EXIT WHEN get_child_links%NOTFOUND;
1518 
1519       OPEN get_multi_rollup(l_linked_parent_proj_id);
1520       FETCH get_multi_rollup into l_dest_multi_rollup_flag;
1521       CLOSE get_multi_rollup;
1522 
1523       IF (l_dest_multi_rollup_flag = 'N') THEN
1524         CLOSE get_child_links;
1525         return 'N';
1526       END IF;
1527     END LOOP;
1528     CLOSE get_child_links;
1529   END IF;
1530   --end bug 3893970
1531 
1532   IF (p_structure_type = 'WORKPLAN') THEN
1533     OPEN get_loop1(l_src_project_id);
1534     LOOP
1535       FETCH get_loop1 INTO l_proj_id, l_proj_id_from; -- Fix for Bug # 4297715.
1536       EXIT when get_loop1%NOTFOUND;
1537 
1538       IF ((l_proj_id = l_dest_project_id) -- Fix for Bug # 4297715.
1539 
1540           -- Fix for Bug # 4297715. If the published versions of the source project and the destination
1541           -- project are linked in a parent and immediate child relationship respectively,  we still allow
1542           -- the working version of the source project to be linked to the published version of the
1543           -- destination project.
1544 
1545           and  NOT((nvl(l_status_code,'X') = 'STRUCTURE_WORKING') -- Fix for Bug # 4297715.
1546                 and (l_proj_id_from = l_src_project_id))) -- Fix for Bug # 4297715.
1547      THEN
1548         CLOSE get_loop1;
1549         return 'N';
1550       END If;
1551 
1552     END LOOP;
1553     CLOSE get_loop1;
1554   END IF;
1555 
1556   IF (p_structure_type = 'FINANCIAL') THEN
1557     OPEN get_loop2(l_src_project_id);
1558     LOOP
1559       FETCH get_loop2 INTO l_proj_id, l_proj_id_from; -- Fix for Bug # 4297715.
1560       EXIT when get_loop2%NOTFOUND;
1561 
1562       IF ((l_proj_id = l_dest_project_id) -- Fix for Bug # 4297715.
1563 
1564       -- Fix for Bug # 4297715. If the published versions of the source project and the destination
1565           -- project are linked in a parent and immediate child relationship respectively,  we still allow
1566       -- the working version of the source project to be linked to the published version of the
1567       -- destination project.
1568 
1569           and  NOT((nvl(l_status_code,'X') = 'STRUCTURE_WORKING') -- Fix for Bug # 4297715.
1570                    and (l_proj_id_from = l_src_project_id))) -- Fix for Bug # 4297715.
1571     THEN
1572         CLOSE get_loop2;
1573         return 'N';
1574       END If;
1575 
1576     END LOOP;
1577     CLOSE get_loop2;
1578   END IF;
1579 
1580   --IMP Note: Please add any new validation above this code
1581   --Imp Note: Let this be the last validation to be performed by this API.
1582   -- Start of Bug 3621794
1583   OPEN get_proj_prog_fl(l_src_project_id);
1584   FETCH get_proj_prog_fl INTO l_proj_prog_fl;
1585      IF l_proj_prog_fl = 'Y' THEN
1586         CLOSE get_proj_prog_fl;
1587 --        return 'N';                 --Bug 3622177
1588           return 'Y';                 --Bug 3622177
1589      END IF;
1590   CLOSE get_proj_prog_fl;
1591 
1592   l_proj_prog_fl:='N';
1593   OPEN get_parent_sub_proj(l_src_project_id);
1594   LOOP
1595      FETCH get_parent_sub_proj INTO l_proj_prog_fl;
1596      IF get_parent_sub_proj%NOTFOUND THEN
1597         CLOSE get_parent_sub_proj;
1598     return 'N';
1599      END IF;
1600 --     EXIT WHEN get_parent_sub_proj%NOTFOUND;
1601      IF l_proj_prog_fl = 'Y' THEN
1602         CLOSE get_parent_sub_proj;
1603 --        return 'N';                 --Bug 3622177
1604           return 'Y';                 --Bug 3622177
1605      END IF;
1606   END LOOP;
1607   CLOSE get_parent_sub_proj;
1608   -- End of Bug 3621794
1609 
1610   return 'Y';
1611 END CREATE_SUB_PROJ_ASSO_OK;
1612 
1613 FUNCTION IS_AUTO_ROLLUP(p_project_id NUMBER)
1614   RETURN VARCHAR2
1615 IS
1616   cursor c1 is
1617     select ppwa.AUTO_ROLLUP_SUBPROJ_FLAG
1618       from pa_proj_workplan_attr ppwa,
1619            pa_proj_elements ppe,
1620            pa_proj_structure_types ppst,
1621            pa_structure_types pst
1622      where ppe.project_id = p_project_id
1623        and ppe.object_type = 'PA_STRUCTURES'
1624        and ppe.proj_element_id = ppst.proj_element_id
1625        and ppst.structure_type_id = pst.structure_type_id
1626        and pst.structure_type = 'WORKPLAN'
1627        and ppe.project_id = ppwa.project_id
1628        and ppe.proj_element_id = ppwa.proj_element_id;
1629   l_dummy VARCHAR2(1);
1630 BEGIN
1631   OPEN c1;
1632   FETCH c1 into l_dummy;
1633   CLOSE c1;
1634 
1635   return l_dummy;
1636 
1637 END IS_AUTO_ROLLUP;
1638 
1639 FUNCTION Get_Latest_Parent_Ver_obj_Id(p_structure_ver_id NUMBER,
1640                                       p_task_id NUMBER
1641                       , p_relationship_type VARCHAR2 := 'LW') -- Fix for Bug # 4471484.
1642   RETURN NUMBER
1643 IS
1644   CURSOR c1 IS
1645     select por2.object_relationship_id, por2.relationship_type, ppev.element_version_id
1646       from pa_object_relationships  por1,
1647            pa_object_relationships  por2,
1648            pa_proj_element_versions ppev,
1649            pa_proj_elements         ppe
1650      where ppe.proj_element_id = p_task_id
1651        and ppe.proj_element_id = ppev.proj_element_id
1652        and ppe.project_id = ppev.project_id
1653        and ppev.element_version_id = por1.object_id_from1
1654        and por1.relationship_type = 'S'
1655        and por2.object_id_to1 = p_structure_ver_id
1656        and por2.object_id_from1 = por1.object_id_to1
1657        and por2.relationship_type = p_relationship_type -- IN ('LF', 'LW') -- Fix for Bug # 4471484.
1658        -- and rownum < 2 -- Fix for Bug # 4477118.
1659      order by ppev.element_version_id desc ; -- por2.relationship_type desc, -- Fix for Bug # 4477118.
1660 
1661 /*
1662     select por1.object_id_from1
1663       from pa_object_relationships  por1,
1664            pa_object_relationships  por2
1665      where por2.object_id_to1 = p_structure_ver_id
1666        and por2.object_id_from1 = por1.object_id_to1
1667        and por2.relationship_type IN ('LF', 'LW')
1668        and rownum < 2
1669   order by por1.object_id_from1 desc;
1670 */
1671 
1672   l_obj_rel_id    NUMBER;
1673   l_element_ver_id NUMBER;
1674   l_obj_type      VARCHAR2(30);
1675 BEGIN
1676   OPEN c1;
1677   FETCH c1 into l_obj_rel_id, l_obj_type, l_element_ver_id;
1678   CLOSE c1;
1679 
1680   return l_obj_rel_id;
1681 END Get_Latest_Parent_Ver_obj_Id;
1682 
1683 FUNCTION Get_Latest_Parent_Task_Ver_Id(p_structure_ver_id NUMBER,
1684                                       p_task_id NUMBER
1685                       , p_relationship_type VARCHAR2 := 'LW')
1686   RETURN NUMBER
1687 IS
1688   CURSOR c1 IS
1689     select por2.object_relationship_id, por2.relationship_type, ppev.element_version_id
1690       from pa_object_relationships  por1,
1691            pa_object_relationships  por2,
1692            pa_proj_element_versions ppev,
1693            pa_proj_elements         ppe
1694      where ppe.proj_element_id = p_task_id
1695        and ppe.proj_element_id = ppev.proj_element_id
1696        and ppe.project_id = ppev.project_id
1697        and ppev.element_version_id = por1.object_id_from1
1698        and por1.relationship_type = 'S'
1699        and por2.object_id_to1 = p_structure_ver_id
1700        and por2.object_id_from1 = por1.object_id_to1
1701        and por2.relationship_type = p_relationship_type
1702      order by ppev.element_version_id desc ;
1703 
1704   l_obj_rel_id    NUMBER;
1705   l_element_ver_id NUMBER;
1706   l_obj_type      VARCHAR2(30);
1707 BEGIN
1708   OPEN c1;
1709   FETCH c1 into l_obj_rel_id, l_obj_type, l_element_ver_id;
1710   CLOSE c1;
1711 
1712   return l_element_ver_id;
1713 END Get_Latest_Parent_Task_Ver_Id;
1714 
1715 
1716 FUNCTION Get_Latest_Child_Ver_Id(p_task_ver_id NUMBER)
1717   RETURN NUMBER
1718 IS
1719   CURSOR c1 IS
1720     select por2.object_id_to1
1721       from pa_object_relationships  por1,
1722            pa_object_relationships  por2
1723      where por1.object_id_from1 = p_task_ver_id
1724        and por1.object_id_to1 = por2.object_id_from1
1725        and por2.relationship_type IN ('LF', 'LW')
1726        and rownum < 2
1727   order by por2.object_id_to1 desc;
1728 
1729   l_child_ver_id NUMBER;
1730 BEGIN
1731   OPEN c1;
1732   FETCH c1 into l_child_ver_id;
1733   CLOSE c1;
1734 
1735   return l_child_ver_id;
1736 END Get_Latest_Child_Ver_Id;
1737 
1738 
1739 --============================================================================================
1740 /*Bug 3629024 : ## SHORT NOTE ON THE FOLL. TWO MUTUALLY RECURSIVE FUNCTIONS ##
1741 Treat the workplan structure as a directed graph, with nodes being the
1742 structure/tasks and links between the nodes being dependencies and/or
1743 parent/child task relationships.
1744 Dependency links are directed from sucessor to predecessor.
1745 Child Tasks are linked to their parents with a bi-directional link.
1746 Then, there should be no circular path for any node
1747 
1748 The following two functions check for the existence of such a closed path.
1749 */
1750 
1751 -- Function             : get_predecessors
1752 -- Type                 : Mutually Recursive functions alongwith get_parents_childs
1753 -- Purpose              : Retrieves tasks which are predecessor of the task passed to
1754 --                        this function (p_src_task_ver_id)
1755 -- Return               : Returns with TRUE if
1756 --                        SUCCESSOR(p_orig_succ_task_ver_id) matches any of the retrieved
1757 --                        predecessors
1758 -- Assumptions          : We have started from the PREDECESSOR to which a dependency is
1759 --                        trying to be created
1760 -- Parameters                    Type      Required  Description and Purpose
1761 -- ---------------------------  ------     --------  --------------------------------------------------------
1762 -- p_src_task_ver_id            NUMBER        Y      Task id for which predecessors are to be retieved and checked
1763 -- p_orig_succ_task_ver_id      NUMBER        Y      Task id to which the retrieved predecessors are compared
1764 --
1765 -- Call the function as get_predecessors(PRE,SUCC) where
1766 -- PRE  = predecessor to which a dependency is trying to be created
1767 -- SUCC = successor from which a dependency is trying to be created
1768 FUNCTION get_predecessors( p_src_task_ver_id       IN NUMBER
1769                           ,p_orig_succ_task_ver_id IN NUMBER ) RETURN BOOLEAN IS
1770 CURSOR cur_get_predecessors IS
1771      SELECT por1.object_id_to1 RELATED_TASK
1772      FROM   pa_object_relationships por1
1773      WHERE  por1.relationship_type     = 'D'
1774      AND    LEVEL = 1
1775      AND    por1.object_id_from2 = por1.object_id_to2
1776      START WITH       por1.object_id_from1 = p_src_task_ver_id
1777      CONNECT BY PRIOR por1.object_id_to1   = por1.object_id_from1
1778      AND        PRIOR por1.relationship_type = por1.relationship_type
1779      AND        PRIOR por1.object_id_from2 = por1.object_id_from2
1780      ;
1781 --NOTE : * PRIOR por1.relationship_type = por1.relationship_type
1782 --         is required so as to prevent traversing parent-child dependency relns.
1783 --       * PRIOR por1.object_id_from2 = por1.object_id_from2 in CONNECT clause
1784 --         is required to prevent traversing inter-project dependencies; which can be
1785 --         circular and can give a "ORA-01436: CONNECT BY loop in user data" error
1786 --       * por1.object_id_from2 = por1.object_id_to2 in WHERE clause
1787 --         is required to filter out only those rows which correspond to intra-proj dependencies
1788 BEGIN
1789      FOR rec_predecessors IN cur_get_predecessors LOOP
1790           IF rec_predecessors.related_task = p_orig_succ_task_ver_id
1791           OR get_parents_childs( rec_predecessors.related_task, p_orig_succ_task_ver_id ) = TRUE THEN
1792                RETURN TRUE;
1793           END IF;
1794      END LOOP;
1795 
1796      RETURN FALSE;
1797 END get_predecessors;
1798 
1799 -- Function             : get_parents_childs
1800 -- Type                 : Mutually Recursive functions alongwith get_predecessors
1801 -- Purpose              : Retrieves tasks which are parents or childs, of the task passed to
1802 --                        this function (p_src_task_ver_id)
1803 -- Return               : Returns with TRUE if
1804 --                        SUCCESSOR(p_orig_succ_task_ver_id) matches any of the retrieved
1805 --                        parents/childs
1806 -- Assumptions          : We have started from the PREDECESSOR to which a dependency is
1807 --                        trying to be created
1808 -- Parameters                    Type      Required  Description and Purpose
1809 -- ---------------------------  ------     --------  --------------------------------------------------------
1810 -- p_src_task_ver_id            NUMBER        Y      Task id for which parents/childs are to be retieved and checked
1811 -- p_orig_succ_task_ver_id      NUMBER        Y      Task id to which the retrieved parents/childs are compared
1812 FUNCTION get_parents_childs( p_src_task_ver_id       IN NUMBER
1813                             ,p_orig_succ_task_ver_id IN NUMBER ) RETURN BOOLEAN IS
1814 CURSOR cur_get_parents_childs IS
1815      SELECT por1.object_id_to1 RELATED_TASK
1816      FROM   pa_object_relationships por1
1817      WHERE      por1.relationship_type     = 'S'
1818      AND        por1.relationship_subtype = 'TASK_TO_TASK'
1819      START WITH       por1.object_id_from1 = p_src_task_ver_id
1820                   AND relationship_type = 'S' --bug 3944567
1821      CONNECT BY PRIOR por1.object_id_to1   = por1.object_id_from1
1822      AND        PRIOR por1.relationship_type = por1.relationship_type
1823      UNION
1824      SELECT por2.object_id_from1 RELATED_TASK
1825      FROM   pa_object_relationships por2
1826      WHERE      por2.relationship_type          = 'S'
1827      AND        por2.relationship_subtype = 'TASK_TO_TASK'
1828      START WITH       por2.object_id_to1   = p_src_task_ver_id
1829                   AND relationship_type = 'S' --bug 3944567
1830      CONNECT BY PRIOR por2.object_id_from1 = por2.object_id_to1
1831      AND        PRIOR por2.relationship_type = por2.relationship_type
1832      UNION
1833      SELECT p_src_task_ver_id RELATED_TASK
1834      FROM   dual
1835      ;
1836 
1837    --bug 4145585
1838    Cursor check_intersect IS
1839      select object_id_from1 elem_ver_id
1840        from pa_object_relationships
1841       start with object_id_to1 = p_orig_succ_task_ver_id
1842         and relationship_type = 'D'
1843  connect by  object_id_to1 =  prior object_id_from1
1844         and relationship_type = prior relationship_type
1845         and object_id_to2 = object_id_from2
1846      INTERSECT
1847      select object_id_to1
1848        from pa_object_relationships
1849       start with object_id_to1 = p_src_task_ver_id
1850         and relationship_type = 'S'
1851  connect by prior object_id_to1 = object_id_from1
1852         and relationship_type = prior relationship_type;
1853    l_dummy NUMBER;
1854    --end bug 4145585
1855 
1856 BEGIN
1857    --bug 4145585
1858 /*
1859      FOR rec_parents_childs IN cur_get_parents_childs LOOP
1860           IF rec_parents_childs.related_task = p_orig_succ_task_ver_id
1861           OR get_predecessors( rec_parents_childs.related_task, p_orig_succ_task_ver_id ) = TRUE THEN
1862                RETURN TRUE;
1863           END IF;
1864      END LOOP;
1865 
1866      RETURN FALSE;
1867 */
1868    OPEN check_intersect;
1869    FETCH check_intersect into l_dummy;
1870    IF check_intersect%FOUND THEN
1871      CLOSE check_intersect;
1872      RETURN TRUE;
1873    END IF;
1874    CLOSE check_intersect;
1875 
1876    RETURN FALSE;
1877    --end bug 4145585
1878 
1879 END get_parents_childs;
1880 --============================================================================================
1881 
1882 FUNCTION Check_link_exists(p_project_id number
1883    ,p_link_type    VARCHAR2 DEFAULT 'SHARED'    --bug 4532826
1884 ) return VARCHAR2
1885 IS
1886   CURSOR get_count IS
1887     Select count(1) from pa_object_relationships
1888      where relationship_type IN ('LW', 'LF')
1889        and (object_id_from2 = p_project_id or object_id_to2 = p_project_id);
1890 
1891 -- bug 4532826
1892   CURSOR get_count_fn IS
1893     Select count(1) from pa_object_relationships
1894      where relationship_type = 'LF'
1895        and (object_id_from2 = p_project_id or object_id_to2 = p_project_id);
1896 
1897   CURSOR get_count_wp IS
1898     Select count(1) from pa_object_relationships
1899      where relationship_type = 'LW'
1900        and (object_id_from2 = p_project_id or object_id_to2 = p_project_id);
1901 --end bug 4532826
1902 
1903 
1904   l_cnt NUMBER :=0;
1905 BEGIN
1906   IF p_link_type = 'SHARED'    --bug 4532826
1907   THEN
1908       OPEN get_count;
1909       FETCH get_count into l_cnt;
1910       CLOSE get_count;
1911 --bug 4532826
1912   ELSIF  p_link_type = 'FINANCIAL'
1913   THEN
1914 
1915       OPEN get_count_fn;
1916       FETCH get_count_fn into l_cnt;
1917       CLOSE get_count_fn;
1918 
1919   ELSIF  p_link_type = 'WORKPLAN'
1920   THEN
1921 
1922       OPEN get_count_wp;
1923       FETCH get_count_wp into l_cnt;
1924       CLOSE get_count_wp;
1925 
1926   END IF;
1927  --bug end 4532826
1928 
1929   IF l_cnt > 0 THEN
1930      return 'Y';
1931   END IF;
1932 
1933   return 'N';
1934 END Check_link_exists;
1935 
1936 FUNCTION Check_proj_currency_identical(p_src_project_id NUMBER
1937                                      , p_dest_project_id NUMBER) return VARCHAR2
1938 IS
1939   CURSOR get_proj_curr_code(c_project_id NUMBER) IS
1940   select project_currency_code
1941     from pa_projects_all
1942    where project_id = C_project_id;
1943   l_src_proj_currency_code  VARCHAR2(15);
1944   l_dest_proj_currency_code VARCHAR2(15);
1945 BEGIN
1946   OPEN get_proj_curr_code(p_src_project_id);
1947   FETCH get_proj_curr_code INTO l_src_proj_currency_code;
1948   CLOSE get_proj_curr_code;
1949 
1950   OPEN get_proj_curr_code(p_dest_project_id);
1951   FETCH get_proj_curr_code INTO l_dest_proj_currency_code;
1952   CLOSE get_proj_curr_code;
1953 
1954   IF (l_src_proj_currency_code <> l_dest_proj_currency_code) THEN
1955     return 'N';
1956   END IF;
1957 
1958   return 'Y';
1959 END check_proj_currency_identical;
1960 
1961 FUNCTION check_dependencies_valid(p_new_parent_task_ver_id  IN NUMBER
1962                                  ,p_task_ver_id IN NUMBER) RETURN VARCHAR2
1963 IS
1964   CURSOR get_parent_to_child IS
1965     select count(1)
1966       from pa_object_relationships
1967      where relationship_type = 'D'
1968        and object_id_from1 IN (     --get all tasks in upper branch
1969                select object_id_to1
1970                from pa_object_relationships
1971                start with object_id_to1 = p_new_parent_task_ver_id
1972                       and relationship_type = 'S'
1973                connect by prior object_id_from1  = object_id_to1
1974                    and relationship_type = prior relationship_type
1975                    and prior object_type_from = object_type_to)
1976        and object_id_to1 IN (       --get all tasks in lower branch
1977                select object_id_to1
1978                from pa_object_relationships
1979                start with object_id_to1 = p_task_ver_id
1980                       and relationship_type = 'S'
1981                connect by prior object_id_to1 = object_id_from1
1982                    and relationship_type = prior relationship_type
1983                    and prior object_type_to = object_type_from);
1984 
1985   CURSOR get_child_to_parent IS
1986     select count(1)
1987       from pa_object_relationships
1988      where relationship_type = 'D'
1989        and object_id_from1 IN (    --get tasks in lower branch
1990                select object_id_to1
1991                from pa_object_relationships
1992                start with object_id_to1 = p_task_ver_id
1993                       and relationship_type = 'S'
1994                connect by prior object_id_to1 = object_id_from1
1995                    and relationship_type = prior relationship_type
1996                    and prior object_type_to = object_type_from)
1997        and object_id_to1 IN (     --get tasks in upper branch
1998                select object_id_to1
1999                from pa_object_relationships
2000                start with object_id_to1 = p_new_parent_task_ver_id
2001                       and relationship_type = 'S'
2002                connect by prior object_id_from1  = object_id_to1
2003                    and relationship_type = prior relationship_type
2004                    and prior object_type_from = object_type_to);
2005   l_cnt NUMBER;
2006 
2007 BEGIN
2008   OPEN get_parent_to_child;
2009   FETCH get_parent_to_child INTO l_cnt;
2010   CLOSE get_parent_to_child;
2011   IF l_cnt > 0 THEN
2012     return 'N';
2013   END IF;
2014 
2015   OPEN get_child_to_parent;
2016   FETCH get_child_to_parent INTO l_cnt;
2017   CLOSE get_child_to_parent;
2018   IF l_cnt > 0 THEN
2019     return 'N';
2020   END IF;
2021 
2022   RETURN 'Y';
2023 END check_dependencies_valid;
2024 
2025 -- Begin fix for Bug # 4266540.
2026 
2027 FUNCTION check_task_has_sub_proj(p_project_id NUMBER
2028                  , p_task_id NUMBER
2029                  , p_task_version_id NUMBER := NULL)
2030 return VARCHAR2 is
2031 
2032 cursor cur_sub_project (c_project_id NUMBER, c_task_id NUMBER, c_task_version_id NUMBER) is
2033 select count(pslv.sub_project_id)
2034 from pa_structures_links_v pslv
2035 where pslv.parent_project_id = c_project_id
2036 and pslv.parent_task_id = c_task_id
2037 and pslv.parent_task_version_id = c_task_version_id;
2038 
2039 cursor cur_task_version_id (c_project_id NUMBER, c_task_id NUMBER, c_structure_version_id NUMBER) is
2040 select ppev.element_version_id
2041 from pa_proj_element_versions ppev
2042 where ppev.project_id = c_project_id
2043 and ppev.proj_element_id = c_task_id
2044 and ppev.parent_structure_version_id = c_structure_version_id;
2045 
2046 l_cur_working_str_ver_id        NUMBER := null;
2047 
2048 l_task_version_id               NUMBER := null;
2049 
2050 l_count                         NUMBER := null;
2051 
2052 l_return                        VARCHAR2(1) := null;
2053 
2054 BEGIN
2055 
2056     l_return := 'N';
2057 
2058     if (p_task_version_id is null) then
2059 
2060         -- The calling API in this case is: pa_task_utils.check_create_subtask_ok() which is only
2061         -- called for 'FINANCIAL' tasks.
2062 
2063         l_cur_working_str_ver_id := pa_project_structure_utils.get_fin_struc_ver_id(p_project_id);
2064 
2065             open cur_task_version_id(p_project_id, p_task_id, l_cur_working_str_ver_id);
2066             fetch cur_task_version_id into l_task_version_id;
2067             close cur_task_version_id;
2068 
2069     else
2070 
2071             l_task_version_id := p_task_version_id;
2072 
2073     end if;
2074 
2075         open cur_sub_project(p_project_id, p_task_id, l_task_version_id);
2076         fetch cur_sub_project into l_count;
2077         close cur_sub_project;
2078 
2079         if nvl(l_count,0) > 0 then
2080 
2081                 l_return := 'Y';
2082 
2083         end if;
2084 
2085         return(l_return);
2086 
2087 END check_task_has_sub_proj;
2088 
2089 -- End fix for Bug # 4266540.
2090 
2091 -- Begin fix for Bug # 4411603.
2092 
2093 function is_str_linked_to_working_ver
2094 (p_project_id NUMBER
2095  , p_structure_version_id NUMBER
2096  , p_relationship_type VARCHAR2 := 'LW') return VARCHAR2
2097 is
2098 
2099 l_return_value VARCHAR2(1) := null;
2100 
2101 cursor cur_structure_version_ids (c_object_id_from NUMBER
2102                                   , c_relationship_type VARCHAR2) is
2103 -- Bug # 4757224.
2104 
2105 select 1
2106 from   dual
2107 where exists (select 1
2108               from pa_proj_element_versions pev, pa_object_relationships por, pa_proj_elem_ver_structure ppevs
2109               where pev.parent_structure_version_id = c_object_id_from
2110 	      and pev.element_version_id = por.object_id_from1
2111 	      and por.object_id_to1 = ppevs.element_version_id
2112               -- Bug Fix 5077552
2113               -- Adding the project id to avoid the FTS on ppevs.
2114               and por.object_id_to2 = ppevs.project_id
2115 	      and por.object_type_to = 'PA_STRUCTURES'
2116 	      and por.relationship_type in (c_relationship_type, 'S')
2117 	      and ppevs.status_code='STRUCTURE_WORKING');
2118 
2119 /*
2120 -- Bug # 4737033.
2121 
2122 select ppevs.status_code status_code
2123 from (select por.object_id_to1
2124       from pa_object_relationships por
2125       where por.object_type_to = 'PA_STRUCTURES'
2126       and relationship_type in (c_relationship_type, 'S')
2127       start with por.object_id_from1 = c_object_id_from
2128       connect by prior por.object_id_to1 = por.object_id_from1
2129       and prior relationship_type in (c_relationship_type, 'S')) por
2130       ,pa_proj_elem_ver_structure ppevs
2131 where
2132     por.object_id_to1 = ppevs.element_version_id (+);
2133 
2134 select ppevs.status_code status_code
2135 from pa_object_relationships por, pa_proj_elem_ver_structure ppevs
2136 where por.object_id_to1 = ppevs.element_version_id (+)
2137 and por.object_type_to = 'PA_STRUCTURES'
2138 and relationship_type in (c_relationship_type, 'S')
2139 start with por.object_id_from1 = c_object_id_from
2140 connect by prior por.object_id_to1 = por.object_id_from1
2141 and prior relationship_type in (c_relationship_type, 'S');
2142 
2143 -- Bug # 4737033.
2144 */
2145 
2146 -- Bug # 4757224.
2147 
2148 l_structure_working VARCHAR2(1) := null;
2149 
2150 rec_structure_version_ids cur_structure_version_ids%rowtype;
2151 
2152 begin
2153 
2154 l_return_value := 'N';
2155 
2156 if (pa_project_structure_utils.check_program_flag_enable(p_project_id) = 'Y') then -- Bug # 4742904.
2157 
2158 -- Bug # 4757224.
2159 
2160     open cur_structure_version_ids(p_structure_version_id, p_relationship_type);
2161     fetch cur_structure_version_ids into rec_structure_version_ids;
2162 
2163     if cur_structure_version_ids%NOTFOUND then
2164         l_return_value:='N';
2165     else
2166         l_return_value:='Y';
2167     end if;
2168 
2169     close cur_structure_version_ids;
2170 
2171 /*
2172 for rec_structure_version_ids in cur_structure_version_ids(p_structure_version_id, p_relationship_type)
2173 loop
2174 
2175     if (rec_structure_version_ids.status_code = 'STRUCTURE_WORKING') then
2176 
2177        l_return_value := 'Y';
2178 
2179     end if;
2180 
2181 end loop;
2182 */
2183 
2184 -- Bug # 4757224.
2185 
2186 end if; -- Bug # 4742904.
2187 
2188 return(l_return_value);
2189 
2190 end is_str_linked_to_working_ver;
2191 
2192 -- End fix for Bug # 4411603.
2193 
2194 --bug 4541039
2195 
2196 FUNCTION Check_parent_project_Exists
2197 (
2198      p_project_id NUMBER,
2199      p_structure_ver_id NUMBER
2200     ,p_link_type        VARCHAR2     default 'SHARED'    --bug 4541039
2201 )RETURN VARCHAR2
2202 IS
2203     CURSOR check_parentproj_exists IS
2204     SELECT '1'
2205        from     pa_object_relationships por
2206        WHERE p_structure_ver_id = por.object_id_to1
2207        and por.object_id_to2 = p_project_id
2208        and por.relationship_type IN ('LW', 'LF');
2209 
2210 
2211     CURSOR check_parentproj_exists_wp IS
2212     SELECT '1'
2213        from    pa_object_relationships por
2214        WHERE p_structure_ver_id = por.object_id_to1
2215        and por.object_id_to2 = p_project_id
2216        and por.relationship_type = 'LW';
2217 
2218     CURSOR check_parentproj_exists_fn IS
2219     SELECT '1'
2220         from   pa_object_relationships por
2221        WHERE p_structure_ver_id = por.object_id_to1
2222        and por.object_id_to2 = p_project_id
2223        and por.relationship_type = 'LF';
2224 
2225     l_dummy VARCHAR2(1);
2226 BEGIN
2227     IF p_link_type = 'SHARED'  --bug 4541039
2228     THEN
2229         OPEN check_parentproj_exists;
2230         FETCH check_parentproj_exists INTO l_dummy;
2231         IF check_parentproj_exists%NOTFOUND THEN
2232         CLOSE check_parentproj_exists;
2233           RETURN 'N';
2234         ELSE
2235           CLOSE check_parentproj_exists;
2236           RETURN 'Y';
2237         END IF;
2238     ELSIF p_link_type = 'WORKPLAN'
2239     THEN
2240         OPEN check_parentproj_exists_wp;
2241         FETCH check_parentproj_exists_wp INTO l_dummy;
2242         IF check_parentproj_exists_wp%NOTFOUND THEN
2243         CLOSE check_parentproj_exists_wp;
2244           RETURN 'N';
2245         ELSE
2246           CLOSE check_parentproj_exists_wp;
2247           RETURN 'Y';
2248         END IF;
2249     ELSIF p_link_type = 'FINANCIAL'
2250     THEN
2251         OPEN check_parentproj_exists_fn;
2252         FETCH check_parentproj_exists_fn INTO l_dummy;
2253         IF check_parentproj_exists_fn%NOTFOUND THEN
2254         CLOSE check_parentproj_exists_fn;
2255           RETURN 'N';
2256         ELSE
2257           CLOSE check_parentproj_exists_fn;
2258           RETURN 'Y';
2259         END IF;
2260     END IF;
2261 
2262 END Check_parent_project_Exists;
2263 
2264 --bug 4619824
2265 FUNCTION Check_subproject_link_exists(p_project_id number
2266    ,p_link_type    VARCHAR2 DEFAULT 'SHARED'    --bug 4532826
2267 ) return VARCHAR2
2268 IS
2269   CURSOR get_count IS
2270     Select count(1) from pa_object_relationships
2271      where relationship_type IN ('LW', 'LF')
2272        and object_id_from2 = p_project_id;
2273 
2274   CURSOR get_count_fn IS
2275     Select count(1) from pa_object_relationships
2276      where relationship_type = 'LF'
2277        and object_id_from2 = p_project_id;
2278 
2279   CURSOR get_count_wp IS
2280     Select count(1) from pa_object_relationships
2281      where relationship_type = 'LW'
2282        and (object_id_from2 = p_project_id);
2283 
2284 
2285   l_cnt NUMBER :=0;
2286 BEGIN
2287   IF p_link_type = 'SHARED'
2288   THEN
2289       OPEN get_count;
2290       FETCH get_count into l_cnt;
2291       CLOSE get_count;
2292   ELSIF  p_link_type = 'FINANCIAL'
2293   THEN
2294 
2295       OPEN get_count_fn;
2296       FETCH get_count_fn into l_cnt;
2297       CLOSE get_count_fn;
2298 
2299   ELSIF  p_link_type = 'WORKPLAN'
2300   THEN
2301 
2302       OPEN get_count_wp;
2303       FETCH get_count_wp into l_cnt;
2304       CLOSE get_count_wp;
2305 
2306   END IF;
2307 
2308   IF l_cnt > 0 THEN
2309      return 'Y';
2310   END IF;
2311 
2312   return 'N';
2313 END Check_subproject_link_exists;
2314 
2315 
2316 end PA_RELATIONSHIP_UTILS;