DBA Data[Home] [Help]

PACKAGE BODY: APPS.PA_RELATIONSHIP_UTILS

Source


1 package body PA_RELATIONSHIP_UTILS as
2 /*$Header: PAXRELUB.pls 120.18.12000000.2 2007/06/28 16:19:32 rmandali 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,
307                                                   x_err_stage => l_err_stage
308                                                   );
309               IF (l_err_code <> 0) THEN
310 
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;
356        (l_financial_to = 'N') THEN
353 
354     If (l_financial_from = 'Y') and
355        (l_workplan_to = 'Y') and
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 
495    ,p_element_version_id_to   IN NUMBER
492   procedure Check_Create_Association_Ok
493   (
494     p_element_version_id_from 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          ;
555      l_return_value    VARCHAR2(1) := 'N';
556   BEGIN
557 
558        OPEN cur_parent_lp_link;
559        FETCH cur_parent_lp_link INTO l_return_value;
560        CLOSE cur_parent_lp_link;
561 
562        RETURN l_return_value;
563   END parent_LP_link_exists;
564 
565 -- API name                      : check_create_intra_dep_ok
566 -- Type                          : Private Check procedure
567 -- Pre-reqs                      : None
568 -- Return Value                  : Returns error status
569 -- Parameters
570 --  p_pre_project_id    IN NUMBER
571 --  p_pre_task_ver_id   IN NUMBER
572 --  p_project_id        IN NUMBER
573 --  p_task_ver_id       IN NUMBER
574 --
575 --
576 --  History
577 --
578 --  19-DEC-03   Maansari             -Created
579 --
580 --  Description
581 --
582 -- This check procedure check s the following business rules and returns status 'E' with proper
583 -- error message if any of the rules fails.
584 --a.    No duplicates.
585 --b.    No circular dependencies between two or more tasks.
586 --c.    A task cannot depend on itself.
587 --d.    You cannot create a dependency from an object (predecessor) to you (successor) if that object has
588 --      subtasks (successor) that depend on you (predecessor).
589 --e.    You cannot create a dependency between objects that are in the same direct path from lowest
590 --      node to the top node.
591 --
592 -- Notes:  The p_pre_<> paramaters are for predecessor tasks and stored in object_id_to1 colunmn
593 --         of pa_object_relationships.
594 
595   procedure check_create_intra_dep_ok(
596    p_pre_project_id    IN NUMBER
597   ,p_pre_task_ver_id   IN NUMBER
598   ,p_project_id        IN NUMBER
599   ,p_task_ver_id       IN NUMBER
600   ,x_return_status                     OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
601   ,x_msg_count                         OUT  NOCOPY NUMBER --File.Sql.39 bug 4440895
602   ,x_msg_data                          OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
603   ) IS
604 
605     CURSOR cur_a
606     IS
607       SELECT 'x'
608         FROM pa_object_relationships
609        WHERE object_id_from1 = p_task_ver_id
610          AND object_id_from2 = p_project_id
611          AND object_id_to1 = p_pre_task_ver_id
612          AND object_id_to2 = p_pre_project_id
613          AND relationship_type = 'D'
614        ;
615 
616     CURSOR cur_b
617     IS
618       SELECT 'x'
619                       FROM (
620                         SELECT object_id_to1
621                         FROM pa_object_relationships por2
625                         AND        relationship_type    = 'D'                          --bug 3944567
622                         WHERE relationship_type = 'D'
623                         AND   por2.object_id_from2 = por2.object_id_to2                --Bug 3629024
624                         START WITH por2.object_id_from1 = p_pre_task_ver_id
626                         CONNECT BY por2.object_id_from1 = PRIOR por2.object_id_to1
627                         AND        relationship_type    = PRIOR relationship_type
628                         AND        relationship_type    = 'D'
629                         AND        por2.object_id_from2 = PRIOR por2.object_id_from2 ) --Bug 3629024
630                       where object_id_to1 = p_task_ver_id;
631 
632    /* the successor is a prdecessor of the sub-tasks of the predecessor.*/
633 /*Commented out for bug 3629024
634    CURSOR cur_d
635    IS
636     SELECT 'x'
637       FROM pa_object_relationships por1
638      WHERE por1.relationship_type = 'D'
639        AND por1.object_id_to1 = p_task_ver_id
640        AND por1.object_id_from1 IN
641         ( SELECT por2.object_id_to1
642                FROM pa_object_relationships por2
643               START WITH por2.object_id_from1 = p_pre_task_ver_id
644             CONNECT BY por2.object_id_from1 = prior por2.object_id_to1
645                 AND por2.relationship_type = prior por2.relationship_type
646                 AND por2.relationship_type = 'S')
647     ;
648 */
649    CURSOR cur_e1_get_parent( c_child_task_ver_id NUMBER )
650    IS
651     SELECT object_id_from1
652       FROM pa_object_relationships
653      where object_id_to1 = c_child_task_ver_id
654      and relationship_type = 'S'
655       ;
656 
657    l_dummy_char          VARCHAR2(1);
658    l_child_task_ver_id   NUMBER;
659    l_parent_task_ver_id  NUMBER;
660 BEGIN
661 
662     IF p_pre_project_id IS NULL OR
663        p_pre_task_ver_id IS NULL OR
664        p_project_id IS NULL OR
665        p_task_ver_id   IS NULL
666     THEN
667         x_return_status := FND_API.G_RET_STS_ERROR;
668         x_msg_count := FND_MSG_PUB.count_msg;
669         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
670                              ,p_msg_name       => 'PA_PS_PARAMS_NULL');
671         raise FND_API.G_EXC_ERROR;
672     END IF;
673 
674     IF p_pre_project_id <> p_project_id
675     THEN
676         x_return_status := FND_API.G_RET_STS_ERROR;
677         x_msg_count := FND_MSG_PUB.count_msg;
678         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
679                              ,p_msg_name       => 'PA_PS_NOT_INTRA_DEPND');
680         raise FND_API.G_EXC_ERROR;
681     END IF;
682 
683     --c) a task cannot depend on it-self
684     IF p_pre_task_ver_id = p_task_ver_id
685     THEN
686         x_return_status := FND_API.G_RET_STS_ERROR;
687         x_msg_count := FND_MSG_PUB.count_msg;
688         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
689                              ,p_msg_name       => 'PA_PS_NO_SELF_DEPDN');
690         raise FND_API.G_EXC_ERROR;
691     END IF;
692 
693     OPEN cur_a;
694     FETCH cur_a INTO l_dummy_char;
695     IF cur_a%FOUND
696     THEN
697         x_return_status := FND_API.G_RET_STS_ERROR;
698         x_msg_count := FND_MSG_PUB.count_msg;
699         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
700                              ,p_msg_name       => 'PA_PS_DEPND_EXISTS');
701         raise FND_API.G_EXC_ERROR;
702     END IF;
703     CLOSE cur_a;
704 
705     OPEN cur_b;
706     FETCH cur_b INTO l_dummy_char;
707     IF cur_b%FOUND
708     THEN
709         x_return_status := FND_API.G_RET_STS_ERROR;
710         x_msg_count := FND_MSG_PUB.count_msg;
711         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
712                              ,p_msg_name       => 'PA_PS_CIRCLR_DEPND_EXISTS');
713         raise FND_API.G_EXC_ERROR;
714     END IF;
715     CLOSE cur_b;
716 
717 /*  Following code commented out for bug 3629024
718     OPEN cur_d;
719     FETCH cur_d INTO l_dummy_char;
720     IF cur_d%FOUND
721     THEN
722         x_return_status := FND_API.G_RET_STS_ERROR;
723         x_msg_count := FND_MSG_PUB.count_msg;
724         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
725                              ,p_msg_name       => 'PA_PS_SUBTASKS_DEPND_EXISTS');
726         raise FND_API.G_EXC_ERROR;
727     END IF;
728     CLOSE cur_d;
729 */
730     --Bug 3629024 : Check for the existence of a closed path
731     --This bug fix is for rule D
732     IF get_parents_childs(p_pre_task_ver_id, p_task_ver_id) = TRUE THEN
733         x_return_status := FND_API.G_RET_STS_ERROR;
734         x_msg_count     := FND_MSG_PUB.count_msg;
735         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
736                              ,p_msg_name       => 'PA_PS_SUBTASKS_DEPND_EXISTS');
737         raise FND_API.G_EXC_ERROR;
738     END IF;
739 
740 /*    --check if predecessor is parent in the same line of hierarchy.
741     OPEN cur_e1;
742     FETCH cur_e1 INTO l_dummy_char;
743     IF cur_e1%FOUND
744     THEN
745         x_return_status := FND_API.G_RET_STS_ERROR;
746         x_msg_count := FND_MSG_PUB.count_msg;
747         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
751     CLOSE cur_e1;
748                              ,p_msg_name       => 'PA_PS_NO_PARENT_PRED');
749         raise FND_API.G_EXC_ERROR;
750     END IF;
752 
753     --check if predecessor is child in the same line of hierarchy.
754     OPEN cur_e2;
755     FETCH cur_e2 INTO l_dummy_char;
756     IF cur_e2%FOUND
757     THEN
758         x_return_status := FND_API.G_RET_STS_ERROR;
759         x_msg_count := FND_MSG_PUB.count_msg;
760         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
761                              ,p_msg_name       => 'PA_PS_NO_CHILD_PRED');
762         raise FND_API.G_EXC_ERROR;
763     END IF;
764     CLOSE cur_e2;
765 */
766 
767   /* check for predecessor is parent */
768   l_child_task_ver_id := p_task_ver_id;
769   WHILE ( l_child_task_ver_id IS NOT NULL ) LOOP
770        OPEN cur_e1_get_parent( l_child_task_ver_id);
771        FETCH cur_e1_get_parent INTO l_parent_task_ver_id; /* predecessor is parent */
772        IF cur_e1_get_parent%NOTFOUND THEN
773          close cur_e1_get_parent;
774          exit;
775        END IF;
776        CLOSE cur_e1_get_parent;
777 
778        IF l_parent_task_ver_id IS NOT NULL AND
779           l_parent_task_ver_id = p_pre_task_ver_id
780        THEN
781           x_return_status := FND_API.G_RET_STS_ERROR;
782           x_msg_count := FND_MSG_PUB.count_msg;
783           PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
784                                ,p_msg_name       => 'PA_PS_NO_PARENT_PRED');
785           raise FND_API.G_EXC_ERROR;
786        ELSE
787           l_child_task_ver_id := l_parent_task_ver_id;
788        END IF;
789   END LOOP;
790 
791 
792   /* check for predecessor is child or successor is a parent */
793   /* starting from predecessor, find out the parent up the hierarchy and compare the
794      successor with the parent found. if successor is same as the parent found then it means
795      the predecessor is a child of the succeesor down the line in the hierarchy */
796   /* it is not possible to traverse down the hierarchy to find out whether the predecessor is a
797      child in the same line of successsor starting from the suceesor therefore traversing up
798      the hierarchy starting from predecessor*/
799 
800   l_child_task_ver_id := p_pre_task_ver_id;
801   WHILE ( l_child_task_ver_id IS NOT NULL ) LOOP
802        OPEN cur_e1_get_parent( l_child_task_ver_id);
803        FETCH cur_e1_get_parent INTO l_parent_task_ver_id;
804        IF cur_e1_get_parent%NOTFOUND THEN
805          close cur_e1_get_parent;
806          exit;
807        END IF;
808        CLOSE cur_e1_get_parent;
809 
810        IF l_parent_task_ver_id IS NOT NULL AND
811           l_parent_task_ver_id = p_task_ver_id  /* is succssor a parent in the same line of hierarcgy*/
812        THEN
813           x_return_status := FND_API.G_RET_STS_ERROR;
814           x_msg_count := FND_MSG_PUB.count_msg;
815           PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
816                                ,p_msg_name       => 'PA_PS_NO_CHILD_PRED');
817           raise FND_API.G_EXC_ERROR;
818        ELSE
819           l_child_task_ver_id := l_parent_task_ver_id;
820        END IF;
821   END LOOP;
822 
823 
824   EXCEPTION
825     when FND_API.G_EXC_ERROR then
826       x_return_status := FND_API.G_RET_STS_ERROR;
827       x_msg_count := FND_MSG_PUB.count_msg;
828     when OTHERS then
829       x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
830       x_msg_count := 1;     -- 4537865 : RESET OUT param
831       x_msg_data := SUBSTRB(SQLERRM,1,240);     -- 4537865 : RESET OUT PARAM
832       fnd_msg_pub.add_exc_msg(p_pkg_name       => 'PA_RELATIONSHIOP_UTILS',
833                               p_procedure_name => 'check_create_intra_dep_ok',
834                               p_error_text     => x_msg_data ); -- 4537865
835       raise;
836 
837 END check_create_intra_dep_ok;
838 
839 -- API name                      : check_create_intra_dep_ok
840 -- Type                          : Private Check procedure
841 -- Pre-reqs                      : None
842 -- Return Value                  : Returns error status
843 -- Parameters
844 --  p_pre_project_id    IN NUMBER
845 --  p_pre_task_ver_id   IN NUMBER
846 --  p_project_id        IN NUMBER
847 --  p_task_ver_id       IN NUMBER
848 --
849 --
850 --  History
851 --
852 --  19-DEC-03   Maansari             -Created
853 --
854 --  Description
855 --
856 -- This check procedure check s the following business rules and returns status 'E' with proper
857 -- error message if any of the rules fails.
858 --a.    No duplicates.
859 -- Notes:  The p_pre_<> paramaters are for predecessor tasks and stored in object_id_to1 colunmn
860 --         of pa_object_relationships.
861 
862   procedure check_create_inter_dep_ok(
863    p_pre_project_id    IN NUMBER
864   ,p_pre_task_ver_id   IN NUMBER
865   ,p_project_id        IN NUMBER
866   ,p_task_ver_id       IN NUMBER
867   ,x_return_status                     OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
868   ,x_msg_count                         OUT  NOCOPY NUMBER --File.Sql.39 bug 4440895
869   ,x_msg_data                          OUT  NOCOPY VARCHAR2 --File.Sql.39 bug 4440895
870   ) IS
871 
872     CURSOR cur_a
873     IS
874       SELECT 'x'
878          AND object_id_to1 = p_pre_task_ver_id
875         FROM pa_object_relationships
876        WHERE object_id_from1 = p_task_ver_id
877          AND  object_id_from2 = p_project_id
879          AND object_id_to2 = p_pre_project_id
880          AND relationship_type = 'D'
881        ;
882 
883    CURSOR CUR_valid_sucsr_proj_task
884    IS
885     SELECT 'x'
886       FROM pa_proj_element_versions
887      WHERE project_id = p_project_id
888       AND element_version_id = p_task_ver_id
889      ;
890 
891 
892    CURSOR CUR_valid_pred_proj_task
893    IS
894     SELECT 'x'
895       FROM pa_proj_element_versions
896      WHERE project_id = p_pre_project_id
897       AND element_version_id = p_pre_task_ver_id
898      ;
899 
900    l_dummy_char   VARCHAR2(1);
901 
902 -- Begin fix for Bug # Bug # 4256435.
903 
904 cursor cur_sub_proj_hierarchy(c_pre_project_id NUMBER) is
905 -- This query selects all the parent projects of the predecessor project.
906 select por.object_id_from1 task_ver_id, por.object_id_from2 project_id
907 from pa_object_relationships por
908 where por.relationship_type in ('LW', 'LF')
909 start with por.object_id_to2 = c_pre_project_id
910 connect by prior por.object_id_from2 = por.object_id_to2
911 and prior por.relationship_type = por.relationship_type
912 and por.relationship_type in ('LW', 'LF')
913 union all
914 -- This query selects all the child projects of the predecessor project.
915 select por.object_id_to1 task_ver_id, por.object_id_to2 project_id
916 from pa_object_relationships por
917 where por.relationship_type in ('LW', 'LF')
918 start with por.object_id_from2 = c_pre_project_id
919 connect by prior por.object_id_to2 = por.object_id_from2
920 and prior por.relationship_type = por.relationship_type
921 and por.relationship_type in ('LW', 'LF');
922 
923 rec_sub_proj_hierarchy cur_sub_proj_hierarchy%ROWTYPE;
924 
925 cursor cur_linking_task(c_task_ver_id NUMBER, c_linking_task_ver_id NUMBER) is
926 select 'Y'
927 from pa_object_relationships por
928 where por.object_id_from1 = c_task_ver_id
929 and por.object_id_to1 = c_linking_task_ver_id
930 and por.relationship_type = 'S';
931 
932 l_link_exists   VARCHAR2(1) := 'N';
933 
934 -- End fix for Bug # Bug # 4256435.
935 
936 BEGIN
937 
938     x_return_status := FND_API.G_RET_STS_SUCCESS;
939 
940     --check valid for null parameters
941     IF p_pre_project_id IS NULL OR
942        p_pre_task_ver_id IS NULL OR
943        p_project_id IS NULL OR
944        p_task_ver_id   IS NULL
945     THEN
946         x_return_status := FND_API.G_RET_STS_ERROR;
947         x_msg_count := FND_MSG_PUB.count_msg;
948         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
949                              ,p_msg_name       => 'PA_PS_PARAMS_NULL');
950         raise FND_API.G_EXC_ERROR;
951     END IF;
952 
953     --check for inter projects. The successor project and predecssor projects should be different.
954     IF p_pre_project_id = p_project_id
955     THEN
956         x_return_status := FND_API.G_RET_STS_ERROR;
957         x_msg_count := FND_MSG_PUB.count_msg;
958         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
959                              ,p_msg_name       => 'PA_PS_NOT_INTER_DEPND');
960         raise FND_API.G_EXC_ERROR;
961     END IF;
962 
963 -- Begin fix for Bug # Bug # 4256435.
964 
965         for rec_sub_proj_hierarchy in cur_sub_proj_hierarchy(p_pre_project_id)
966         loop
967 
968                 if (rec_sub_proj_hierarchy.project_id = p_project_id) then
969 
970                         open  cur_linking_task(p_task_ver_id, rec_sub_proj_hierarchy.task_ver_id);
971                         fetch cur_linking_task into l_link_exists;
972                         close cur_linking_task;
973 
974                         if (l_link_exists = 'Y') then
975 
976                                 x_return_status := FND_API.G_RET_STS_ERROR;
977                                 x_msg_count := FND_MSG_PUB.count_msg;
978 
979                                 PA_UTILS.ADD_MESSAGE(p_app_short_name  => 'PA'
980                                                      , p_msg_name       => 'PA_WP_PRGM_EXISTS_NO_DEP');
981 
982                                 raise FND_API.G_EXC_ERROR;
983 
984                         end if;
985                 end if;
986 
987         end loop;
988 
989 -- End fix for Bug # Bug # 4256435.
990 
991 /* do we really need this validation here?
992     --validate successor project id and task ver id combination.
993     OPEN cur_valid_sucsr_proj_task;
994     FETCH cur_valid_sucsr_proj_task INTO l_dummy;
995     IF cur_valid_sucsr_proj_task%NOTFOUND
996     THEN
997         x_return_status := FND_API.G_RET_STS_ERROR;
998         x_msg_count := FND_MSG_PUB.count_msg;
999         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
1000                              ,p_msg_name       => 'PA_PS_INV_SUCSR_PRJ_TSK');
1001         raise FND_API.G_EXC_ERROR;
1002     END IF;
1003     CLOSE cur_valid_sucsr_proj_task;
1004 
1005     --validate predecessor project id and task ver id combination.
1006     OPEN cur_valid_pred_proj_task;
1007     FETCH cur_valid_pred_proj_task INTO l_dummy;
1011         x_msg_count := FND_MSG_PUB.count_msg;
1008     IF cur_valid_pred_proj_task%NOTFOUND
1009     THEN
1010         x_return_status := FND_API.G_RET_STS_ERROR;
1012         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
1013                              ,p_msg_name       => 'PA_PS_INV_PRED_PRJ_TSK');
1014         raise FND_API.G_EXC_ERROR;
1015     END IF;
1016     CLOSE cur_valid_pred_proj_task;
1017 */
1018 
1019     --check for duplicate dependency.
1020     OPEN cur_a;
1021     FETCH cur_a INTO l_dummy_char;
1022     IF cur_a%FOUND
1023     THEN
1024         x_return_status := FND_API.G_RET_STS_ERROR;
1025         x_msg_count := FND_MSG_PUB.count_msg;
1026         PA_UTILS.ADD_MESSAGE( p_app_short_name => 'PA'
1027                              ,p_msg_name       => 'PA_PS_DEPND_EXISTS');
1028         raise FND_API.G_EXC_ERROR;
1029     END IF;
1030     CLOSE cur_a;
1031 
1032   EXCEPTION
1033     when FND_API.G_EXC_ERROR then
1034       x_return_status := FND_API.G_RET_STS_ERROR;
1035       x_msg_count := FND_MSG_PUB.count_msg;
1036     when OTHERS then
1037       x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
1038       x_msg_count := 1;         -- 4537865 : RESET OUT param
1039       x_msg_data := SUBSTRB(SQLERRM,1,240);     -- 4537865 : RESET OUT PARAM
1040       fnd_msg_pub.add_exc_msg(p_pkg_name       => 'PA_RELATIONSHIOP_UTILS',
1041                               p_procedure_name => 'check_create_inter_dep_ok',
1042                               p_error_text     => x_msg_data); -- 4537865
1043       raise;
1044 
1045 END check_create_inter_dep_ok;
1046 
1047 
1048 FUNCTION DISPLAY_PREDECESSORS
1049   ( p_element_version_id IN NUMBER)
1050   RETURN  VARCHAR2 IS
1051 --
1052 -- To modify this template, edit file FUNC.TXT in TEMPLATE
1053 -- directory of SQL Navigator
1054 --
1055 -- Purpose: Briefly explain the functionality of the function
1056 --
1057 -- MODIFICATION HISTORY
1058 -- Person      Date    Comments
1059 -- ---------   ------  -------------------------------------------
1060 -- SMUKKA      01/28/2004   Initial Version
1061 
1062    l_task_name_list                 VARCHAR2(1220):=NULL; --bug 4141897
1063    l_task_count                     NUMBER:=0;
1064 CURSOR cur_task_names( c_element_version_id NUMBER )
1065   IS
1066     SELECT ppe.name task_name
1067       FROM pa_proj_element_versions ppev,
1068            pa_proj_elements ppe
1069      WHERE ppev.proj_element_id = ppe.proj_element_id
1070        and ppev.project_id = ppe.project_id
1071        AND ppev.element_version_id IN (SELECT object_id_to1
1072                                          FROM pa_object_relationships por
1073                                         WHERE por.object_id_from1   = c_element_version_id
1074                                           AND por.object_id_from2   = por.object_id_to2
1075                                           AND por.object_type_from  = 'PA_TASKS' --4141109 Replaced LIKE with Equijoin
1076                                           AND por.object_type_to    = 'PA_TASKS' --4141109 Replaced LIKE with Equijoin
1077                                           AND por.relationship_type = 'D');  --4141109 Replaced LIKE with Equijoin
1078     l_cur_task_names_rec  cur_task_names%ROWTYPE;
1079 BEGIN
1080    OPEN cur_task_names(p_element_version_id);
1081    LOOP
1082       FETCH cur_task_names into l_cur_task_names_rec;
1083       IF cur_task_names%NOTFOUND THEN
1084          EXIT;
1085       ELSE
1086          l_task_count:=l_task_count+1;
1087          IF l_task_count = 1 THEN
1088             l_task_name_list:= l_task_name_list||l_cur_task_names_rec.task_name;
1089          ELSIF l_task_count > 5 THEN
1090                l_task_name_list:= l_task_name_list||'...';
1091          ELSE
1092             l_task_name_list := l_task_name_list||','||l_cur_task_names_rec.task_name;
1093          END IF;
1094       END IF;
1095    END LOOP;
1096    CLOSE cur_task_names;
1097    RETURN l_task_name_list ;
1098 EXCEPTION
1099    WHEN OTHERS THEN
1100        NULL ;
1101 END DISPLAY_PREDECESSORS;
1102 
1103 
1104 FUNCTION ChecK_dep_exists(p_element_version_id IN NUMBER)
1105   RETURN VARCHAR2
1106 IS
1107   CURSOR get_dependency IS
1108     SELECT 1 from pa_object_relationships
1109      where relationship_type = 'D'
1110        and (object_id_from1 = p_element_version_id OR
1111             object_id_to1 = p_element_version_id);
1112   l_dummy NUMBER;
1113 BEGIN
1114   OPEN get_Dependency;
1115   FETCH get_Dependency into l_dummy;
1116   IF get_dependency%FOUND THEN
1117     CLOSE get_dependency;
1118     return 'Y';
1119   END IF;
1120   CLOSE get_Dependency;
1121   return 'N';
1122 END CHECK_DEP_EXISTS;
1123 
1124 
1125 FUNCTION Is_Proj_Top_Program(p_project_id IN NUMBER)
1126   RETURN VARCHAR2
1127 IS
1128   --Bug No 3634315 Performance Fix, to avoid full table scan on pa_object_relationships table.
1129 /*  CURSOR c1 IS
1130     select 1
1131       from pa_object_relationships
1132      where relationship_type IN ('LW', 'LF')
1133        and object_id_to2 = p_project_id;*/
1134     CURSOR c1 IS
1135     select 1
1136       from pa_object_relationships por,
1137            pa_proj_element_versions ppev
1138      where por.relationship_type IN ('LW', 'LF')
1139        and ppev.element_version_id = por.object_id_to1
1140        and por.object_id_to2 = ppev.project_id
1144     select 1
1141        and por.object_id_to2 = p_project_id;
1142 
1143   CURSOR c2 IS
1145       from pa_object_relationships
1146      where relationship_type IN ('LW', 'LF')
1147        and object_id_from2 = p_project_id;
1148 
1149   l_dummy number;
1150 BEGIN
1151   OPEN c1;
1152   FETCH c1 into l_dummy;
1153   IF c1%FOUND THEN
1154     CLOSE c1;
1155     return 'N';
1156   END IF;
1157   CLOSE c1;
1158 
1159   OPEN c2;
1160   FETCH c2 into l_dummy;
1161   IF c2%NOTFOUND THEN
1162     CLOSE c2;
1163     return 'N';
1164   END IF;
1165   CLOSE c2;
1166 
1167   return 'Y';
1168 END Is_Proj_Top_Program;
1169 
1170 FUNCTION Is_Proj_Sub_Project(p_project_id IN NUMBER)
1171   RETURN VARCHAR2
1172 IS
1173   --Bug No 3634315 Performance Fix, to avoid full table scan on pa_object_relationships table.
1174 /*  CURSOR c1 IS
1175     select 1
1176       from pa_object_relationships
1177      where relationship_type IN ('LW', 'LF')
1178        and object_id_to2 = p_project_id;*/
1179     CURSOR c1 IS
1180     select 1
1181       from pa_object_relationships por,
1182            pa_proj_element_versions ppev
1183      where por.relationship_type IN ('LW', 'LF')
1184        and ppev.element_version_id = por.object_id_to1
1185        and por.object_id_to2 = ppev.project_id
1186        and por.object_id_to2 = p_project_id;
1187   l_dummy NUMBER;
1188 BEGIN
1189   open c1;
1190   FETCH c1 into l_dummy;
1191   IF c1%NOTFOUND THEN
1192     CLOSE c1;
1193     return 'N';
1194   END IF;
1195   CLOSE c1;
1196 
1197   return 'Y';
1198 END Is_Proj_Sub_Project;
1199 
1200 FUNCTION DISABLE_SYS_PROG_OK(p_project_id NUMBER)
1201   RETURN varchar2
1202 IS
1203   CURSOR c1 IS
1204     select 1
1205     from pa_object_relationships
1206     where relationship_type IN ('LW', 'LF')
1207     and object_id_from2 = p_project_id;
1208   l_dummy NUMBER;
1209 BEGIN
1210   OPEN c1;
1211   FETCH c1 into l_dummy;
1212   IF c1%found then
1213     CLOSE c1;
1214     return 'N';
1215   END IF;
1216   CLOSE c1;
1217   return 'Y';
1218 END DISABLE_SYS_PROG_OK;
1219 
1220 FUNCTION DISABLE_MULTI_PROG_OK(p_project_id NUMBER)
1221   RETURN varchar2
1222 IS
1223   --Bug No 3634315 Performance Fix, to avoid full table scan on pa_object_relationships table.
1224 /*  CURSOR c1(c_parent_project_id NUMBER, c_child_project_id NUMBER) IS
1225     select count(1)
1226     from pa_object_relationships
1227     where relationship_type IN ('LW', 'LF')
1228     and object_id_to2 = c_child_project_id
1229     and object_id_from1 <> c_parent_project_id;*/
1230   CURSOR c1(c_parent_project_id NUMBER, c_child_project_id NUMBER) IS
1231   select count(1)
1232     from pa_object_relationships por,
1233          pa_proj_element_versions ppev
1234     where relationship_type IN ('LW', 'LF')
1235     and ppev.element_version_id = object_id_to1
1236     and por.object_id_to2 = ppev.project_id
1237     and object_id_to2 = c_child_project_id
1238     and object_id_from2 <> c_parent_project_id;--bug 4244482
1239 
1240   CURSOR c2 IS
1241     select object_id_from2, object_Id_to2
1242       from pa_object_relationships
1243      where relationship_type IN ('LW')   --bug 3962849
1244   start with object_id_from2 = p_project_id
1245          and relationship_type = 'LW'
1246   connect by prior object_id_to2 = object_id_from2
1247          and prior relationship_type = relationship_type;
1248 
1249   CURSOR c3 IS
1250     select object_id_from2, object_Id_to2
1251       from pa_object_relationships
1252      where relationship_type IN ('LF')   --bug 3962849
1253   start with object_id_from2 = p_project_id
1254          and relationship_type = 'LF'
1255   connect by prior object_id_to2 = object_id_from2
1256          and prior relationship_type = relationship_type;
1257 
1258   l_parent_proj_id NUMBER;
1259   l_child_proj_id NUMBER;
1260   l_count NUMBER;
1261 BEGIN
1262   OPEN c2;
1263   LOOP
1264     FETCH c2 into l_parent_proj_id, l_child_proj_id;
1265     EXIT WHEN C2%NOTFOUND;
1266     OPEN c1(l_parent_proj_id, l_child_proj_id);
1267     FETCH c1 INTO l_count;
1268     IF l_count > 0 THEN
1269       CLOSE c1;
1270       CLOSE c2;
1271       return 'N';
1272     END IF;
1273     CLOSE c1;
1274   END LOOP;
1275   CLOSE c2;
1276 
1277   OPEN c3;
1278   LOOP
1279     FETCH c3 into l_parent_proj_id, l_child_proj_id;
1280     EXIT WHEN C3%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 c3;
1286       return 'N';
1287     END IF;
1288     CLOSE c1;
1289   END LOOP;
1290   CLOSE c3;
1291 
1292   return 'Y';
1293 END DISABLE_MULTI_PROG_OK;
1294 
1295 FUNCTION CREATE_SUB_PROJ_ASSO_OK(p_task_version_id NUMBER, p_project_id NUMBER,
1296                                  p_structure_type VARCHAR2 := 'WORKPLAN')
1297   RETURN VARCHAR2
1298 IS
1299   CURSOR get_project_id(c_element_version_id NUMBER) IS
1300     select project_id
1301       from pa_proj_element_versions
1302      where element_version_id = c_element_version_id;
1303 
1307      where relationship_type IN ('LW')
1304   CURSOR get_loop1(c_project_id NUMBER) IS
1305     select object_Id_to2, object_id_from2 -- Fix for Bug # 4297715.
1306       from pa_object_relationships
1308      start with object_id_from2 = c_project_id
1309    connect by prior object_id_to2 = object_id_from2
1310                 and prior relationship_type = relationship_type
1311                 and relationship_type = 'LW';
1312 
1313   CURSOR get_loop2(c_project_id NUMBER) IS
1314     select object_Id_to2, object_id_from2 -- Fix for Bug # 4297715.
1315       from pa_object_relationships
1316      where relationship_type IN ('LF')
1317      start with object_id_from2 = c_project_id
1318    connect by prior object_id_to2 = object_id_from2
1319                 and prior relationship_type = relationship_type
1320                 and relationship_type = 'LF';
1321 --
1322   -- Start of Bug 3621794
1323   CURSOR get_proj_prog_fl(c_project_id NUMBER) IS
1324   SELECT sys_program_flag
1325     FROM pa_projects_all
1326    WHERE project_id =c_project_id;
1327 
1328    CURSOR get_parent_sub_proj(c_project_id NUMBER) IS
1329      SELECT ppa.sys_program_flag
1330      FROM pa_proj_element_versions ppev,
1331           pa_proj_elements ppe,
1332           pa_projects_all ppa
1333     WHERE ppe.project_id = ppev.project_id
1334       AND ppe.proj_element_id = ppev.proj_element_id
1335       AND ppev.object_type = 'PA_TASKS'
1336       AND ppe.object_type = 'PA_TASKS'
1337       AND ppe.project_id = ppa.project_id
1338       AND ppev.element_version_id IN (
1339                      SELECT object_id_from1
1340                        FROM pa_object_relationships
1341                       WHERE relationship_type IN ('LW','LF')
1342                  START WITH object_id_to2 = c_project_id
1343                         AND object_type_to = 'PA_STRUCTURES'
1344                  CONNECT BY object_id_from2 = prior object_id_to2
1345                         and prior relationship_type = relationship_type
1346                         AND relationship_type IN ('LW','LF')
1347                         AND object_type_from = 'PA_TASKS');
1348   -- End of Bug 3621794
1349 --
1350   --bug 3893970
1351   CURSOR get_multi_rollup(c_project_id NUMBER) IS
1352   select nvl(ALLOW_MULTI_PROGRAM_ROLLUP,'N')
1353     from pa_projects_all
1354    where project_id = c_project_id;
1355 
1356   CURSOR get_child_links(c_project_id NUMBER, c_parent_proj_id NUMBER) IS
1357   select distinct(object_id_from2)
1358       from pa_object_relationships a
1359      where a.relationship_type IN ('LW','LF')
1360        and a.object_id_to2 = c_project_id
1361        and a.object_id_from2 <> c_parent_proj_id -- Fix for Bug # 4297715.
1362        and exists (select 1 from PA_PROJ_ELEMENT_VERSIONS elv  /* Added the exists for Bug 6148092 */
1363               where elv.element_version_id = a.object_id_from1
1364               and ((elv.PARENT_STRUCTURE_VERSION_ID =
1365                    PA_PROJECT_STRUCTURE_UTILS.get_current_working_ver_id(elv.project_id))
1366                 or (elv.PARENT_STRUCTURE_VERSION_ID =
1367                    PA_PROJECT_STRUCTURE_UTILS.get_latest_wp_version(elv.project_id))
1368                 )
1369               );
1370 
1371   l_linked_parent_proj_id NUMBER;
1372   l_multi_rollup_flag VARCHAR2(1);
1373   l_dest_multi_rollup_flag VARCHAR2(1);
1374   --end bug 3893970
1375 
1376   l_src_project_id NUMBER;
1377   l_dest_project_id NUMBER;
1378   l_proj_id NUMBER;
1379   l_proj_prog_fl  VARCHAR2(1);                 --Bug 3621794
1380 
1381 -- Begin Fix for Bug # 4297715.
1382 
1383 cursor cur_get_status_code(c_task_version_id NUMBER) is
1384 select ppevs.status_code
1385 from pa_proj_elem_ver_structure ppevs, pa_proj_element_versions ppev
1386 where ppev.element_version_id = c_task_version_id
1387 and ppev.project_id = ppevs.project_id -- Bug # 4868867.
1388 and ppev.parent_structure_version_id = ppevs.element_version_id;
1389 
1390 l_status_code   VARCHAR2(150) := NULL;
1391 
1392 l_proj_id_from  NUMBER := NULL;
1393 
1394 -- End Fix for Bug # 4297715.
1395 
1396 -- Begin fix for Bug # Bug # 4256435.
1397 
1398 cursor cur_dep_hierarchy(c_src_task_ver_id NUMBER) is
1399 -- This query selects all the successor projects of the source project.
1400 select por.object_id_from2 project_id
1401 from pa_object_relationships por
1402 where por.relationship_type = 'D'
1403 start with por.object_id_to1 = c_src_task_ver_id
1404 -- connect by prior por.object_id_from2 = por.object_id_to2 -- Fix for Bug # 4256435.
1405 connect by prior por.object_id_from1 = por.object_id_to1 -- Fix for Bug # 4256435.
1406 and prior por.relationship_type = por.relationship_type
1407 and por.relationship_type = 'D'
1408 union all
1409 -- This query selects all the predecessor projects of the source project.
1410 select por.object_id_to2 project_id
1411 from pa_object_relationships por
1412 where por.relationship_type = 'D'
1413 start with por.object_id_from1 = c_src_task_ver_id
1414 -- connect by prior por.object_id_to2 = por.object_id_from2 -- Fix for Bug # 4256435.
1415 connect by prior por.object_id_to1 = por.object_id_from1 -- Fix for Bug # 4256435.
1416 and prior por.relationship_type = por.relationship_type
1417 and por.relationship_type = 'D';
1418 
1419 rec_dep_hierarchy cur_dep_hierarchy%ROWTYPE;
1420 
1421 -- End fix for Bug # Bug # 4256435.
1422 
1423 BEGIN
1424   OPEN get_project_id(p_task_version_id);
1428 -- Begin Fix for Bug # 4297715.
1425   FETCH get_project_id into l_src_project_id;
1426   CLOSE get_project_id;
1427 
1429 
1430   open cur_get_status_code(p_task_version_id);
1431   fetch cur_get_status_code into l_status_code;
1432   close cur_get_status_code;
1433 
1434 -- End Fix for Bug # 4297715.
1435 
1436 
1437   l_dest_project_id := p_project_id;
1438 
1439   IF (l_src_project_id = l_dest_project_id) THEN
1440     return 'N';
1441   END IF;
1442 
1443 -- Begin fix for Bug # Bug # 4256435.
1444 
1445         for rec_dep_hierarchy in cur_dep_hierarchy(p_task_version_id)
1446         loop
1447 
1448                 if (rec_dep_hierarchy.project_id = l_dest_project_id) then
1449 
1450                         PA_UTILS.ADD_MESSAGE(p_app_short_name  => 'PA'
1451                                              , p_msg_name       => 'PA_WP_DEP_EXISTS_NO_PRGM');
1452 
1453                         return 'N';
1454 
1455                  end if;
1456 
1457         end loop;
1458 
1459 -- End fix for Bug # Bug # 4256435.
1460 
1461   --bug 3893970
1462   OPEN get_multi_rollup(l_src_project_id);
1463   FETCH get_multi_rollup INTO l_multi_rollup_flag;
1464   CLOSE get_multi_rollup;
1465 
1466   If l_multi_rollup_flag = 'N' THEN
1467     --need to check if new child is already linked
1468     OPEN get_child_links(l_dest_project_id, l_src_project_id);
1469     FETCH get_child_links INTO l_linked_parent_proj_id;
1470     IF get_child_links%FOUND THEN
1471       CLOSE get_child_links;
1472       return 'N';
1473     END IF;
1474     CLOSE get_child_links;
1475 
1476     --need to check all new child to see if it has multi rollup = 'Y'
1477     FOR i IN get_loop1(l_dest_project_id) LOOP
1478       OPEN get_multi_rollup(i.object_id_to2);
1479       FETCH get_multi_rollup into l_dest_multi_rollup_flag;
1480       CLOSE get_multi_rollup;
1481 
1482       IF (l_dest_multi_rollup_flag = 'Y') THEN
1483         return 'N';
1484       END IF;
1485     END LOOP;
1486 
1487     FOR i IN get_loop2(l_dest_project_id) LOOP
1488       OPEN get_multi_rollup(i.object_id_to2);
1489       FETCH get_multi_rollup into l_dest_multi_rollup_flag;
1490       CLOSE get_multi_rollup;
1491 
1492       IF (l_dest_multi_rollup_flag = 'Y') THEN
1493         return 'N';
1494       END IF;
1495     END LOOP;
1496   ELSE
1497     --If allow, need to check if new child has parent which does not allow
1498     --need to check all new child to see if its parent has multi rollup = 'N'
1499     OPEN get_child_links(l_dest_project_id, l_src_project_id);
1500     LOOP
1501       FETCH get_child_links INTO l_linked_parent_proj_id;
1502       EXIT WHEN get_child_links%NOTFOUND;
1503 
1504       OPEN get_multi_rollup(l_linked_parent_proj_id);
1505       FETCH get_multi_rollup into l_dest_multi_rollup_flag;
1506       CLOSE get_multi_rollup;
1507 
1508       IF (l_dest_multi_rollup_flag = 'N') THEN
1509         CLOSE get_child_links;
1510         return 'N';
1511       END IF;
1512     END LOOP;
1513     CLOSE get_child_links;
1514   END IF;
1515   --end bug 3893970
1516 
1517   IF (p_structure_type = 'WORKPLAN') THEN
1518     OPEN get_loop1(l_src_project_id);
1519     LOOP
1520       FETCH get_loop1 INTO l_proj_id, l_proj_id_from; -- Fix for Bug # 4297715.
1521       EXIT when get_loop1%NOTFOUND;
1522 
1523       IF ((l_proj_id = l_dest_project_id) -- Fix for Bug # 4297715.
1524 
1525           -- Fix for Bug # 4297715. If the published versions of the source project and the destination
1526           -- project are linked in a parent and immediate child relationship respectively,  we still allow
1527           -- the working version of the source project to be linked to the published version of the
1528           -- destination project.
1529 
1530           and  NOT((nvl(l_status_code,'X') = 'STRUCTURE_WORKING') -- Fix for Bug # 4297715.
1531                 and (l_proj_id_from = l_src_project_id))) -- Fix for Bug # 4297715.
1532      THEN
1533         CLOSE get_loop1;
1534         return 'N';
1535       END If;
1536 
1537     END LOOP;
1538     CLOSE get_loop1;
1539   END IF;
1540 
1541   IF (p_structure_type = 'FINANCIAL') THEN
1542     OPEN get_loop2(l_src_project_id);
1543     LOOP
1544       FETCH get_loop2 INTO l_proj_id, l_proj_id_from; -- Fix for Bug # 4297715.
1545       EXIT when get_loop2%NOTFOUND;
1546 
1547       IF ((l_proj_id = l_dest_project_id) -- Fix for Bug # 4297715.
1548 
1549       -- Fix for Bug # 4297715. If the published versions of the source project and the destination
1550           -- project are linked in a parent and immediate child relationship respectively,  we still allow
1551       -- the working version of the source project to be linked to the published version of the
1552       -- destination project.
1553 
1554           and  NOT((nvl(l_status_code,'X') = 'STRUCTURE_WORKING') -- Fix for Bug # 4297715.
1555                    and (l_proj_id_from = l_src_project_id))) -- Fix for Bug # 4297715.
1556     THEN
1557         CLOSE get_loop2;
1558         return 'N';
1559       END If;
1560 
1561     END LOOP;
1562     CLOSE get_loop2;
1563   END IF;
1564 
1565   --IMP Note: Please add any new validation above this code
1566   --Imp Note: Let this be the last validation to be performed by this API.
1567   -- Start of Bug 3621794
1571         CLOSE get_proj_prog_fl;
1568   OPEN get_proj_prog_fl(l_src_project_id);
1569   FETCH get_proj_prog_fl INTO l_proj_prog_fl;
1570      IF l_proj_prog_fl = 'Y' THEN
1572 --        return 'N';                 --Bug 3622177
1573           return 'Y';                 --Bug 3622177
1574      END IF;
1575   CLOSE get_proj_prog_fl;
1576 
1577   l_proj_prog_fl:='N';
1578   OPEN get_parent_sub_proj(l_src_project_id);
1579   LOOP
1580      FETCH get_parent_sub_proj INTO l_proj_prog_fl;
1581      IF get_parent_sub_proj%NOTFOUND THEN
1582         CLOSE get_parent_sub_proj;
1583     return 'N';
1584      END IF;
1585 --     EXIT WHEN get_parent_sub_proj%NOTFOUND;
1586      IF l_proj_prog_fl = 'Y' THEN
1587         CLOSE get_parent_sub_proj;
1588 --        return 'N';                 --Bug 3622177
1589           return 'Y';                 --Bug 3622177
1590      END IF;
1591   END LOOP;
1592   CLOSE get_parent_sub_proj;
1593   -- End of Bug 3621794
1594 
1595   return 'Y';
1596 END CREATE_SUB_PROJ_ASSO_OK;
1597 
1598 FUNCTION IS_AUTO_ROLLUP(p_project_id NUMBER)
1599   RETURN VARCHAR2
1600 IS
1601   cursor c1 is
1602     select ppwa.AUTO_ROLLUP_SUBPROJ_FLAG
1603       from pa_proj_workplan_attr ppwa,
1604            pa_proj_elements ppe,
1605            pa_proj_structure_types ppst,
1606            pa_structure_types pst
1607      where ppe.project_id = p_project_id
1608        and ppe.object_type = 'PA_STRUCTURES'
1609        and ppe.proj_element_id = ppst.proj_element_id
1610        and ppst.structure_type_id = pst.structure_type_id
1611        and pst.structure_type = 'WORKPLAN'
1612        and ppe.project_id = ppwa.project_id
1613        and ppe.proj_element_id = ppwa.proj_element_id;
1614   l_dummy VARCHAR2(1);
1615 BEGIN
1616   OPEN c1;
1617   FETCH c1 into l_dummy;
1618   CLOSE c1;
1619 
1620   return l_dummy;
1621 
1622 END IS_AUTO_ROLLUP;
1623 
1624 FUNCTION Get_Latest_Parent_Ver_obj_Id(p_structure_ver_id NUMBER,
1625                                       p_task_id NUMBER
1626                       , p_relationship_type VARCHAR2 := 'LW') -- Fix for Bug # 4471484.
1627   RETURN NUMBER
1628 IS
1629   CURSOR c1 IS
1630     select por2.object_relationship_id, por2.relationship_type, ppev.element_version_id
1631       from pa_object_relationships  por1,
1632            pa_object_relationships  por2,
1633            pa_proj_element_versions ppev,
1634            pa_proj_elements         ppe
1635      where ppe.proj_element_id = p_task_id
1636        and ppe.proj_element_id = ppev.proj_element_id
1637        and ppe.project_id = ppev.project_id
1638        and ppev.element_version_id = por1.object_id_from1
1639        and por1.relationship_type = 'S'
1640        and por2.object_id_to1 = p_structure_ver_id
1641        and por2.object_id_from1 = por1.object_id_to1
1642        and por2.relationship_type = p_relationship_type -- IN ('LF', 'LW') -- Fix for Bug # 4471484.
1643        -- and rownum < 2 -- Fix for Bug # 4477118.
1644      order by ppev.element_version_id desc ; -- por2.relationship_type desc, -- Fix for Bug # 4477118.
1645 
1646 /*
1647     select por1.object_id_from1
1648       from pa_object_relationships  por1,
1649            pa_object_relationships  por2
1650      where por2.object_id_to1 = p_structure_ver_id
1651        and por2.object_id_from1 = por1.object_id_to1
1652        and por2.relationship_type IN ('LF', 'LW')
1653        and rownum < 2
1654   order by por1.object_id_from1 desc;
1655 */
1656 
1657   l_obj_rel_id    NUMBER;
1658   l_element_ver_id NUMBER;
1659   l_obj_type      VARCHAR2(30);
1660 BEGIN
1661   OPEN c1;
1662   FETCH c1 into l_obj_rel_id, l_obj_type, l_element_ver_id;
1663   CLOSE c1;
1664 
1665   return l_obj_rel_id;
1666 END Get_Latest_Parent_Ver_obj_Id;
1667 
1668 FUNCTION Get_Latest_Parent_Task_Ver_Id(p_structure_ver_id NUMBER,
1669                                       p_task_id NUMBER
1670                       , p_relationship_type VARCHAR2 := 'LW')
1671   RETURN NUMBER
1672 IS
1673   CURSOR c1 IS
1674     select por2.object_relationship_id, por2.relationship_type, ppev.element_version_id
1675       from pa_object_relationships  por1,
1676            pa_object_relationships  por2,
1677            pa_proj_element_versions ppev,
1678            pa_proj_elements         ppe
1679      where ppe.proj_element_id = p_task_id
1680        and ppe.proj_element_id = ppev.proj_element_id
1681        and ppe.project_id = ppev.project_id
1682        and ppev.element_version_id = por1.object_id_from1
1683        and por1.relationship_type = 'S'
1684        and por2.object_id_to1 = p_structure_ver_id
1685        and por2.object_id_from1 = por1.object_id_to1
1686        and por2.relationship_type = p_relationship_type
1687      order by ppev.element_version_id desc ;
1688 
1689   l_obj_rel_id    NUMBER;
1690   l_element_ver_id NUMBER;
1691   l_obj_type      VARCHAR2(30);
1692 BEGIN
1693   OPEN c1;
1694   FETCH c1 into l_obj_rel_id, l_obj_type, l_element_ver_id;
1695   CLOSE c1;
1696 
1697   return l_element_ver_id;
1698 END Get_Latest_Parent_Task_Ver_Id;
1699 
1700 
1701 FUNCTION Get_Latest_Child_Ver_Id(p_task_ver_id NUMBER)
1702   RETURN NUMBER
1703 IS
1704   CURSOR c1 IS
1705     select por2.object_id_to1
1706       from pa_object_relationships  por1,
1707            pa_object_relationships  por2
1708      where por1.object_id_from1 = p_task_ver_id
1712   order by por2.object_id_to1 desc;
1709        and por1.object_id_to1 = por2.object_id_from1
1710        and por2.relationship_type IN ('LF', 'LW')
1711        and rownum < 2
1713 
1714   l_child_ver_id NUMBER;
1715 BEGIN
1716   OPEN c1;
1717   FETCH c1 into l_child_ver_id;
1718   CLOSE c1;
1719 
1720   return l_child_ver_id;
1721 END Get_Latest_Child_Ver_Id;
1722 
1723 
1724 --============================================================================================
1725 /*Bug 3629024 : ## SHORT NOTE ON THE FOLL. TWO MUTUALLY RECURSIVE FUNCTIONS ##
1726 Treat the workplan structure as a directed graph, with nodes being the
1727 structure/tasks and links between the nodes being dependencies and/or
1728 parent/child task relationships.
1729 Dependency links are directed from sucessor to predecessor.
1730 Child Tasks are linked to their parents with a bi-directional link.
1731 Then, there should be no circular path for any node
1732 
1733 The following two functions check for the existence of such a closed path.
1734 */
1735 
1736 -- Function             : get_predecessors
1737 -- Type                 : Mutually Recursive functions alongwith get_parents_childs
1738 -- Purpose              : Retrieves tasks which are predecessor of the task passed to
1739 --                        this function (p_src_task_ver_id)
1740 -- Return               : Returns with TRUE if
1741 --                        SUCCESSOR(p_orig_succ_task_ver_id) matches any of the retrieved
1742 --                        predecessors
1743 -- Assumptions          : We have started from the PREDECESSOR to which a dependency is
1744 --                        trying to be created
1745 -- Parameters                    Type      Required  Description and Purpose
1746 -- ---------------------------  ------     --------  --------------------------------------------------------
1747 -- p_src_task_ver_id            NUMBER        Y      Task id for which predecessors are to be retieved and checked
1748 -- p_orig_succ_task_ver_id      NUMBER        Y      Task id to which the retrieved predecessors are compared
1749 --
1750 -- Call the function as get_predecessors(PRE,SUCC) where
1751 -- PRE  = predecessor to which a dependency is trying to be created
1752 -- SUCC = successor from which a dependency is trying to be created
1753 FUNCTION get_predecessors( p_src_task_ver_id       IN NUMBER
1754                           ,p_orig_succ_task_ver_id IN NUMBER ) RETURN BOOLEAN IS
1755 CURSOR cur_get_predecessors IS
1756      SELECT por1.object_id_to1 RELATED_TASK
1757      FROM   pa_object_relationships por1
1758      WHERE  por1.relationship_type     = 'D'
1759      AND    LEVEL = 1
1760      AND    por1.object_id_from2 = por1.object_id_to2
1761      START WITH       por1.object_id_from1 = p_src_task_ver_id
1762      CONNECT BY PRIOR por1.object_id_to1   = por1.object_id_from1
1763      AND        PRIOR por1.relationship_type = por1.relationship_type
1764      AND        PRIOR por1.object_id_from2 = por1.object_id_from2
1765      ;
1766 --NOTE : * PRIOR por1.relationship_type = por1.relationship_type
1767 --         is required so as to prevent traversing parent-child dependency relns.
1768 --       * PRIOR por1.object_id_from2 = por1.object_id_from2 in CONNECT clause
1769 --         is required to prevent traversing inter-project dependencies; which can be
1770 --         circular and can give a "ORA-01436: CONNECT BY loop in user data" error
1771 --       * por1.object_id_from2 = por1.object_id_to2 in WHERE clause
1772 --         is required to filter out only those rows which correspond to intra-proj dependencies
1773 BEGIN
1774      FOR rec_predecessors IN cur_get_predecessors LOOP
1775           IF rec_predecessors.related_task = p_orig_succ_task_ver_id
1776           OR get_parents_childs( rec_predecessors.related_task, p_orig_succ_task_ver_id ) = TRUE THEN
1777                RETURN TRUE;
1778           END IF;
1779      END LOOP;
1780 
1781      RETURN FALSE;
1782 END get_predecessors;
1783 
1784 -- Function             : get_parents_childs
1785 -- Type                 : Mutually Recursive functions alongwith get_predecessors
1786 -- Purpose              : Retrieves tasks which are parents or childs, of the task passed to
1787 --                        this function (p_src_task_ver_id)
1788 -- Return               : Returns with TRUE if
1789 --                        SUCCESSOR(p_orig_succ_task_ver_id) matches any of the retrieved
1790 --                        parents/childs
1791 -- Assumptions          : We have started from the PREDECESSOR to which a dependency is
1792 --                        trying to be created
1793 -- Parameters                    Type      Required  Description and Purpose
1794 -- ---------------------------  ------     --------  --------------------------------------------------------
1795 -- p_src_task_ver_id            NUMBER        Y      Task id for which parents/childs are to be retieved and checked
1796 -- p_orig_succ_task_ver_id      NUMBER        Y      Task id to which the retrieved parents/childs are compared
1797 FUNCTION get_parents_childs( p_src_task_ver_id       IN NUMBER
1798                             ,p_orig_succ_task_ver_id IN NUMBER ) RETURN BOOLEAN IS
1799 CURSOR cur_get_parents_childs IS
1800      SELECT por1.object_id_to1 RELATED_TASK
1801      FROM   pa_object_relationships por1
1802      WHERE      por1.relationship_type     = 'S'
1803      AND        por1.relationship_subtype = 'TASK_TO_TASK'
1804      START WITH       por1.object_id_from1 = p_src_task_ver_id
1805                   AND relationship_type = 'S' --bug 3944567
1806      CONNECT BY PRIOR por1.object_id_to1   = por1.object_id_from1
1810      FROM   pa_object_relationships por2
1807      AND        PRIOR por1.relationship_type = por1.relationship_type
1808      UNION
1809      SELECT por2.object_id_from1 RELATED_TASK
1811      WHERE      por2.relationship_type          = 'S'
1812      AND        por2.relationship_subtype = 'TASK_TO_TASK'
1813      START WITH       por2.object_id_to1   = p_src_task_ver_id
1814                   AND relationship_type = 'S' --bug 3944567
1815      CONNECT BY PRIOR por2.object_id_from1 = por2.object_id_to1
1816      AND        PRIOR por2.relationship_type = por2.relationship_type
1817      UNION
1818      SELECT p_src_task_ver_id RELATED_TASK
1819      FROM   dual
1820      ;
1821 
1822    --bug 4145585
1823    Cursor check_intersect IS
1824      select object_id_from1 elem_ver_id
1825        from pa_object_relationships
1826       start with object_id_to1 = p_orig_succ_task_ver_id
1827         and relationship_type = 'D'
1828  connect by  object_id_to1 =  prior object_id_from1
1829         and relationship_type = prior relationship_type
1830         and object_id_to2 = object_id_from2
1831      INTERSECT
1832      select object_id_to1
1833        from pa_object_relationships
1834       start with object_id_to1 = p_src_task_ver_id
1835         and relationship_type = 'S'
1836  connect by prior object_id_to1 = object_id_from1
1837         and relationship_type = prior relationship_type;
1838    l_dummy NUMBER;
1839    --end bug 4145585
1840 
1841 BEGIN
1842    --bug 4145585
1843 /*
1844      FOR rec_parents_childs IN cur_get_parents_childs LOOP
1845           IF rec_parents_childs.related_task = p_orig_succ_task_ver_id
1846           OR get_predecessors( rec_parents_childs.related_task, p_orig_succ_task_ver_id ) = TRUE THEN
1847                RETURN TRUE;
1848           END IF;
1849      END LOOP;
1850 
1851      RETURN FALSE;
1852 */
1853    OPEN check_intersect;
1854    FETCH check_intersect into l_dummy;
1855    IF check_intersect%FOUND THEN
1856      CLOSE check_intersect;
1857      RETURN TRUE;
1858    END IF;
1859    CLOSE check_intersect;
1860 
1861    RETURN FALSE;
1862    --end bug 4145585
1863 
1864 END get_parents_childs;
1865 --============================================================================================
1866 
1867 FUNCTION Check_link_exists(p_project_id number
1868    ,p_link_type    VARCHAR2 DEFAULT 'SHARED'    --bug 4532826
1869 ) return VARCHAR2
1870 IS
1871   CURSOR get_count IS
1872     Select count(1) from pa_object_relationships
1873      where relationship_type IN ('LW', 'LF')
1874        and (object_id_from2 = p_project_id or object_id_to2 = p_project_id);
1875 
1876 -- bug 4532826
1877   CURSOR get_count_fn IS
1878     Select count(1) from pa_object_relationships
1879      where relationship_type = 'LF'
1880        and (object_id_from2 = p_project_id or object_id_to2 = p_project_id);
1881 
1882   CURSOR get_count_wp IS
1883     Select count(1) from pa_object_relationships
1884      where relationship_type = 'LW'
1885        and (object_id_from2 = p_project_id or object_id_to2 = p_project_id);
1886 --end bug 4532826
1887 
1888 
1889   l_cnt NUMBER :=0;
1890 BEGIN
1891   IF p_link_type = 'SHARED'    --bug 4532826
1892   THEN
1893       OPEN get_count;
1894       FETCH get_count into l_cnt;
1895       CLOSE get_count;
1896 --bug 4532826
1897   ELSIF  p_link_type = 'FINANCIAL'
1898   THEN
1899 
1900       OPEN get_count_fn;
1901       FETCH get_count_fn into l_cnt;
1902       CLOSE get_count_fn;
1903 
1904   ELSIF  p_link_type = 'WORKPLAN'
1905   THEN
1906 
1907       OPEN get_count_wp;
1908       FETCH get_count_wp into l_cnt;
1909       CLOSE get_count_wp;
1910 
1911   END IF;
1912  --bug end 4532826
1913 
1914   IF l_cnt > 0 THEN
1915      return 'Y';
1916   END IF;
1917 
1918   return 'N';
1919 END Check_link_exists;
1920 
1921 FUNCTION Check_proj_currency_identical(p_src_project_id NUMBER
1922                                      , p_dest_project_id NUMBER) return VARCHAR2
1923 IS
1924   CURSOR get_proj_curr_code(c_project_id NUMBER) IS
1925   select project_currency_code
1926     from pa_projects_all
1927    where project_id = C_project_id;
1928   l_src_proj_currency_code  VARCHAR2(15);
1929   l_dest_proj_currency_code VARCHAR2(15);
1930 BEGIN
1931   OPEN get_proj_curr_code(p_src_project_id);
1932   FETCH get_proj_curr_code INTO l_src_proj_currency_code;
1933   CLOSE get_proj_curr_code;
1934 
1935   OPEN get_proj_curr_code(p_dest_project_id);
1936   FETCH get_proj_curr_code INTO l_dest_proj_currency_code;
1937   CLOSE get_proj_curr_code;
1938 
1939   IF (l_src_proj_currency_code <> l_dest_proj_currency_code) THEN
1940     return 'N';
1941   END IF;
1942 
1943   return 'Y';
1944 END check_proj_currency_identical;
1945 
1946 FUNCTION check_dependencies_valid(p_new_parent_task_ver_id  IN NUMBER
1947                                  ,p_task_ver_id IN NUMBER) RETURN VARCHAR2
1948 IS
1949   CURSOR get_parent_to_child IS
1950     select count(1)
1951       from pa_object_relationships
1952      where relationship_type = 'D'
1953        and object_id_from1 IN (     --get all tasks in upper branch
1954                select object_id_to1
1955                from pa_object_relationships
1956                start with object_id_to1 = p_new_parent_task_ver_id
1960                    and prior object_type_from = object_type_to)
1957                       and relationship_type = 'S'
1958                connect by prior object_id_from1  = object_id_to1
1959                    and relationship_type = prior relationship_type
1961        and object_id_to1 IN (       --get all tasks in lower branch
1962                select object_id_to1
1963                from pa_object_relationships
1964                start with object_id_to1 = p_task_ver_id
1965                       and relationship_type = 'S'
1966                connect by prior object_id_to1 = object_id_from1
1967                    and relationship_type = prior relationship_type
1968                    and prior object_type_to = object_type_from);
1969 
1970   CURSOR get_child_to_parent IS
1971     select count(1)
1972       from pa_object_relationships
1973      where relationship_type = 'D'
1974        and object_id_from1 IN (    --get tasks in lower branch
1975                select object_id_to1
1976                from pa_object_relationships
1977                start with object_id_to1 = p_task_ver_id
1978                       and relationship_type = 'S'
1979                connect by prior object_id_to1 = object_id_from1
1980                    and relationship_type = prior relationship_type
1981                    and prior object_type_to = object_type_from)
1982        and object_id_to1 IN (     --get tasks in upper branch
1983                select object_id_to1
1984                from pa_object_relationships
1985                start with object_id_to1 = p_new_parent_task_ver_id
1986                       and relationship_type = 'S'
1987                connect by prior object_id_from1  = object_id_to1
1988                    and relationship_type = prior relationship_type
1989                    and prior object_type_from = object_type_to);
1990   l_cnt NUMBER;
1991 
1992 BEGIN
1993   OPEN get_parent_to_child;
1994   FETCH get_parent_to_child INTO l_cnt;
1995   CLOSE get_parent_to_child;
1996   IF l_cnt > 0 THEN
1997     return 'N';
1998   END IF;
1999 
2000   OPEN get_child_to_parent;
2001   FETCH get_child_to_parent INTO l_cnt;
2002   CLOSE get_child_to_parent;
2003   IF l_cnt > 0 THEN
2004     return 'N';
2005   END IF;
2006 
2007   RETURN 'Y';
2008 END check_dependencies_valid;
2009 
2010 -- Begin fix for Bug # 4266540.
2011 
2012 FUNCTION check_task_has_sub_proj(p_project_id NUMBER
2013                  , p_task_id NUMBER
2014                  , p_task_version_id NUMBER := NULL)
2015 return VARCHAR2 is
2016 
2017 cursor cur_sub_project (c_project_id NUMBER, c_task_id NUMBER, c_task_version_id NUMBER) is
2018 select count(pslv.sub_project_id)
2019 from pa_structures_links_v pslv
2020 where pslv.parent_project_id = c_project_id
2021 and pslv.parent_task_id = c_task_id
2022 and pslv.parent_task_version_id = c_task_version_id;
2023 
2024 cursor cur_task_version_id (c_project_id NUMBER, c_task_id NUMBER, c_structure_version_id NUMBER) is
2025 select ppev.element_version_id
2026 from pa_proj_element_versions ppev
2027 where ppev.project_id = c_project_id
2028 and ppev.proj_element_id = c_task_id
2029 and ppev.parent_structure_version_id = c_structure_version_id;
2030 
2031 l_cur_working_str_ver_id        NUMBER := null;
2032 
2033 l_task_version_id               NUMBER := null;
2034 
2035 l_count                         NUMBER := null;
2036 
2037 l_return                        VARCHAR2(1) := null;
2038 
2039 BEGIN
2040 
2041     l_return := 'N';
2042 
2043     if (p_task_version_id is null) then
2044 
2045         -- The calling API in this case is: pa_task_utils.check_create_subtask_ok() which is only
2046         -- called for 'FINANCIAL' tasks.
2047 
2048         l_cur_working_str_ver_id := pa_project_structure_utils.get_fin_struc_ver_id(p_project_id);
2049 
2050             open cur_task_version_id(p_project_id, p_task_id, l_cur_working_str_ver_id);
2051             fetch cur_task_version_id into l_task_version_id;
2052             close cur_task_version_id;
2053 
2054     else
2055 
2056             l_task_version_id := p_task_version_id;
2057 
2058     end if;
2059 
2060         open cur_sub_project(p_project_id, p_task_id, l_task_version_id);
2061         fetch cur_sub_project into l_count;
2062         close cur_sub_project;
2063 
2064         if nvl(l_count,0) > 0 then
2065 
2066                 l_return := 'Y';
2067 
2068         end if;
2069 
2070         return(l_return);
2071 
2072 END check_task_has_sub_proj;
2073 
2074 -- End fix for Bug # 4266540.
2075 
2076 -- Begin fix for Bug # 4411603.
2077 
2078 function is_str_linked_to_working_ver
2079 (p_project_id NUMBER
2080  , p_structure_version_id NUMBER
2081  , p_relationship_type VARCHAR2 := 'LW') return VARCHAR2
2082 is
2083 
2084 l_return_value VARCHAR2(1) := null;
2085 
2086 cursor cur_structure_version_ids (c_object_id_from NUMBER
2087                                   , c_relationship_type VARCHAR2) is
2088 -- Bug # 4757224.
2089 
2090 select 1
2091 from   dual
2092 where exists (select 1
2093               from pa_proj_element_versions pev, pa_object_relationships por, pa_proj_elem_ver_structure ppevs
2094               where pev.parent_structure_version_id = c_object_id_from
2095 	      and pev.element_version_id = por.object_id_from1
2096 	      and por.object_id_to1 = ppevs.element_version_id
2097               -- Bug Fix 5077552
2098               -- Adding the project id to avoid the FTS on ppevs.
2099               and por.object_id_to2 = ppevs.project_id
2100 	      and por.object_type_to = 'PA_STRUCTURES'
2101 	      and por.relationship_type in (c_relationship_type, 'S')
2102 	      and ppevs.status_code='STRUCTURE_WORKING');
2103 
2104 /*
2105 -- Bug # 4737033.
2106 
2107 select ppevs.status_code status_code
2108 from (select por.object_id_to1
2109       from pa_object_relationships por
2110       where por.object_type_to = 'PA_STRUCTURES'
2111       and relationship_type in (c_relationship_type, 'S')
2112       start with por.object_id_from1 = c_object_id_from
2113       connect by prior por.object_id_to1 = por.object_id_from1
2114       and prior relationship_type in (c_relationship_type, 'S')) por
2115       ,pa_proj_elem_ver_structure ppevs
2116 where
2117     por.object_id_to1 = ppevs.element_version_id (+);
2118 
2119 select ppevs.status_code status_code
2120 from pa_object_relationships por, pa_proj_elem_ver_structure ppevs
2121 where por.object_id_to1 = ppevs.element_version_id (+)
2122 and por.object_type_to = 'PA_STRUCTURES'
2123 and relationship_type in (c_relationship_type, 'S')
2124 start with por.object_id_from1 = c_object_id_from
2125 connect by prior por.object_id_to1 = por.object_id_from1
2126 and prior relationship_type in (c_relationship_type, 'S');
2127 
2128 -- Bug # 4737033.
2129 */
2130 
2131 -- Bug # 4757224.
2132 
2133 l_structure_working VARCHAR2(1) := null;
2134 
2135 rec_structure_version_ids cur_structure_version_ids%rowtype;
2136 
2137 begin
2138 
2139 l_return_value := 'N';
2140 
2141 if (pa_project_structure_utils.check_program_flag_enable(p_project_id) = 'Y') then -- Bug # 4742904.
2142 
2143 -- Bug # 4757224.
2144 
2145     open cur_structure_version_ids(p_structure_version_id, p_relationship_type);
2146     fetch cur_structure_version_ids into rec_structure_version_ids;
2147 
2148     if cur_structure_version_ids%NOTFOUND then
2149         l_return_value:='N';
2150     else
2151         l_return_value:='Y';
2152     end if;
2153 
2154     close cur_structure_version_ids;
2155 
2156 /*
2157 for rec_structure_version_ids in cur_structure_version_ids(p_structure_version_id, p_relationship_type)
2158 loop
2159 
2160     if (rec_structure_version_ids.status_code = 'STRUCTURE_WORKING') then
2161 
2162        l_return_value := 'Y';
2163 
2164     end if;
2165 
2166 end loop;
2167 */
2168 
2169 -- Bug # 4757224.
2170 
2171 end if; -- Bug # 4742904.
2172 
2173 return(l_return_value);
2174 
2175 end is_str_linked_to_working_ver;
2176 
2177 -- End fix for Bug # 4411603.
2178 
2179 --bug 4541039
2180 
2181 FUNCTION Check_parent_project_Exists
2182 (
2183      p_project_id NUMBER,
2184      p_structure_ver_id NUMBER
2185     ,p_link_type        VARCHAR2     default 'SHARED'    --bug 4541039
2186 )RETURN VARCHAR2
2187 IS
2188     CURSOR check_parentproj_exists IS
2189     SELECT '1'
2190        from     pa_object_relationships por
2191        WHERE p_structure_ver_id = por.object_id_to1
2192        and por.object_id_to2 = p_project_id
2193        and por.relationship_type IN ('LW', 'LF');
2194 
2195 
2196     CURSOR check_parentproj_exists_wp IS
2197     SELECT '1'
2198        from    pa_object_relationships por
2199        WHERE p_structure_ver_id = por.object_id_to1
2200        and por.object_id_to2 = p_project_id
2201        and por.relationship_type = 'LW';
2202 
2203     CURSOR check_parentproj_exists_fn 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 = 'LF';
2209 
2210     l_dummy VARCHAR2(1);
2211 BEGIN
2212     IF p_link_type = 'SHARED'  --bug 4541039
2213     THEN
2214         OPEN check_parentproj_exists;
2215         FETCH check_parentproj_exists INTO l_dummy;
2216         IF check_parentproj_exists%NOTFOUND THEN
2217         CLOSE check_parentproj_exists;
2218           RETURN 'N';
2219         ELSE
2220           CLOSE check_parentproj_exists;
2221           RETURN 'Y';
2222         END IF;
2223     ELSIF p_link_type = 'WORKPLAN'
2224     THEN
2225         OPEN check_parentproj_exists_wp;
2226         FETCH check_parentproj_exists_wp INTO l_dummy;
2227         IF check_parentproj_exists_wp%NOTFOUND THEN
2228         CLOSE check_parentproj_exists_wp;
2229           RETURN 'N';
2230         ELSE
2231           CLOSE check_parentproj_exists_wp;
2232           RETURN 'Y';
2233         END IF;
2234     ELSIF p_link_type = 'FINANCIAL'
2235     THEN
2236         OPEN check_parentproj_exists_fn;
2237         FETCH check_parentproj_exists_fn INTO l_dummy;
2238         IF check_parentproj_exists_fn%NOTFOUND THEN
2239         CLOSE check_parentproj_exists_fn;
2240           RETURN 'N';
2241         ELSE
2242           CLOSE check_parentproj_exists_fn;
2243           RETURN 'Y';
2244         END IF;
2245     END IF;
2246 
2247 END Check_parent_project_Exists;
2248 
2249 --bug 4619824
2250 FUNCTION Check_subproject_link_exists(p_project_id number
2251    ,p_link_type    VARCHAR2 DEFAULT 'SHARED'    --bug 4532826
2252 ) return VARCHAR2
2253 IS
2254   CURSOR get_count IS
2255     Select count(1) from pa_object_relationships
2256      where relationship_type IN ('LW', 'LF')
2257        and object_id_from2 = p_project_id;
2258 
2259   CURSOR get_count_fn IS
2260     Select count(1) from pa_object_relationships
2261      where relationship_type = 'LF'
2262        and object_id_from2 = p_project_id;
2263 
2264   CURSOR get_count_wp IS
2265     Select count(1) from pa_object_relationships
2266      where relationship_type = 'LW'
2267        and (object_id_from2 = p_project_id);
2268 
2269 
2270   l_cnt NUMBER :=0;
2271 BEGIN
2272   IF p_link_type = 'SHARED'
2273   THEN
2274       OPEN get_count;
2275       FETCH get_count into l_cnt;
2276       CLOSE get_count;
2277   ELSIF  p_link_type = 'FINANCIAL'
2278   THEN
2279 
2280       OPEN get_count_fn;
2281       FETCH get_count_fn into l_cnt;
2282       CLOSE get_count_fn;
2283 
2284   ELSIF  p_link_type = 'WORKPLAN'
2285   THEN
2286 
2287       OPEN get_count_wp;
2288       FETCH get_count_wp into l_cnt;
2289       CLOSE get_count_wp;
2290 
2291   END IF;
2292 
2293   IF l_cnt > 0 THEN
2294      return 'Y';
2295   END IF;
2296 
2297   return 'N';
2298 END Check_subproject_link_exists;
2299 
2300 
2301 end PA_RELATIONSHIP_UTILS;