1 PACKAGE BODY QA_PARENT_CHILD_PKG as
2 /* $Header: qapcb.pls 120.26.12010000.2 2008/09/26 13:43:11 pdube ship $ */
3
4 -- Bug 4343758
5 -- R12 OAF Txn Integration Project
6 -- Standard Global variable
7 -- shkalyan 05/07/2005.
8 g_pkg_name CONSTANT VARCHAR2(30) := 'QA_PARENT_CHILD_PKG';
9
10 --
11 -- Through out this package all the functions will return 'T' or 'F'
12 -- instead of 'TRUE' or 'FALSE'. The reason is, we may call this
13 -- serverside functions from Java or by other platforms.
14 --
15
16 FUNCTION aggregate_functions(p_sql_string IN VARCHAR2,
17 p_occurrence IN NUMBER,
18 p_child_plan_id IN NUMBER,
19 x_value OUT NOCOPY NUMBER) RETURN VARCHAR2 IS
20 l_value NUMBER;
21
22 BEGIN
23 BEGIN
24 EXECUTE IMMEDIATE p_sql_string INTO l_value USING p_occurrence,p_child_plan_id;
25
26 -- Bug 2716973
27 -- Even though fix here is not required, but for consistency adding NVL function here.
28 -- rponnusa Sun Jan 12 23:59:07 PST 2003
29
30 x_value := NVL(l_value,0);
31 RETURN 'T';
32 EXCEPTION
33 WHEN OTHERS THEN
34 RETURN 'F';
35 END;
36
37 END aggregate_functions;
38
39 --
40 -- bug 5682448
41 -- added the Txn_header_id parameter
42 -- ntungare Wed Feb 21 07:28:43 PST 2007
43 --
44 FUNCTION aggregate_functions(p_sql_string IN VARCHAR2,
45 p_occurrence IN NUMBER,
46 p_child_plan_id IN NUMBER,
47 p_txn_header_id IN NUMBER,
48 x_value OUT NOCOPY NUMBER) RETURN VARCHAR2 IS
49 l_value NUMBER;
50
51 BEGIN
52 BEGIN
53 EXECUTE IMMEDIATE p_sql_string INTO l_value
54 USING p_occurrence,p_child_plan_id,p_txn_header_id;
55
56 -- Bug 2716973
57 -- Even though fix here is not required, but for consistency adding NVL function here.
58 -- rponnusa Sun Jan 12 23:59:07 PST 2003
59 x_value := NVL(l_value,0);
60 RETURN 'T';
61 EXCEPTION
62 WHEN OTHERS THEN
63 RETURN 'F';
64 END;
65
66 END aggregate_functions;
67
68
69 FUNCTION commit_allowed(p_plan_id NUMBER, p_collection_id NUMBER,
70 p_occurrence NUMBER ,p_child_plan_ids VARCHAR2) RETURN VARCHAR2 IS
71 l_incomplete_plan_ids VARCHAR2(10000);
72 BEGIN
73
74 -- Bug 5161719. SHKALYAN 13-Apr-2006
75 -- Modified to call the new overloaded commit_allowed to avoid
76 -- code duplication
77 RETURN commit_allowed
78 (
79 p_plan_id => p_plan_id,
80 p_collection_id => p_collection_id,
81 p_occurrence => p_occurrence,
82 p_child_plan_ids => p_child_plan_ids,
83 x_incomplete_plan_ids => l_incomplete_plan_ids
84 );
85 END commit_allowed;
86
87 -- Bug 5161719. SHKALYAN 13-Apr-2006
88 -- Created this overloaded commit_allowed function to pass back to the
89 -- caller a list of incomplete child plan ids in x_incomplete_plan_ids
90 -- This is because in OAF Txn integration project the message is expected
91 -- to have the incomplete child plan information.
92 -- Rest of the logic was moved from the old get_plan_name
93 -- to avoid code duplication.
94 FUNCTION commit_allowed(
95 p_plan_id NUMBER,
96 p_collection_id NUMBER,
97 p_occurrence NUMBER,
98 p_child_plan_ids VARCHAR2,
99 x_incomplete_plan_ids OUT NOCOPY VARCHAR2) RETURN VARCHAR2 IS
100
101 ---
102 --- Simple function which returns True when results are collected for
103 --- immediate child plans else returns False.
104 ---
105 --- Important thing to remember here is that collection_id for parent
106 --- child plan are same in case of EQR. That is the reason I have included
107 --- one more where condtion in the cursor c2. See the following statement
108 --- 'AND child_collection_id = p_collection_id '
109 ---
110 --- The parameter 'p_child_plan_ids' will contain all the immediate child plan ids
111 --- separated by comma operator.
112
113
114 l_child_id_array ChildPlanArray;
115 l_child_plan_id NUMBER;
116 l_total_length NUMBER;
117 l_result VARCHAR2(1);
118 separator CONSTANT VARCHAR2(1) := ',';
119
120 -- Bug 2300962. Removed child_collection_id in the where clause
121 -- To check, child is entered or not child plan id is enough.
122
123 CURSOR c2(c_child_plan_id NUMBER) IS
124 SELECT 'T' FROM qa_pc_results_relationship
125 WHERE parent_plan_id = p_plan_id
126 AND parent_collection_id = p_collection_id
127 AND parent_occurrence = p_occurrence
128 AND child_plan_id = c_child_plan_id
129 AND rownum =1;
130
131 BEGIN
132 l_result := 'F';
133 l_total_length := LENGTH(p_child_plan_ids);
134
135 -- We need check for all the child_plan_ids one by one to see whether records are
136 -- entered for the child plan or not.
137
138 -- anagarwa Mon Apr 15 15:51:58 PDT 2002
139 -- Bug 2320896 was being caused due to error in logic.
140 -- This code is being replaced to avoid character to number conversion
141
142
143 parse_list(p_child_plan_ids, l_child_id_array);
144
145 FOR i IN 1..l_child_id_array.COUNT LOOP
146 l_child_plan_id := l_child_id_array(i);
147 OPEN c2(l_child_plan_id);
148 FETCH c2 INTO l_result;
149 IF (c2%NOTFOUND) THEN
150 l_result := 'F';
151
152 -- Bug 5161719. SHKALYAN 13-Apr-2006
153 -- In addition to setting result as false form the list of
154 -- incomplete plan ids
155 x_incomplete_plan_ids := x_incomplete_plan_ids || separator || l_child_plan_id;
156 CLOSE c2;
157 EXIT;
158 END IF;
159 CLOSE c2;
160
161 END LOOP;
162
163 -- Bug 5161719. SHKALYAN 13-Apr-2006
164 -- Remove the leading comma
165 IF ( x_incomplete_plan_ids IS NOT NULL ) THEN
166 x_incomplete_plan_ids := SUBSTR( x_incomplete_plan_ids, LENGTH(separator) + 1 );
167 END IF;
168
169 RETURN l_result;
170
171 END commit_allowed;
172
173
174 PROCEDURE enable_and_fire_actions(p_collection_id NUMBER) IS
175
176 ---
177 --- This procedure commits all the records corresponding to one single session with status = 2.
178 --- This is required since all the child records will be saved with qa_results.status =1
179 --- When the child record is enabled, status code will be changed to 2. The status of
180 --- child record is changed to 2 only when Parent record gets committed
181 ---
182
183 BEGIN
184 qa_results_api.enable_and_fire_action(p_collection_id);
185 END enable_and_fire_actions;
186
187 FUNCTION get_descendants(
188 p_plan_id NUMBER,
189 p_collection_id NUMBER,
190 p_occurrence NUMBER,
191 x_plan_ids OUT NOCOPY dbms_sql.number_table,
192 x_collection_ids OUT NOCOPY dbms_sql.number_table,
193 x_occurrences OUT NOCOPY dbms_sql.number_table) RETURN VARCHAR2 IS
194
195 ---
196 --- Given a parent record (plan/collection/occurrence), this procedure finds all the child and
197 --- grandchildren records (therefore, descendants) of the record. These are returned in the
198 --- three output PL/SQL tables. The parent record itself is not included in the output.
199 --- The query technical is called hierarchical subquery. The final where clause makes
200 --- sure the child record is actually enabled in the qa_results table.
201 ---
202
203 BEGIN
204
205 SELECT child_plan_id, child_collection_id, child_occurrence
206 BULK COLLECT INTO
207 x_plan_ids, x_collection_ids, x_occurrences
208 FROM qa_pc_results_relationship r
209 WHERE EXISTS (
210 SELECT 1
211 FROM qa_results qr
212 WHERE qr.plan_id = r.child_plan_id AND
213 qr.collection_id = r.child_collection_id AND
214 qr.occurrence = r.child_occurrence AND
215 (qr.status IS NULL or qr.status=2) )
216 START WITH parent_plan_id = p_plan_id AND
217 parent_collection_id = p_collection_id AND
218 parent_occurrence = p_occurrence
219 CONNECT BY PRIOR child_occurrence = parent_occurrence;
220
221 IF (SQL%FOUND) THEN
222 RETURN 'T';
223 ELSE
224 RETURN 'F';
225 END IF;
226
227 END get_descendants;
228
229 ---------------------------------------------------------------------------
230 FUNCTION evaluate_child_lov_criteria( p_plan_id IN NUMBER,
231 p_criteria_values IN VARCHAR2,
232 x_child_plan_ids OUT NOCOPY VARCHAR2)
233 RETURN VARCHAR2 IS
234 ---
235 --- This function finds all the matching child plan for the current plan.
236 --- First converts the values passed through p_criteria_values
237 --- into array. For each child plan we checking for the criteria values
238 --- by calling another function 'criteria_matched'.
239 --- We will concatenate all the child id into string with separator as ','
240 --- Return true if any matching child availabe with the concatenated
241 --- child plan_id's otherwise return false.
242 ---
243
244 -- Bug 2448888. when all child plans have effective from and to date range is
245 -- outside the sysdate then, FRM-41084:- Error getting Group Cell raised when
246 -- child button is hit. This is similar to bug Bug 2355817.
247 -- Make a join to qa_plans in cursor C and fetch only effective child plans.
248 -- rponnusa Tue Jul 9 00:25:19 PDT 2002
249
250 CURSOR c IS SELECT qpr.plan_relationship_id,qpr.child_plan_id
251 FROM qa_plans qp,
252 qa_pc_plan_relationship qpr
253 WHERE qpr.parent_plan_id = p_plan_id
254 AND qpr.child_plan_id = qp.plan_id
255 AND qpr.plan_relationship_type = 1
256 AND qpr.data_entry_mode in (1,2,3)
257 AND ((qp.effective_to IS NULL AND TRUNC(SYSDATE) >= qp.effective_from)
258 OR (qp.effective_from IS NULL AND TRUNC(SYSDATE) <= qp.effective_to)
259 OR (qp.effective_from IS NOT NULL AND qp.effective_to IS NOT NULL
260 AND TRUNC(SYSDATE) BETWEEN qp.effective_from AND qp.effective_to)
261 OR (qp.effective_from IS NULL AND qp.effective_to IS NULL ));
262
263 current_child_plan_id NUMBER;
264 p_plan_relationship_id NUMBER;
265 ret_value VARCHAR2(1);
266 childexist BOOLEAN;
267 elements qa_txn_grp.ElementsArray;
268 BEGIN
269 ret_value := 'F';
270 childexist := FALSE;
271 elements := qa_txn_grp.result_to_array(p_criteria_values);
272 OPEN c;
273 LOOP
274 FETCH c INTO p_plan_relationship_id,current_child_plan_id;
275 IF (c%NOTFOUND) THEN
276 EXIT;
277 END IF;
278
279 IF( criteria_matched(p_plan_relationship_id,elements) = 'T') THEN
280
281 IF( childexist) THEN
282 x_child_plan_ids := x_child_plan_ids ||','||current_child_plan_id;
283 ELSE
284 x_child_plan_ids :=current_child_plan_id;
285 childexist := TRUE;
286 END IF;
287 END IF;
288 END LOOP;
289
290 IF (c%ROWCOUNT = 0) THEN
291 ret_value := 'F';
292 ELSIF (x_child_plan_ids IS NULL) THEN
293 ret_value := 'F';
294 ELSE
295 ret_value := 'T';
296 END IF;
297 CLOSE c;
298
299 RETURN ret_value;
300 END evaluate_child_lov_criteria;
301
302 /* following function added to be able to view history records in VQR.
303 The name is eval_updateview_lov_criteria and NOT evaluate_updateview_lov_criteria
304 because there's a character limit for length of function name in package.
305 */
306
307 FUNCTION eval_updateview_lov_criteria( p_plan_id IN NUMBER,
308 p_criteria_values IN VARCHAR2,
309 x_child_plan_ids OUT NOCOPY VARCHAR2)
310 RETURN VARCHAR2 IS
311 ---
312 --- This function finds all the matching child plan for the current plan.
313 --- First converts the values passed through p_criteria_values
314 --- into array. For each child plan we checking for the criteria values
315 --- by calling another function 'criteria_matched'.
316 --- We will concatenate all the child id into string with separator as ','
317 --- Return true if any matching child availabe with the concatenated
318 --- child plan_id's otherwise return false.
319 ---
320
321 -- Bug 2448888. when all child plans have effective from and to date range is
322 -- outside the sysdate then, FRM-41084:- Error getting Group Cell raised when
323 -- child button is hit. This is similar to bug Bug 2355817.
324 -- Make a join to qa_plans in cursor C and fetch only effective child plans.
325 -- rponnusa Tue Jul 9 00:25:19 PDT 2002
326
327 CURSOR c IS SELECT qpr.plan_relationship_id,qpr.child_plan_id
328 FROM qa_plans qp,
329 qa_pc_plan_relationship qpr
330 WHERE qpr.parent_plan_id = p_plan_id
331 AND qpr.child_plan_id = qp.plan_id
332 AND qpr.plan_relationship_type = 1
333 AND qpr.data_entry_mode in (1,2,3,4)
334 AND ((qp.effective_to IS NULL AND TRUNC(SYSDATE) >= qp.effective_from)
335 OR (qp.effective_from IS NULL AND TRUNC(SYSDATE) <= qp.effective_to)
336 OR (qp.effective_from IS NOT NULL AND qp.effective_to IS NOT NULL
337 AND TRUNC(SYSDATE) BETWEEN qp.effective_from AND qp.effective_to)
338 OR (qp.effective_from IS NULL AND qp.effective_to IS NULL ));
339
340 current_child_plan_id NUMBER;
341 p_plan_relationship_id NUMBER;
342 ret_value VARCHAR2(1);
343 childexist BOOLEAN;
344 elements qa_txn_grp.ElementsArray;
345 BEGIN
346 ret_value := 'F';
347 childexist := FALSE;
348 elements := qa_txn_grp.result_to_array(p_criteria_values);
349 OPEN c;
350 LOOP
351 FETCH c INTO p_plan_relationship_id,current_child_plan_id;
352 IF (c%NOTFOUND) THEN
353 EXIT;
354 END IF;
355
356 IF( criteria_matched(p_plan_relationship_id,elements) = 'T') THEN
357
358 IF( childexist) THEN
359 x_child_plan_ids := x_child_plan_ids ||','||current_child_plan_id;
360 ELSE
361 x_child_plan_ids :=current_child_plan_id;
362 childexist := TRUE;
363 END IF;
364 END IF;
365 END LOOP;
366
367 IF (c%ROWCOUNT = 0) THEN
368 ret_value := 'F';
369 ELSIF (x_child_plan_ids IS NULL) THEN
370 ret_value := 'F';
371 ELSE
372 ret_value := 'T';
373 END IF;
374 CLOSE c;
375
376 RETURN ret_value;
377
378 END eval_updateview_lov_criteria;
379
380 -----------------------------------------------------------------------------------------------------
381 FUNCTION criteria_matched(p_plan_relationship_id IN NUMBER,
382 p_criteria_array qa_txn_grp.ElementsArray)
383 RETURN VARCHAR2 IS
384
385 ---
386 --- This function first finds out all the criteria for the parent-child
387 --- relationship through plan_relationship_id in qa_pc_criteria table.
388 --- If no criteria found then return true
389 --- else finds out all the char_id and its associated values
390 --- for the plan_relationship_id.
391
392 --- Check for each char_id (ie,. element ) to see value available
393 --- in the parent form. We are checking this condition in the
394 --- element array (which contains all the parent-form char_id and
395 --- its associated value). If, not able to find the char_id in the
396 --- element array then return false.
397
398 --- If there is matching char_id in element array then compare
399 --- the value in the element array with the low_value, high_value.
400 --- If everything is ok then return true, false otherwise.
401 ---
402
403 l_char_id NUMBER ;
404 l_operator NUMBER ;
405 l_low_value VARCHAR2(150);
406 l_high_value VARCHAR2(150);
407 l_ret_value VARCHAR2(1);
408 l_datatype NUMBER;
409
410 CURSOR c IS SELECT qpc.char_id,qpc.operator,qpc.low_value,qpc.high_value,qc.datatype
411 FROM qa_pc_criteria qpc ,qa_chars qc
412 WHERE qpc.plan_relationship_id = p_plan_relationship_id
413 AND qpc.char_id = qc.char_id;
414 BEGIN
415
416 l_ret_value := 'F';
417 OPEN c;
418
419 -- To launch a single child plan there may be more than one criteria defined.
420 -- Hence going into the loop to match all criteria. In case of more than one
421 -- criteria, all the criteria should match in order to return TRUE
422
423 LOOP
424 FETCH c INTO l_char_id, l_operator, l_low_value, l_high_value, l_datatype;
425 IF (c%NOTFOUND) THEN
426 EXIT;
427 END IF;
428
429 -- There are records for the plan_relationship_id, our next job is to
430 -- check the value entered in the parent plan for the element, matches
431 -- with the criteria for the same element in qa_pc_criteria
432
433 IF (p_criteria_array.EXISTS(l_char_id)) THEN
434
435 IF( QLTCOMPB.compare(p_criteria_array(l_char_id).value,
436 l_operator,l_low_value,
437 l_high_value,l_datatype)) THEN
438
439 l_ret_value := 'T';
440 ELSE
441 -- For example if 3 criteria defined and matching condition
442 -- fails in the first criteria itself then we need not check for
443 -- other criterias, we can simply exit from the loop and
444 -- return FALSE
445
446 l_ret_value := 'F';
447 EXIT;
448 END IF;
449 ELSE
450 -- This is a worst case. There is no value found in the element array
451 -- for the char_id
452 l_ret_value := 'F';
453 END IF;
454 END LOOP;
455
456 IF (c%ROWCOUNT = 0) THEN
457 -- No criteria defined for the plan, so simply return TRUE
458 l_ret_value := 'T';
459 END IF;
460 CLOSE c;
461
462 RETURN l_ret_value;
463 END criteria_matched;
464
465 ------------------------------------------------------------------------------------------
466 FUNCTION evaluate_criteria(p_plan_id IN NUMBER,
467 p_criteria_values IN VARCHAR2,
468 p_relationship_type IN NUMBER,
469 p_data_entry_mode IN NUMBER,
470 x_child_plan_ids OUT NOCOPY VARCHAR2) RETURN VARCHAR2 IS
471 --
472 -- This function finds out the matching child plan for the given data_entry_mode and
473 -- relationship_type. In case of matching child found returns TRUE with the child
474 -- plan_id in a comma separated string through x_child_plan_ids.
475 -- In case of no match simply returns FALSE
476 --
477
478 CURSOR c IS SELECT plan_relationship_id,child_plan_id
479 FROM qa_pc_plan_relationship
480 WHERE parent_plan_id = p_plan_id
481 AND plan_relationship_type = p_relationship_type
482 AND data_entry_mode = p_data_entry_mode;
483
484 -- Added the cursor below to check the effectivity of the child plan.
485 -- The Cursor will fetch the child_plan only if it falls in the effective
486 -- data range. Bug 2355817. kabalakr 06 MAY 2002.
487
488 CURSOR p(l_child_plan_id NUMBER) IS
489 SELECT plan_id
490 FROM qa_plans
491 WHERE plan_id = l_child_plan_id
492 AND ((effective_to IS NULL AND TRUNC(SYSDATE) >= effective_from)
493 OR (effective_from IS NULL AND TRUNC(SYSDATE) <= effective_to)
494 OR (effective_from IS NOT NULL AND effective_to IS NOT NULL
495 AND TRUNC(SYSDATE) BETWEEN effective_from AND effective_to)
496 OR (effective_from IS NULL AND effective_to IS NULL ));
497
498
499 current_child_plan_id NUMBER ;
500 p_plan_relationship_id NUMBER ;
501 ret_value VARCHAR2(1);
502 childexist BOOLEAN;
503 separator CONSTANT VARCHAR2(1) := ',';
504
505 elements qa_txn_grp.ElementsArray;
506
507 -- Bug 2355817. kabalakr
508 l_child_pl_id NUMBER;
509
510 BEGIN
511 ret_value := 'F';
512 childexist := FALSE;
513 elements := qa_txn_grp.result_to_array(p_criteria_values);
514 OPEN c;
515 -- Get all the child plan id for the parent plan to find out any matching
516 -- childplan is exist or not.
517 LOOP
518
519 FETCH c INTO p_plan_relationship_id,current_child_plan_id;
520 IF (c%NOTFOUND) THEN
521 EXIT;
522 END IF;
523
524 -- Open cursor p for the current child_plan_id. Call criteria_matched
525 -- only if the cursor fetches the plan. Bug 2355817.
526 -- kabalakr 06 MAY 2002.
527
528 OPEN p(current_child_plan_id);
529 FETCH p INTO l_child_pl_id;
530
531 IF (p%FOUND) THEN
532
533 IF( criteria_matched(p_plan_relationship_id,elements) = 'T') THEN
534
535 -- The following 'if' condition is required because we should not return the
536 -- child plan ids with last character as the separator ( comma here)
537
538 IF( childexist) THEN
539 x_child_plan_ids := x_child_plan_ids || separator ||current_child_plan_id;
540 ELSE
541 x_child_plan_ids :=current_child_plan_id;
542 childexist := TRUE;
543 END IF;
544
545 END IF;
546 END IF;
547
548 CLOSE p;
549
550 END LOOP;
551
552 IF (c%ROWCOUNT = 0) THEN
553 -- This scanario can happen if the parent plan dont have child plan associated
554 -- with it.
555 ret_value := 'F';
556
557 ELSIF (x_child_plan_ids IS NULL) THEN
558 -- This can happen when parent plan have child but the matching criteria to launch the
559 -- child fails
560 ret_value := 'F';
561 ELSE
562 ret_value := 'T';
563 END IF;
564 CLOSE c;
565
566 RETURN ret_value;
567
568 END evaluate_criteria;
569
570 PROCEDURE parse_list(x_result IN VARCHAR2,
571 x_array OUT NOCOPY ChildPlanArray) IS
572
573 -- For longcomments enhancement, Bug 2234299
574 -- changed 'value' type from qa_results.character1%TYPE to varchar2(2000)
575 -- rponnusa Thu Mar 14 21:27:04 PST 2002
576
577 value VARCHAR2(2000);
578 c VARCHAR2(10);
579 separator CONSTANT VARCHAR2(1) := ',';
580 arr_index INTEGER;
581 p INTEGER;
582 n INTEGER;
583
584 BEGIN
585 --
586 -- Loop until a single ',' is found or x_result is exhausted.
587 --
588 arr_index := 1;
589 p := 1;
590 n := length(x_result);
591 WHILE p <= n LOOP
592 c := substr(x_result, p, 1);
593 p := p + 1;
594 IF (c = separator) THEN
595 x_array(arr_index) := value;
596 arr_index := arr_index + 1;
597 value := '';
598 ELSE
599 value := value || c;
600 END IF;
601
602 END LOOP;
603 x_array(arr_index) := value;
604 END parse_list;
605
606 --
607 -- Removed DEFAULT clause for GSCC compliance
608 -- Before removal
609 -- p_txn_header_id IN NUMBER DEFAULT NULL
610 -- After removal
611 -- p_txn_header_id IN NUMBER
612 -- rkunchal
613 --
614
615 PROCEDURE insert_automatic_records(p_plan_id IN NUMBER,
616 p_collection_id IN NUMBER,
617 p_occurrence IN NUMBER,
618 p_child_plan_ids IN VARCHAR2,
619 p_relationship_type IN NUMBER,
620 p_data_entry_mode IN NUMBER,
621 p_criteria_values IN VARCHAR2,
622 p_org_id IN NUMBER,
623 p_spec_id IN NUMBER,
624 x_status OUT NOCOPY VARCHAR2,
625 p_txn_header_id IN NUMBER) IS
626
627 parent_values_array qa_txn_grp.ElementsArray;
628 l_child_id_array ChildPlanArray;
629 l_sysdate DATE;
630 l_length INTEGER;
631 l_row_count INTEGER;
632 l_count INTEGER;
633 l_child_char_id INTEGER;
634 l_parent_char_id INTEGER;
635 l_p INTEGER;
636 l_return_int INTEGER;
637 l_occurrence NUMBER;
638 l_child_plan_id NUMBER;
639 l_child_element_values VARCHAR2(32000);
640 l_messages VARCHAR2(32000);
641 l_rowid VARCHAR2(1000);
642
643
644 CURSOR row_num_cur(c_child_plan_id NUMBER) IS
645 SELECT auto_row_count
646 FROM qa_pc_plan_relationship
647 WHERE parent_plan_id = p_plan_id
648 AND child_plan_id = c_child_plan_id;
649
650
651 -- anagarwa Mon Dec 16 16:55:09 PST 2002
652 -- Bug 2701777
653 -- if parent or child elements are disabled and the parent child relationship
654 -- still exists for them then insert API qa_mqa_results.post_result raises
655 -- returns an error and prevents the history as well as automatic results
656 -- from being saved. It causes a ON-INSERT trigger being raised on forms
657 -- and even the parent results cannot be saved.
658 -- To fix the problem, qa_pc_result_column_v is being modified to have parent
659 -- and child char's enabled flags which are checked to be 1 before the values
660 -- are copied.
661
662 CURSOR char_id_cur(c_child_plan_id NUMBER) IS
663 SELECT parent_char_id, child_char_id
664 FROM qa_pc_result_columns_v
665 WHERE parent_plan_id = p_plan_id
666 AND child_plan_id = c_child_plan_id
667 AND parent_enabled_flag = 1
668 AND child_enabled_flag = 1;
669
670 -- Bug 3678910. In Automatic data collection, sequence generation should be
671 -- enabled for Sequence type elements. The below cursor will fetch all the
672 -- sequence element char_ids which is not a target for Copy Element relation.
673 -- If there exist any copy relation with sequence element as target, the value
674 -- will be copied from the parent plan. Sequence will not get generated in that
675 -- case. kabalakr.
676
677 -- Bug 4958734. SQL Repository Fix SQL ID: 15007931
678 CURSOR child_seq_char_ids(c_child_plan_id NUMBER) IS
679 SELECT qc.char_id
680 FROM qa_plan_chars qpc, qa_chars qc
681 WHERE qpc.plan_id = c_child_plan_id
682 AND qpc.char_id = qc.char_id
683 AND qpc.enabled_flag = 1
684 AND qc.datatype = 5
685 MINUS
686 SELECT child_char_id
687 FROM qa_pc_result_columns_v
688 WHERE parent_plan_id = p_plan_id
689 AND child_plan_id = c_child_plan_id
690 AND parent_enabled_flag = 1
691 AND child_enabled_flag = 1;
692 /*
693 SELECT qc.char_id
694 FROM qa_plan_chars qpc,
695 qa_chars qc
696 WHERE qpc.plan_id = c_child_plan_id
697 AND qpc.char_id = qc.char_id
698 AND qpc.enabled_flag = 1
699 AND qc.datatype = 5
700 AND qc.char_id NOT IN
701 (SELECT child_char_id
702 FROM qa_pc_result_columns_v
703 WHERE parent_plan_id = p_plan_id
704 AND child_plan_id = c_child_plan_id
705 AND parent_enabled_flag = 1
706 AND child_enabled_flag = 1);
707 */
708
709 l_seq_default_str VARCHAR(30);
710
711 --
712 -- Bug 5383667
713 -- String to hold the Id values
714 -- ntungare
715 --
716 l_char_id_val VARCHAR2(2000);
717 l_id_str VARCHAR2(2000);
718
719 --
720 -- bug 6086385
721 -- New variable to catch the status returned
722 -- by the insert_history_auto_rec_QWB proc
723 -- called for the subsequent child records
724 -- ntungare Thu Jul 5 06:50:27 PDT 2007
725 --
726 auto_hist_proc_stat varchar2(2000);
727
728 --
729 -- bug 6086385
730 -- New variable to read the occurrence of
731 -- the Child plan record enetred
732 -- ntungare Thu Jul 5 06:50:27 PDT 2007
733 --
734 l_child_occurrence NUMBER;
735
736 BEGIN
737 l_length := length(p_child_plan_ids);
738 l_count := 1;
739 l_sysdate := sysdate;
740
741 -- flatten the p_criteria_values string into an array
742 parent_values_array := qa_txn_grp.result_to_array(p_criteria_values);
743
744 --parse p_child_plan_ids to get child plan ids in an array
745 IF p_child_plan_ids IS NOT NULL THEN
746 l_p := 0;
747 parse_list(p_child_plan_ids, l_child_id_array);
748 END IF;
749 --for each child plan insert automatic rows as follows
750 FOR i IN 1..l_child_id_array.COUNT LOOP
751
752 l_child_plan_id := l_child_id_array(i);
753
754 --if p_relationship_type=1 and p_data_entry_mode=4, it means we are
755 --entering rows for History plan. The number of rows to be entered
756 -- in this case is always 1. ELSE get the number of rows to be entered.
757 IF(p_relationship_type=1 AND p_data_entry_mode=4) THEN
758 l_row_count := 1;
759 ELSE
760 OPEN row_num_cur(l_child_id_array(i));
761 fetch row_num_cur into l_row_count;
762 CLOSE row_num_cur;
763 END IF;
764 --for row_count
765 WHILE l_count <= l_row_count LOOP
766 --OPEN cursor of parent_char_id and child_char_id from
767 -- QA_PC_RESULTS_COLUMN_V for p_plan_id and current child plan id
768 --for each cursor row
769 l_child_element_values := '';
770 FOR char_id_record IN char_id_cur(l_child_id_array(i)) LOOP
771 l_parent_char_id := char_id_record.parent_char_id;
772 l_child_char_id := char_id_record.child_char_id;
773
774 -- Bug 2403395
775 -- Added 'replace' command to doubly encode ''@' character
776 -- if the l_parent_char_id.value contains '@' character.
777 -- rponnusa Wed Jun 5 00:49:14 PDT 2002
778 l_child_element_values := l_child_element_values || '@' ||
779 l_child_char_id || '=' ||
780 replace(parent_values_array(l_parent_char_id).value,'@','@@');
781
782 --
783 -- Bug 5383667
784 -- Constructing the Id str
785 -- The id string has to be built of the format
786 -- charid=value@charid=value.
787 -- ntungare
788 --
789 l_char_id_val := qa_plan_element_api.get_id_val
790 (l_child_char_id,
791 p_plan_id,
792 p_collection_id,
793 p_occurrence);
794
795 If l_char_id_val IS NOT NULL THEN
796 l_id_str := l_id_str || '@' || l_child_char_id || '='|| l_char_id_val;
797 End If;
798
799 END LOOP; -- for all columns to be copied
800
801 -- Bug 3678910. Now, check whether we are inserting records for
802 -- data entry mode - Automatic. If yes, we should make sure to generate
803 -- sequence numbers (assign the string 'Automatic') for sequence type
804 -- elements that are not copy targets. kabalakr.
805
806 IF(p_relationship_type=1 AND p_data_entry_mode=2) THEN
807
808 fnd_message.set_name('QA','QA_SEQ_DEFAULT');
809 l_seq_default_str := fnd_message.get;
810
811 FOR seq_char_id_record IN child_seq_char_ids(l_child_id_array(i))
812 LOOP
813 l_child_element_values := l_child_element_values || '@' ||
814 seq_char_id_record.char_id || '=' ||
815 l_seq_default_str;
816 END LOOP;
817
818 END IF; -- If Automatic. End of bug 3678910.
819
820 --
821 -- Bug 5383667
822 -- Removing the extra @ appended at the start
823 -- ntungare
824 --
825 If l_id_str IS NOT NULL THEN
826 l_id_str := SUBSTR(l_id_str, 2);
827 END If;
828
829 IF (l_child_element_values IS NOT NULL) THEN
830 l_child_element_values := substr(l_child_element_values,2);
831 l_p :=1;
832
833 --
834 -- bug 5682448
835 -- modified the call to the proc to send the commit
836 -- flag as no (0)
837 -- ntungare Wed Feb 21 07:31:00 PST 2007
838 --
839
840 -- Bug 2290747.Added parameter p_txn_header_id to enable
841 -- history plan record when parent plan gets updated
842 -- rponnusa Mon Apr 1 22:25:49 PST 2002
843
844 -- anagarwa Thu Dec 19 15:43:27 PST 2002
845 -- Bug 2701777
846 -- post_result_with_no_validation inserts records into
847 -- qa_results without any validations. This prevents any
848 -- errors if user changes element values in parent plan
849 -- but not the History plan
850
851 --
852 -- bug 5383667
853 -- Passing the Id string as well
854 -- ntungare
855 --
856 l_return_int:= qa_mqa_results.post_result_with_no_validation(
857 l_occurrence,
858 p_org_id,
859 l_child_plan_id, p_spec_id,
860 p_collection_id,
861 l_child_element_values,
862 l_id_str, '', l_p, 0, l_messages,
863 p_txn_header_id);
864
865 --ilawler - bug #2648137 - Fri Mar 19 09:50:07 2004
866 --added post_result return check
867 IF l_return_int = -1 THEN
868 x_status := 'F';
869 RETURN;
870 END IF;
871
872 -- anagarwa Fri Aug 30 13:07:05 PDT 2002
873 -- Bug 2517932
874 -- following added to copy attachments to History records.
875
876 IF p_data_entry_mode = 4 THEN
877 FND_ATTACHED_DOCUMENTS2_PKG.copy_attachments(
878 X_from_entity_name => 'QA_RESULTS',
879 X_from_pk1_value => to_char(p_occurrence),
880 X_from_pk2_value => to_char(p_collection_id),
881 X_from_pk3_value => to_char(p_plan_id),
882 X_to_entity_name => 'QA_RESULTS',
883 X_to_pk1_value => to_char(l_occurrence),
884 X_to_pk2_value => to_char(p_collection_id),
885 X_to_pk3_value => to_char(l_child_plan_id));
886 END IF;
887
888 -- insert the relationships
889 -- Gapless Sequence Proj. rponnusa Wed Jul 30 04:52:45 PDT 2003
890 -- passing child_txn_header_id
891 QA_PC_RESULTS_REL_PKG.Insert_Row(
892 X_Rowid => l_rowid,
893 X_Parent_Plan_Id => p_plan_id,
894 X_Parent_Collection_Id => p_collection_id,
895 X_Parent_Occurrence => p_occurrence,
896 X_Child_Plan_Id => l_child_plan_id,
897 X_Child_Collection_Id => p_collection_id,
898 X_Child_Occurrence => l_occurrence,
899 X_Enabled_Flag => 1,
900 X_Last_Update_Date => l_sysdate,
901 X_Last_Updated_By => fnd_global.user_id,
902 X_Creation_Date => l_sysdate,
903 X_Created_By => fnd_global.user_id,
904 X_Last_Update_Login => fnd_global.user_id,
905 X_Child_Txn_Header_Id => p_txn_header_id);
906
907 END IF;
908 l_count := l_count + 1;
909
910 --
911 -- Bug 5383667
912 -- Resetting the Id string for the next row being
913 -- processed
914 -- ntungare
915 l_id_str := NULL;
916
917 --
918 -- bug 6086385
919 -- Getting the Occurrence of the Child record that has been
920 -- inserted
921 -- nutngare Thu Jul 5 05:21:16 PDT 2007
922 --
923 SELECT MAX(occurrence)
924 into l_child_occurrence
925 FROM qa_results
926 WHERE plan_id = l_child_plan_id and
927 collection_id = p_collection_id and
928 organization_id = p_org_id and
929 txn_header_id = p_txn_header_id;
930
931 --
932 -- bug 6086385
933 -- Processing the Subsequent Automatic Child plans
934 -- Using the insert_history_auto_rec_QWB instead of
935 -- insert_history_auto_rec to make sure that the Txn_header_id
936 -- is not incremented
937 -- ntungare Thu Jul 5 05:15:29 PDT 2007
938 --
939 insert_history_auto_rec_QWB(p_plan_id => l_child_plan_id,
940 p_collection_id => p_collection_id,
941 p_occurrence => l_child_occurrence,
942 p_organization_id => p_org_id,
943 p_txn_header_id => p_txn_header_id,
944 p_relationship_type => 1,
945 p_data_entry_mode => 2 ,
946 x_status => auto_hist_proc_stat);
947
948 --
949 -- bug 6086385
950 -- Processing the History Child plans
951 -- Using the insert_history_auto_rec_QWB instead of
952 -- insert_history_auto_rec to make sure that the Txn_header_id
953 -- is not incremented
954 -- ntungare Thu Jul 5 05:15:29 PDT 2007
955 --
956 insert_history_auto_rec_QWB(p_plan_id => l_child_plan_id,
957 p_collection_id => p_collection_id,
958 p_occurrence => l_child_occurrence,
959 p_organization_id => p_org_id,
960 p_txn_header_id => p_txn_header_id,
961 p_relationship_type => 1,
962 p_data_entry_mode => 4 ,
963 x_status => auto_hist_proc_stat);
964
965 END LOOP; --for number of rows
966
967 /* Bug 3223081 : Added the following statement to reset the l_count to 1 after all the rows are inserted for one child plan
968 l_count :=1;
969 - akbhatia
970 */
971 l_count :=1;
972 -- i := i + 1;
973 END LOOP; --outer for loop for child plans
974 x_status := 'T';
975 END;
976
977
978
979
980 FUNCTION descendants_exist(p_plan_id NUMBER,
981 p_collection_id NUMBER,
982 p_occurrence NUMBER)
983 RETURN VARCHAR2 IS
984 ---
985 --- This function takes in plan_id, collection_id and occurrence and returns a 'T'
986 --- if it finds any child record for this record. Otherwise it returns 'F'.
987 ---
988
989 --l_exists INTEGER;
990 l_exists VARCHAR2(1);
991
992 CURSOR descendant_cur IS
993 SELECT 'T'
994 FROM qa_pc_results_relationship
995 WHERE parent_occurrence = p_occurrence
996 AND rownum = 1;
997
998
999 BEGIN
1000 l_exists := 'F';
1001 OPEN descendant_cur;
1002 FETCH descendant_cur INTO l_exists;
1003 IF (descendant_cur%NOTFOUND) THEN
1004 l_exists := 'F';
1005 END IF;
1006
1007 CLOSE descendant_cur;
1008 RETURN l_exists;
1009
1010 END;
1011
1012 FUNCTION get_disabled_descendants(p_plan_id NUMBER,
1013 p_collection_id NUMBER,
1014 p_occurrence NUMBER,
1015 --p_enabled NUMBER,
1016 x_plan_ids OUT NOCOPY dbms_sql.number_table,
1017 x_collection_ids OUT NOCOPY dbms_sql.number_table,
1018 x_occurrences OUT NOCOPY dbms_sql.number_table)
1019 RETURN VARCHAR2 IS
1020 ---
1021 --- This function is similar to get_descendants above with one difference
1022 --- it looks for all disabled records .
1023 ---
1024
1025 BEGIN
1026
1027 BEGIN
1028 SELECT child_plan_id, child_collection_id, child_occurrence
1029 BULK COLLECT INTO
1030 x_plan_ids, x_collection_ids, x_occurrences
1031 FROM qa_pc_results_relationship r
1032 WHERE EXISTS (
1033 SELECT 1
1034 FROM qa_results qr
1035 WHERE qr.plan_id = r.child_plan_id AND
1036 qr.collection_id = r.child_collection_id AND
1037 qr.occurrence = r.child_occurrence AND
1038 qr.status = 1 )
1039 START WITH parent_plan_id = p_plan_id AND
1040 parent_collection_id = p_collection_id AND
1041 parent_occurrence = p_occurrence
1042 CONNECT BY PRIOR child_occurrence = parent_occurrence;
1043 EXCEPTION
1044 WHEN NO_DATA_FOUND THEN
1045 RETURN 'F';
1046 END;
1047
1048 IF SQL%FOUND THEN
1049 RETURN 'T';
1050 ELSE
1051 RETURN 'F';
1052 END IF;
1053
1054 END;
1055
1056 PROCEDURE delete_child_rows(p_plan_ids IN dbms_sql.number_table,
1057 p_collection_ids IN dbms_sql.number_table,
1058 p_occurrences IN dbms_sql.number_table,
1059 p_parent_plan_id NUMBER ,
1060 p_parent_collection_id NUMBER ,
1061 p_parent_occurrence NUMBER ,
1062 p_enabled_flag VARCHAR2)
1063
1064 IS
1065 ---
1066 --- The following procedure takes in plan_id, collection id and occurrece and
1067 --- deletes these rows from QA_RESULTS. It also deletes entry for these rows
1068 --- from relationships tables.
1069 ---
1070 --- p_enabled_flag holds 'T' => delete only enabled child records
1071 --- 'F' => delete only disabled child records
1072
1073 i INTEGER ;
1074
1075 BEGIN
1076
1077 i := 0;
1078
1079 -- Gapless Sequence Proj. rponnusa Wed Jul 30 04:52:45 PDT 2003
1080 -- Call the sequence api to capture audit information for the child/grand
1081 -- child record records. Audit info. for toplevel parent is not
1082 -- collected here.
1083
1084 -- capture audit only when enabled child records (status NULL or 2)
1085 -- are deleted
1086 IF p_enabled_flag = 'T' THEN
1087
1088 QA_SEQUENCE_API.audit_sequence_values(
1089 p_plan_ids,
1090 p_collection_ids,
1091 p_occurrences,
1092 p_parent_plan_id,
1093 p_parent_collection_id,
1094 p_parent_occurrence);
1095 END IF;
1096
1097 FORALL i IN p_occurrences.FIRST .. p_occurrences.LAST
1098 DELETE from QA_RESULTS
1099 WHERE plan_id = p_plan_ids(i)
1100 AND collection_id = p_collection_ids(i)
1101 AND occurrence = p_occurrences(i);
1102
1103 FORALL i IN p_occurrences.FIRST .. p_occurrences.LAST
1104 DELETE from QA_PC_RESULTS_RELATIONSHIP
1105 WHERE child_occurrence = p_occurrences(i);
1106 END delete_child_rows;
1107
1108
1109 PROCEDURE enable_fire_for_txn_hdr_id(p_txn_header_id IN NUMBER) IS
1110 flag BOOLEAN ;
1111
1112 BEGIN
1113
1114 IF p_txn_header_id is not null THEN
1115 UPDATE qa_results
1116 SET status = 2
1117 WHERE txn_header_id = p_txn_header_id;
1118
1119 flag := QLTDACTB.DO_ACTIONS(p_txn_header_id, 1, NULL, NULL,
1120 FALSE , FALSE, 'DEFERRED' , 'TXN_HEADER_ID');
1121 END IF;
1122 END;
1123
1124 --
1125 -- bug 5682448
1126 -- New proc to enable the records and fire
1127 -- the actions for all those enabled records
1128 -- ntungare Wed Feb 21 07:34:11 PST 2007
1129 --
1130 PROCEDURE enable_fire_for_coll_id(p_txn_header_id IN NUMBER) IS
1131 flag BOOLEAN ;
1132
1133 Type num_tab_typ is table of number index by binary_integer;
1134
1135 plan_id_tab num_tab_typ;
1136 collection_id_tab num_tab_typ;
1137 occurrence_tab num_tab_typ;
1138
1139 BEGIN
1140 IF p_txn_header_id is not null THEN
1141
1142 -- Updating the rows in the QA_RESULTS which are currently
1143 -- invalid
1144 --
1145 UPDATE qa_results
1146 SET status = 2
1147 WHERE txn_header_id = p_txn_header_id
1148 and status =1
1149 RETURNING plan_id, collection_id, occurrence
1150 BULK COLLECT INTO plan_id_tab, collection_id_tab, occurrence_tab;
1151
1152 -- Looping through all the updated records and firing
1153 -- actions for them
1154 --
1155 For Cntr in 1..plan_id_tab.COUNT
1156 LOOP
1157 -- Calling the do_actions for the plan_id, collection_id,
1158 -- Occurrence combination
1159 --
1160 flag := QLTDACTB.DO_ACTIONS
1161 (X_TXN_HEADER_ID => collection_id_tab(cntr),
1162 X_CONCURRENT => 1,
1163 X_PO_TXN_PROCESSOR_MODE => NULL,
1164 X_GROUP_ID => NULL,
1165 X_BACKGROUND => FALSE ,
1166 X_DEBUG => FALSE,
1167 X_ACTION_TYPE => 'DEFERRED' ,
1168 X_PASSED_ID_NAME => 'COLLECTION_ID',
1169 P_OCCURRENCE => occurrence_tab(cntr),
1170 P_PLAN_ID => plan_id_tab(cntr));
1171 END LOOP;
1172 END IF; --p_txn_header_id is not null
1173 END enable_fire_for_coll_id;
1174
1175
1176 -- Bug 4270911. CU2 SQL Literal fix. TD #18
1177 -- Uses FND_DSQL package for the case of unknown number of binds.
1178 -- srhariha. Fri Apr 15 06:40:15 PDT 2005.
1179
1180 FUNCTION find_parent(p_child_plan_id IN NUMBER,
1181 p_child_collection_id IN NUMBER,
1182 p_child_occurrence IN NUMBER,
1183 x_parent_plan_id OUT NOCOPY NUMBER,
1184 x_parent_collection_id OUT NOCOPY NUMBER,
1185 x_parent_occurrence OUT NOCOPY NUMBER)
1186 RETURN VARCHAR2 IS
1187
1188 --
1189 -- This function intelligently finding out parent plan record when child plan record information
1190 -- is passed. First find out parent_plan_id from qa_pc_plan_relationship. Then findout all
1191 -- element ids with which parent and child plans are related. Take only those elements which have
1192 -- link_flag = 1 in qa_pc_element_relationship table.
1193
1194 -- Find the values of the elements from qa_results for the child plan. Then find the first record
1195 -- for the parent plan which has all the elements (only those related in the qa_pc_element_relation)
1196 -- same value for those of child plan. Return the parent record information.
1197
1198 l_plan_relationship_id NUMBER;
1199 l_parent_plan_id NUMBER;
1200 l_temp_var NUMBER;
1201 l_res_col VARCHAR2(150); -- stores result column name in qa_results
1202 l_res_value VARCHAR2(150); -- stores result column value in qa_results
1203
1204 query_clause VARCHAR2(32000):= NULL;
1205 select_clause VARCHAR2(80) := NULL;
1206 from_clause CONSTANT VARCHAR2(80) := ' FROM QA_RESULTS ';
1207 where_clause VARCHAR2(5000) := NULL;
1208 parent_where_clause VARCHAR2(5000):= NULL;
1209
1210
1211 Type resCurTyp IS REF CURSOR; --define weak REF CURSOR type
1212 res_cur resCurTyp; --define cursor variable
1213
1214 CURSOR plan_cursor(p_child_plan_id NUMBER) IS
1215 SELECT plan_relationship_id,parent_plan_id
1216 FROM qa_pc_plan_relationship
1217 WHERE child_plan_id = p_child_plan_id
1218 AND rownum = 1;
1219
1220 -- Bug 2357067. Modified the element_cursor so that all parent,child columns
1221 -- can be fetched once.
1222
1223 CURSOR element_cursor(p_relationship_id NUMBER) IS
1224 select pe.parent_char_id,
1225 qpc1.result_column_name parent_database_column,
1226 pe.child_char_id,
1227 qpc2.result_column_name child_database_column
1228 from
1229 qa_pc_plan_relationship pr,
1230 qa_pc_element_relationship pe,
1231 qa_plan_chars qpc1,
1232 qa_plan_chars qpc2
1233 where
1234 pr.plan_relationship_id = pe.plan_relationship_id and
1235 pr.parent_plan_id = qpc1.plan_id and
1236 pe.parent_char_id = qpc1.char_id and
1237 pr.child_plan_id = qpc2.plan_id and
1238 pe.child_char_id = qpc2.char_id and
1239 pe.plan_relationship_id = p_relationship_id and
1240 pe.element_relationship_type = 1 and
1241 pe.link_flag = 1;
1242
1243 -- Bug 4270911. CU2 SQL Literal fix.
1244 -- New cursor handler.
1245 cursor_handle NUMBER;
1246 no_of_rows NUMBER;
1247 BEGIN
1248 l_temp_var := -99;
1249 -- Bug 4270911. CU2 SQL Literal fix.
1250 -- Use bind variables.
1251 -- srhariha. Fri Apr 15 06:22:04 PDT 2005.
1252
1253 where_clause := ' WHERE plan_id = :p_child_plan_id' ||
1254 ' AND collection_id = :p_child_collection_id' ||
1255 ' AND occurrence = :p_child_occurrence';
1256
1257 -- get the parent_plan_id for the child plan
1258 OPEN plan_cursor(p_child_plan_id);
1259 FETCH plan_cursor INTO l_plan_relationship_id,l_parent_plan_id;
1260 IF (plan_cursor%NOTFOUND) THEN
1261 CLOSE plan_cursor;
1262 RETURN 'F';
1263 END IF;
1264
1265 CLOSE plan_cursor;
1266
1267 -- Bug 4270911. CU2 SQL Literal fix.
1268 -- Use fnd_dsql package.
1269 -- srhariha. Fri Apr 15 06:22:04 PDT 2005.
1270
1271 select_clause := ' SELECT 1, plan_id, collection_id, occurrence ';
1272 fnd_dsql.init;
1273 fnd_dsql.add_text(select_clause || from_clause || ' ');
1274 fnd_dsql.add_text(' WHERE plan_id =');
1275 fnd_dsql.add_bind(l_parent_plan_id);
1276 fnd_dsql.add_text(' ');
1277
1278 -- parent_where_clause := ' WHERE plan_id = ' || parent_plan_id ;
1279
1280 -- get all the child plan elements which has relationship
1281 -- and link_flag = 1. This flag is specifically used for flow workstation integration.
1282
1283 FOR ele_rec IN element_cursor(l_plan_relationship_id) LOOP
1284
1285 select_clause := ' SELECT ' || ele_rec.child_database_column;
1286 query_clause := select_clause || from_clause || where_clause;
1287
1288 -- Bug 4270911. CU2 SQL Literal fix.
1289 -- Use bind variables.
1290 -- srhariha. Fri Apr 15 06:22:04 PDT 2005.
1291
1292
1293 OPEN res_cur FOR query_clause USING p_child_plan_id, p_child_collection_id, p_child_occurrence;
1294 FETCH res_cur INTO l_res_value;
1295 CLOSE res_cur;
1296
1297 -- If the copy element in child record is null, then build the query accordingly
1298
1299 IF l_res_value IS NULL THEN
1300 --parent_where_clause := parent_where_clause || ' AND ' ||
1301 -- ele_rec.parent_database_column || ' IS NULL';
1302 fnd_dsql.add_text(' AND ' || ele_rec.parent_database_column || ' IS NULL ');
1303 ELSE
1304 /* rkaza 06/04/2002. Bug 2302554. Enclosing l_res_value with single quotes. */
1305 -- parent_where_clause := parent_where_clause || ' AND ' ||
1306 -- ele_rec.parent_database_column || ' = ' || '''' || qa_core_pkg.dequote(l_res_value) || '''';
1307
1308 fnd_dsql.add_text(' AND ' || ele_rec.parent_database_column || ' = ');
1309 fnd_dsql.add_bind(l_res_value);
1310 fnd_dsql.add_text(' ');
1311 END IF;
1312
1313 END LOOP;
1314
1315 --Necessary to say rownum=1 to avoid multiple rows
1316 -- parent_where_clause := parent_where_clause || ' AND ROWNUM = 1 ';
1317 fnd_dsql.add_text(' AND ROWNUM = 1 ');
1318
1319 -- query_clause := select_clause || from_clause || parent_where_clause;
1320
1321 -- OPEN res_cur FOR query_clause USING l_parent_plan_id;
1322 -- FETCH res_cur INTO l_temp_var, x_parent_plan_id,
1323 -- x_parent_collection_id, x_parent_occurrence;
1324 -- CLOSE res_cur;
1325
1326
1327 cursor_handle := dbms_sql.open_cursor;
1328 fnd_dsql.set_cursor(cursor_handle);
1329
1330 query_clause := fnd_dsql.get_text;
1331 dbms_sql.parse(cursor_handle,query_clause,dbms_sql.NATIVE);
1332 fnd_dsql.do_binds;
1333
1334 dbms_sql.define_column(cursor_handle,1,l_temp_var);
1335 dbms_sql.define_column(cursor_handle,2,x_parent_plan_id);
1336 dbms_sql.define_column(cursor_handle,3,x_parent_collection_id);
1337 dbms_sql.define_column(cursor_handle,4,x_parent_occurrence);
1338
1339 no_of_rows := dbms_sql.execute(cursor_handle);
1340
1341 no_of_rows := dbms_sql.fetch_rows(cursor_handle);
1342
1343 l_temp_var := 0;
1344 IF (no_of_rows > 0) THEN
1345 dbms_sql.column_value(cursor_handle,1,l_temp_var);
1346 dbms_sql.column_value(cursor_handle,2,x_parent_plan_id);
1347 dbms_sql.column_value(cursor_handle,3,x_parent_collection_id);
1348 dbms_sql.column_value(cursor_handle,4,x_parent_occurrence);
1349
1350
1351 END IF;
1352
1353 dbms_sql.close_cursor(cursor_handle);
1354
1355 IF (l_temp_var = 1) THEN
1356 RETURN 'T';
1357 ELSE
1358 RETURN 'F';
1359 END IF;
1360
1361 END find_parent;
1362
1363 -- 12. QWB Usability Improvements
1364 -- added 2 new prameters to return a comma separated list
1365 -- of Parent plan elements for which the aggregation is done
1366 -- and the list of the aggregated values
1367 --
1368 --
1369 -- bug 7046071
1370 -- Added the parameter p_ssqr_operation parameter to check if the
1371 -- call is done from the OAF application or from Forms
1372 -- In case of the OAF application, the COMMIT that is
1373 -- executed in the aggregate_parent must not be called
1374 -- ntungare
1375 --
1376 PROCEDURE relate(p_parent_plan_id IN NUMBER,
1377 p_parent_collection_id IN NUMBER,
1378 p_parent_occurrence IN NUMBER,
1379 p_child_plan_id IN NUMBER,
1380 p_child_collection_id IN NUMBER,
1381 p_child_occurrence IN NUMBER,
1382 p_child_txn_header_id IN NUMBER,
1383 x_agg_elements OUT NOCOPY VARCHAR2,
1384 x_agg_val OUT NOCOPY VARCHAR2,
1385 p_ssqr_operation IN NUMBER DEFAULT NULL) IS
1386
1387 l_date DATE;
1388 l_user_id NUMBER;
1389 l_login_id NUMBER;
1390 l_rowid VARCHAR2(18) := null;
1391
1392 l_ret_value VARCHAR2(1);
1393 -- Gapless Sequence Proj. rponnusa Wed Jul 30 04:52:45 PDT 2003
1394 -- Added following cursor.
1395
1396 l_child_txn_header_id NUMBER;
1397
1398 CURSOR c IS
1399 SELECT txn_header_id FROM qa_results
1400 WHERE plan_id = p_child_plan_id AND
1401 collection_id = p_child_collection_id AND
1402 occurrence = p_child_occurrence;
1403
1404 -- 12.1 QWB Usability Improvements
1405 --
1406 agg_elements VARCHAR2(4000);
1407 agg_val VARCHAR2(4000);
1408 BEGIN
1409
1410 --anagarwa Fri Jun 11 15:08:03 PDT 2004
1411 -- bug 3678910
1412 -- If parent or child key is invalid then no need to create a relationship
1413 IF p_parent_occurrence < 0 OR p_parent_collection_id < 0 OR
1414 p_parent_plan_id < 0 OR p_child_plan_id < 0 OR
1415 p_child_collection_id < 0 OR p_child_occurrence < 0 THEN
1416
1417 RETURN;
1418 END IF;
1419
1420 l_user_id := fnd_global.user_id;
1421 l_login_id := fnd_global.login_id;
1422 l_date := sysdate;
1423
1424 -- Gapless Sequence Proj. rponnusa Wed Jul 30 04:52:45 PDT 2003
1425 -- Findout txn header ID for the child record
1426
1427 IF p_child_txn_header_id IS NULL THEN
1428 OPEN c;
1429 FETCH c INTO l_child_txn_header_id;
1430 CLOSE c;
1431 ELSE
1432 l_child_txn_header_id := p_child_txn_header_id;
1433 END IF;
1434
1435 -- Gapless Sequence Proj passing child_txn_header_id
1436 QA_PC_RESULTS_REL_PKG.Insert_Row(
1437 X_Rowid => l_rowid,
1438 X_Parent_Plan_Id => p_parent_plan_id,
1439 X_Parent_Collection_Id => p_parent_collection_id,
1440 X_Parent_Occurrence => p_parent_occurrence,
1441 X_Child_Plan_Id => p_child_plan_id,
1442 X_Child_Collection_Id => p_child_collection_id,
1443 X_Child_Occurrence => p_child_occurrence,
1444 X_Enabled_Flag => 1,
1445 X_Last_Update_Date => l_date,
1446 X_Last_Updated_By => l_user_id,
1447 X_Creation_Date => l_date,
1448 X_Created_By => l_user_id,
1449 X_Last_Update_Login => l_login_id,
1450 X_Child_Txn_Header_Id => l_child_txn_header_id);
1451
1452 -- Bug 2302554
1453 -- once the parent and child are related, parent record
1454 -- should be updated with child element values(if any aggregate
1455 -- relationship defined) and child record should be updated
1456 -- with parent plan values (if copy relation defined with
1457 -- link_flag = 2)
1458 -- 12.1 QWB Usabiltity improvements
1459 -- added 2 new parameters to get the parent element which
1460 -- is to have the aggregated value and to get the aggregated
1461 -- value
1462 --
1463 --
1464 -- bug 7046071
1465 -- Passing the parameter p_ssqr_operation parameter to check if the
1466 -- call is done from the OAF application or from Forms
1467 -- In case of the OAF application, the COMMIT that is
1468 -- executed in the aggregate_parent must not be called
1469 -- ntungare
1470 --
1471 l_ret_value := QA_PARENT_CHILD_PKG.update_parent(p_parent_plan_id ,
1472 p_parent_collection_id ,
1473 p_parent_occurrence,
1474 p_child_plan_id,
1475 p_child_collection_id ,
1476 p_child_occurrence,
1477 agg_elements,
1478 agg_val,
1479 p_ssqr_operation);
1480
1481 -- 12.1 QWB Usability Improvements
1482 --
1483 x_agg_elements := agg_elements;
1484 x_agg_val := agg_val;
1485
1486 l_ret_value:= QA_PARENT_CHILD_PKG.update_child(p_parent_plan_id ,
1487 p_parent_collection_id ,
1488 p_parent_occurrence,
1489 p_child_plan_id,
1490 p_child_collection_id ,
1491 p_child_occurrence );
1492
1493 END relate;
1494
1495 FUNCTION get_plan_name(p_plan_ids IN VARCHAR2 , x_plan_name OUT NOCOPY VARCHAR2) return VARCHAR2 IS
1496
1497 -- This functions returns the name of the plan when plan_id is passed.
1498 -- This can take the plan_id in the comma separated string like '501,502,503'
1499 -- and returns all the plan_name in the comma separated string.
1500
1501 -- This function is useful when we need to display the message to user about the
1502 -- childplan name or parent plan name.
1503
1504 l_child_id_array ChildPlanArray;
1505 l_total_length NUMBER;
1506 l_plan_name VARCHAR2(10000) := NULL;
1507 l_name VARCHAR2(30);
1508 l_plan_id NUMBER;
1509 l_str_from NUMBER := 1;
1510 l_str_to NUMBER;
1511 l_separator CONSTANT VARCHAR2(1) := ',';
1512
1513 CURSOR plan_cursor(c_plan_id NUMBER) IS
1514 SELECT name
1515 FROM qa_plans
1516 WHERE plan_id = c_plan_id;
1517
1518 BEGIN
1519 l_total_length := LENGTH(p_plan_ids);
1520
1521 -- We need check for all the child_plan_ids one by one or parent_plan_id to
1522 -- to get plan name
1523
1524 -- anagarwa Mon Apr 15 15:51:58 PDT 2002
1525 -- Bug 2320896 was being caused due to error in logic.
1526 -- This code is being replaced to avoid character to number conversion
1527
1528 /*
1529
1530 LOOP
1531 l_str_to := instr(p_plan_ids,l_separator,l_str_from);
1532 IF (l_str_to = 0) THEN
1533 -- we are here if only one plan id is passed or we are in the
1534 -- last child plan id
1535
1536 l_plan_id := to_number(substr(p_plan_ids, l_str_from, l_total_length));
1537 ELSE
1538 l_plan_id := to_number(substr(p_plan_ids, l_str_from, l_str_to -1 ));
1539
1540 -- Adding +1 with the l_str_to to make l_str_from variable pointing to first
1541 -- character after the comma separator
1542
1543 l_str_from := l_str_to +1;
1544 END IF;
1545
1546 OPEN plan_cursor;
1547 FETCH plan_cursor INTO l_name;
1548 IF (plan_cursor%NOTFOUND) THEN
1549 CLOSE plan_cursor;
1550 RETURN 'F';
1551 END IF;
1552
1553 IF l_plan_name IS NULL THEN
1554 l_plan_name := l_name;
1555 ELSE
1556 l_plan_name := l_plan_name || l_separator || l_name;
1557 END IF;
1558 CLOSE plan_cursor;
1559
1560 IF (l_str_to = 0 ) THEN
1561 -- We parsed all the child plan ids.
1562 EXIT;
1563 END IF;
1564 END LOOP;
1565 */
1566
1567 parse_list(p_plan_ids, l_child_id_array);
1568
1569 FOR i IN 1..l_child_id_array.COUNT LOOP
1570 l_plan_id := l_child_id_array(i);
1571 OPEN plan_cursor(l_plan_id);
1572 FETCH plan_cursor INTO l_name;
1573 IF (plan_cursor%NOTFOUND) THEN
1574 CLOSE plan_cursor;
1575 RETURN 'F';
1576 END IF;
1577
1578 IF l_plan_name IS NULL THEN
1579 l_plan_name := l_name;
1580 ELSE
1581 l_plan_name := l_plan_name || l_separator || l_name;
1582 END IF;
1583 CLOSE plan_cursor;
1584
1585 END LOOP;
1586 x_plan_name := l_plan_name;
1587
1588 RETURN 'T';
1589 END get_plan_name;
1590
1591 FUNCTION should_parent_spec_be_copied(p_parent_plan_id NUMBER, p_child_plan_id NUMBER)
1592 RETURN VARCHAR2 IS
1593
1594 -- This function returns true if parent plan specification_id can be copied to child
1595 -- else return false.
1596
1597 l_default_parent NUMBER := -99;
1598
1599 CURSOR default_cursor IS
1600 SELECT default_parent_spec
1601 FROM qa_pc_plan_relationship
1602 WHERE parent_plan_id = p_parent_plan_id
1603 AND child_plan_id = p_child_plan_id;
1604
1605
1606 BEGIN
1607
1608 -- As of now just return true. To implement this function we should have a new field
1609 -- default_parent_spec column in table qa_pc_plan_relationship.
1610 -- Hence i am commenting out the actual implementation of this function.
1611
1612 -- RETURN 'T';
1613
1614 OPEN default_cursor;
1615 FETCH default_cursor INTO l_default_parent;
1616 IF (default_cursor%NOTFOUND) THEN
1617 l_default_parent := -99;
1618 END IF;
1619 CLOSE default_cursor;
1620 IF l_default_parent = 1 THEN
1621 RETURN 'T';
1622 ELSE
1623 RETURN 'F';
1624 END IF;
1625
1626 END should_parent_spec_be_copied;
1627
1628 FUNCTION is_parent_child_plan(p_plan_id NUMBER) RETURN VARCHAR2 IS
1629 -- this functions return 'T' if the plan is parent-child relationship
1630 -- plan. ie pc relationship is defined for this plan.
1631
1632 l_is_parent_plan VARCHAR2(1);
1633
1634 CURSOR plan_cursor(p_plan_id NUMBER) IS
1635 SELECT 'T'
1636 FROM qa_pc_plan_relationship
1637 WHERE parent_plan_id = p_plan_id
1638 OR child_plan_id = p_plan_id
1639 AND rownum = 1;
1640 BEGIN
1641 l_is_parent_plan := 'F';
1642 OPEN plan_cursor(p_plan_id);
1643 FETCH plan_cursor INTO l_is_parent_plan;
1644 IF( plan_cursor%NOTFOUND) THEN
1645 l_is_parent_plan := 'F';
1646 END IF;
1647 CLOSE plan_cursor;
1648 RETURN l_is_parent_plan;
1649 END is_parent_child_plan;
1650
1651 -- Bug 4343758
1652 -- R12 OAF Txn Integration Project
1653 -- Added p_commit parameter to the existing update_parent function
1654 -- and renamed it as aggregate_parent since we do not want
1655 -- the explicit commit for OAF Txn Delete Flows
1656 -- shkalyan 05/13/2005.
1657 --
1658 -- 12.1 QWB Usability Improvements
1659 -- added 2 new parameters to get the list of the
1660 -- aggregated elements and the aggregated values.
1661 --
1662 FUNCTION aggregate_parent(p_parent_plan_id IN NUMBER,
1663 p_parent_collection_id IN NUMBER,
1664 p_parent_occurrence IN NUMBER,
1665 p_child_plan_id IN NUMBER,
1666 p_child_collection_id IN NUMBER,
1667 p_child_occurrence IN NUMBER,
1668 p_commit IN VARCHAR2,
1669 x_agg_elements OUT NOCOPY VARCHAR2,
1670 x_agg_val OUT NOCOPY VARCHAR2)
1671 RETURN VARCHAR2 IS
1672
1673 l_sql_string VARCHAR2(32000);
1674 l_update_parent_sql VARCHAR2(32000);
1675 l_value NUMBER;
1676
1677 --
1678 -- Bug 6450756
1679 -- Declaration of variables needed for
1680 -- locking the row that needs to be
1681 -- updated with the aggregating values.
1682 -- bhsankar Sun Sep 30 23:38:58 PDT 2007
1683 --
1684 l_parent_db_col VARCHAR2(30);
1685 l_select_sql VARCHAR2(32000);
1686
1687 -- anagarwa Mon Dec 16 16:55:09 PST 2002
1688 -- Bug 2701777
1689 -- added parent_enabled_flag and child_enabled_flag to where clause
1690 -- to limit working on onlly those elements that are enabled.
1691 CURSOR element_cursor IS
1692 SELECT parent_database_column,
1693 child_database_column,
1694 element_relationship_type,
1695 parent_char_id
1696 FROM qa_pc_result_columns_v
1697 WHERE parent_plan_id = p_parent_plan_id
1698 AND child_plan_id = p_child_plan_id
1699 AND element_relationship_type in (2,3,4,5,6,7,8)
1700 AND parent_enabled_flag = 1
1701 AND child_enabled_flag = 1;
1702
1703 --
1704 -- Bug 6450756
1705 -- User Defined exception for handling row locks
1706 -- in scenarios U->V->U or U->V->E
1707 -- where aggegating into top most parent will
1708 -- result in a lock.
1709 -- bhsankar Sun Sep 30 23:38:58 PDT 2007
1710 --
1711 ROW_LOCK_FAILED EXCEPTION;
1712 PRAGMA EXCEPTION_INIT(ROW_LOCK_FAILED, -54);
1713
1714
1715 BEGIN
1716
1717 FOR cur_rec IN element_cursor LOOP
1718
1719 -- build the required sql string
1720
1721 l_sql_string := 'FROM qa_results qr, qa_pc_results_relationship pc'
1722 || ' WHERE qr.plan_id=pc.child_plan_id'
1723 || ' AND qr.collection_id=pc.child_collection_id'
1724 || ' AND qr.occurrence=pc.child_occurrence'
1725 || ' AND pc.parent_occurrence= :p_parent_occurrence'
1726 || ' AND pc.child_plan_id= :p_child_plan_id'
1727 --
1728 -- bug 5682448
1729 -- Added the extra condititon to aggregate only the
1730 -- enabled records in stauts 2 or NULL
1731 -- ntungare Wed Feb 21 07:38:04 PST 2007
1732 --
1733 || ' AND (qr.status = 2 OR qr.status IS NULL)';
1734
1735 -- Bug 2427337. Fix here is not related this bug. To use aggregate functions
1736 -- on a element which is stored in character col in qa_results table, we need
1737 -- to use to_number function, or else, unwanted value will be returned.
1738 -- rponnusa Tue Jun 25 06:15:48 PDT 2002
1739
1740 IF (cur_rec.element_relationship_type = 2 ) THEN -- sum
1741 l_sql_string := 'SELECT SUM(to_number(qr.'||cur_rec.child_database_column||')) ' || l_sql_string;
1742 ELSIF (cur_rec.element_relationship_type = 3 ) THEN -- average or Mean
1743 l_sql_string := 'SELECT AVG(to_number(qr.'||cur_rec.child_database_column||')) ' || l_sql_string;
1744 ELSIF (cur_rec.element_relationship_type = 4 ) THEN -- std. deviation
1745 l_sql_string := 'SELECT STDDEV(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
1746
1747 ELSIF (cur_rec.element_relationship_type = 5 ) THEN -- min
1748 l_sql_string := 'SELECT MIN(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
1749 ELSIF (cur_rec.element_relationship_type = 6 ) THEN -- max
1750 l_sql_string := 'SELECT MAX(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
1751 ELSIF (cur_rec.element_relationship_type = 7 ) THEN -- variance
1752 l_sql_string := 'SELECT VARIANCE(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
1753 ELSIF (cur_rec.element_relationship_type = 8 ) THEN -- count
1754 -- anagarwa Tue Feb 18 11:13:20 PST 2003
1755 -- Bug 2789847
1756 -- Count may be done on non numeric elements like Sequence Numbers and
1757 -- even Nonconformance Status, Source etc.
1758 -- A to_number will cause an exception in such a case and is hence
1759 -- removed from sql statement.
1760 l_sql_string := 'SELECT COUNT(qr.'|| cur_rec.child_database_column||') ' || l_sql_string;
1761 END IF;
1762 -- find out the aggregate value for the element in child plan.
1763 BEGIN
1764 EXECUTE IMMEDIATE l_sql_string INTO l_value
1765 USING p_parent_occurrence,p_child_plan_id;
1766 EXCEPTION
1767 WHEN OTHERS THEN raise;
1768
1769 END;
1770
1771 -- Bug 2716973
1772 -- When the child aggregate relationship element value is updated to parent record,
1773 -- Post-Forms-Commit Trigger error raised if child element contain null value.
1774 -- rponnusa Sun Jan 12 23:59:07 PST 2003
1775
1776 l_value := NVL(l_value,0);
1777
1778 -- See 2624112
1779 -- The maximum allowed precision is now expanded to 12.
1780 -- Rounding to 12...
1781 -- rkunchal Thu Oct 17 22:51:45 PDT 2002
1782
1783 -- rounding off to 6 digits is required since, for a number field, the maximum allowd
1784 -- decimal places is 6.
1785
1786 -- l_value := round(l_value,6);
1787 l_value := round(l_value,12);
1788 --
1789 -- Bug 6450756
1790 -- Lock the row in the parent so that the
1791 -- values can be aggregated from the child
1792 -- If the row is not getting locked, then
1793 -- it might be because of the following flow
1794 -- U->V->U or U->V->E. Catch the exception and
1795 -- dont take any action since the aggregations
1796 -- would anyway fire at the parent level.
1797 -- bhsankar Sun Sep 30 23:38:58 PDT 2007
1798 --
1799 l_select_sql := 'SELECT '
1800 || cur_rec.parent_database_column
1801 || ' FROM qa_results WHERE plan_id = :p_parent_plan_id'
1802 || ' AND collection_id= :p_parent_collection_id'
1803 || ' AND occurrence= :p_parent_occurrence FOR UPDATE NOWAIT';
1804
1805 BEGIN
1806 EXECUTE IMMEDIATE l_select_sql INTO l_parent_db_col
1807 USING p_parent_plan_id,p_parent_collection_id,p_parent_occurrence;
1808
1809 -- now we need to update the parent record. Build the sql here.
1810
1811 l_update_parent_sql := 'UPDATE qa_results SET '
1812 || cur_rec.parent_database_column || ' = :l_value'
1813 || ' WHERE plan_id= :p_parent_plan_id'
1814 || ' AND collection_id= :p_parent_collection_id'
1815 || ' AND occurrence= :p_parent_occurrence';
1816 BEGIN
1817 EXECUTE IMMEDIATE l_update_parent_sql
1818 USING l_value,p_parent_plan_id,p_parent_collection_id,p_parent_occurrence;
1819
1820 -- 12.1 QWB Usability improvements
1821 -- Building a list of the Aggregated parent plan elements
1822 --
1823 x_agg_elements := x_agg_elements ||','||
1824 qa_ak_mapping_api.get_vo_attribute_name(cur_rec.parent_char_id, p_parent_plan_id);
1825 -- 12.1 QWB Usability improvements
1826 -- Building a list of the Aggregated values
1827 --
1828 x_agg_val := x_agg_val ||','|| l_value;
1829
1830 EXCEPTION
1831 WHEN OTHERS THEN raise;
1832 END;
1833
1834 EXCEPTION
1835 WHEN ROW_LOCK_FAILED THEN NULL;
1836 WHEN OTHERS THEN RAISE;
1837 END;
1838
1839 END LOOP;
1840 -- we are returning true when the parent record is updated or
1841 -- there is no aggregate relationship defined for the parent,child plans.
1842
1843 -- Bug 4343758
1844 -- R12 OAF Txn Integration Project
1845 -- Added check based on p_commit parameter since we do not want to commit
1846 -- by default if invoked from OAF Pages.
1847 -- shkalyan 05/13/2005.
1848 IF ( p_commit = 'T' ) THEN
1849 -- Bug 2300962. Needs explicit commit, if called from post-database-commit trigger
1850 COMMIT;
1851 END IF;
1852
1853 RETURN 'T';
1854
1855 END aggregate_parent;
1856
1857 FUNCTION update_parent(p_parent_plan_id IN NUMBER,
1858 p_parent_collection_id IN NUMBER,
1859 p_parent_occurrence IN NUMBER,
1860 p_child_plan_id IN NUMBER,
1861 p_child_collection_id IN NUMBER,
1862 p_child_occurrence IN NUMBER)
1863 RETURN VARCHAR2 IS
1864
1865 -- 12.1 QWB Usability Improvements
1866 agg_elements VARCHAR2(4000);
1867 agg_val VARCHAR2(4000);
1868 BEGIN
1869 -- 12.1 QWB Usability Improvements
1870 return update_parent(p_parent_plan_id,
1871 p_parent_collection_id,
1872 p_parent_occurrence,
1873 p_child_plan_id,
1874 p_child_collection_id,
1875 p_child_occurrence,
1876 agg_elements,
1877 agg_val);
1878 END;
1879
1880 -- 12.1 QWB Usability Improvements
1881 -- Overloaded method that has 2 additional parameters
1882 -- that return a list of Aggregated elements and
1883 -- their values
1884 --
1885 -- bug 7046071
1886 -- Passing the parameter p_ssqr_operation parameter to check if the
1887 -- call is done from the OAF application or from Forms
1888 -- In case of the OAF application, the COMMIT that is
1889 -- executed in the aggregate_parent must not be called
1890 -- ntungare
1891 --
1892 FUNCTION update_parent(p_parent_plan_id IN NUMBER,
1893 p_parent_collection_id IN NUMBER,
1894 p_parent_occurrence IN NUMBER,
1895 p_child_plan_id IN NUMBER,
1896 p_child_collection_id IN NUMBER,
1897 p_child_occurrence IN NUMBER,
1898 x_agg_elements OUT NOCOPY VARCHAR2,
1899 x_agg_val OUT NOCOPY VARCHAR2,
1900 p_ssqr_operation IN NUMBER DEFAULT NULL)
1901 RETURN VARCHAR2 IS
1902 l_return_status VARCHAR2(1);
1903
1904 agg_elements VARCHAR2(4000);
1905 agg_val VARCHAR2(4000);
1906
1907 -- bug 7046071
1908 l_commit VARCHAR2(1) := 'T';
1909 BEGIN
1910 -- Bug 4343758
1911 -- R12 OAF Txn Integration Project
1912 -- Moved the entire code to aggregate_parent function because
1913 -- this function was committing by default. Since we do not want
1914 -- the explicit commit for OAF Txn Delete Flows we have introduced this
1915 -- new procedure which accepts the commit flag as input.
1916
1917 --
1918 -- bug 7046071
1919 -- If this processing is initiated from the OAF application
1920 -- either standalone or through OAF txn then the commit must
1921 -- not be done since this would taken care by the framework
1922 -- so setting the commit flag as 'F'
1923 -- ntungare
1924 --
1925 IF (p_ssqr_operation IN (1,2)) THEN
1926 l_commit := 'F';
1927 END IF;
1928
1929 -- 12.1 QWB Usabitlity Improvements.
1930 -- Passing parameters for the aggregated elements
1931 --
1932 -- bug 7046071
1933 -- Passing the derived value for the commit flag
1934 -- ntungare
1935 --
1936 l_return_status :=
1937 aggregate_parent
1938 (
1939 p_parent_plan_id => p_parent_plan_id,
1940 p_parent_collection_id => p_parent_collection_id,
1941 p_parent_occurrence => p_parent_occurrence,
1942 p_child_plan_id => p_child_plan_id,
1943 p_child_collection_id => p_child_collection_id,
1944 p_child_occurrence => p_child_occurrence,
1945 p_commit => l_commit,
1946 x_agg_elements => agg_elements,
1947 x_agg_val => agg_val
1948 );
1949
1950 x_agg_elements := agg_elements;
1951 x_agg_val := agg_val;
1952
1953 -- Bug 4343758. OA Framework Integration project.
1954 -- Function should return the status back to caller.
1955 -- srhariha. Tue May 24 22:56:13 PDT 2005.
1956 RETURN l_return_status;
1957 END update_parent;
1958
1959 --
1960 -- bug 6266439
1961 -- New procedure to peform the date conversions while
1962 -- selecting and updating the data in the QA_RESULTS
1963 -- table, while peforming a Child record update.
1964 -- ntungare Thu Aug 2 03:32:32 PDT 2007
1965 --
1966 PROCEDURE DATE_SELECT_UPDATE(p_parent_result_column IN VARCHAR2,
1967 p_child_result_column IN VARCHAR2,
1968 p_parent_plan_id IN NUMBER,
1969 p_child_plan_id IN NUMBER,
1970 p_var IN NUMBER,
1971 p_select_column OUT NOCOPY VARCHAR2,
1972 p_update_column OUT NOCOPY VARCHAR2)
1973 IS
1974
1975 -- Cursor to check if the resultcolumn is
1976 -- of the DateTime type and whether its a Hardcoded
1977 -- element
1978 Cursor cur (p_plan_id in NUMBER, p_res_col in VARCHAR2) is
1979 Select 1, qc.hardcoded_column
1980 from qa_plan_chars qpc, qa_chars qc
1981 where qpc.plan_id = p_plan_id
1982 and qpc.char_id = qc.char_id
1983 and qpc.result_column_name = p_res_col
1984 and qc.datatype = 6;
1985
1986 data_found PLS_INTEGER := 0;
1987 hardcoded_column QA_CHARS.HARDCODED_COLUMN%TYPE := NULL;
1988
1989 parent_is_date BOOLEAN := FALSE;
1990 child_is_date BOOLEAN := FALSE;
1991 parent_hardcoded_column BOOLEAN := FALSE;
1992 child_hardcoded_column BOOLEAN := FALSE;
1993 BEGIN
1994 -- Checking if the Parent element is a date element
1995 Open cur (p_parent_plan_id, p_parent_result_column);
1996 Fetch cur into data_found, hardcoded_column;
1997 Close cur;
1998
1999 If data_found =1 Then
2000 parent_is_date := TRUE;
2001 data_found :=0;
2002
2003 -- Checking if the Parent element is a HC date
2004 If hardcoded_column IS NOT NULL THEN
2005 parent_hardcoded_column := TRUE;
2006 hardcoded_column := NULL;
2007 END If;
2008 End If;
2009
2010 -- This processing is to be performed only if the
2011 -- elements are dates. If the parent element is not a date
2012 -- then the child element too won't be of the date type since
2013 -- relationship with any other datatype cannot be established
2014 -- in which case, the processing can be terminated.
2015 --
2016 If parent_is_date <> TRUE THEN
2017 RETURN;
2018 ELSE
2019 -- Checking if the Child element is a date element
2020 Open cur (p_child_plan_id, p_child_result_column);
2021 fetch cur into data_found, hardcoded_column;
2022 Close cur;
2023
2024 If data_found =1 Then
2025 child_is_date := TRUE;
2026 data_found :=0;
2027 -- Checking if the Child element is a HC date
2028 If hardcoded_column IS NOT NULL THEN
2029 child_hardcoded_column := TRUE;
2030 hardcoded_column := NULL;
2031 END If;
2032 End If;
2033
2034
2035 If (parent_is_date) AND (parent_hardcoded_column) THEN
2036 --HC-> HC
2037 If (child_is_date) AND (child_hardcoded_column) THEN
2038 p_select_column := 'to_char('||p_parent_result_column||',''DD-MON-YYYY HH24:MI:SS'') ';
2039 p_update_column := 'to_date(:'||to_char(p_var)||',''DD-MON-YYYY HH24:MI:SS'') ';
2040
2041 --HC-> SC
2042 ELSIF (child_is_date) AND (child_hardcoded_column = FALSE) THEN
2043 p_select_column := 'QLTDATE.date_to_canon_dt('||p_parent_result_column||') ';
2044 p_update_column := ':'||to_char(p_var);
2045 END IF;
2046 ELSIF (parent_is_date) AND (parent_hardcoded_column = FALSE) THEN
2047 --SC-> HC
2048 If (child_is_date) AND (child_hardcoded_column) THEN
2049 p_select_column := p_parent_result_column;
2050 p_update_column := 'qltdate.canon_to_date(:'||to_char(p_var)||') ';
2051
2052 --SC-> SC
2053 ELSIF (child_is_date) AND (child_hardcoded_column = FALSE) THEN
2054 p_select_column := p_parent_result_column;
2055 p_update_column := ':'||to_char(p_var);
2056 END If;
2057 END If;
2058 END If;
2059 END DATE_SELECT_UPDATE;
2060
2061 -- 5114865
2062 -- Function to perform the Updation of the Child
2063 -- Plan Columns those which have been identified
2064 -- as having a Copy Relationship with the corresponding
2065 -- Parent Plans
2066 -- This section of code was earlier a part of
2067 -- update_child Function and was extraced so that
2068 -- it can be used in common by function
2069 -- update_sequence_Child
2070 -- nutngare Wed Mar 8 09:00:46 PST 2006
2071 --
2072 FUNCTION perform_child_update(p_parentchild_element_tab IN QA_PARENT_CHILD_PKG.g_parentchild_elementtab_type,
2073 p_parent_plan_id IN NUMBER,
2074 p_parent_collection_id IN NUMBER,
2075 p_parent_occurrence IN NUMBER,
2076 p_child_plan_id IN NUMBER,
2077 p_child_collection_id IN NUMBER,
2078 p_child_occurrence IN NUMBER)
2079 RETURN VARCHAR2 IS
2080
2081 l_sql_string VARCHAR2(32000) := NULL;
2082 l_update_clause VARCHAR2(32000) := NULL;
2083 -- bug 6266477
2084 -- Increased the width to 32000 from 2000 for l_value
2085 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2086 l_value VARCHAR2(32000);
2087 l_append BOOLEAN := FALSE;
2088 l_comma CONSTANT VARCHAR2(3) := ' , ';
2089
2090
2091 c1 NUMBER;
2092 ignore NUMBER;
2093 l_var NUMBER := 1;
2094 -- bug 6266477
2095 -- Commented the bindTab array since the elementsarray would
2096 -- be used to build the array out of the string of values.
2097 -- l_bind_var would be declared as an object of ElementsArray
2098 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2099 --
2100 -- TYPE bindTab IS TABLE OF l_value%TYPE INDEX BY BINARY_INTEGER;
2101 -- l_bind_var bindTab;
2102 l_bind_var qa_txn_grp.ElementsArray;
2103
2104 --
2105 -- bug 6266439
2106 -- New variable to hold the name of the column
2107 -- to be selected from the QA_RESULTS table
2108 -- ntungare Thu Aug 2 03:40:42 PDT 2007
2109 --
2110 select_column varchar2(2000);
2111
2112 -- New variable to hold the bind variable
2113 -- to be updated in the QA_RESULTS table
2114 update_column varchar2(2000);
2115
2116 BEGIN
2117 For element_cntr in 1..p_parentchild_element_tab.count
2118 LOOP
2119 --
2120 -- Bug 6266477
2121 -- Moved the if block below for better framing.
2122 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2123 --
2124 -- IF(l_append) THEN
2125 -- l_update_clause := l_update_clause || l_comma;
2126 -- END IF;
2127
2128 --
2129 -- bug 6266439
2130 -- If the result column names are not of the sequenceXX or CommentsXX
2131 -- type, then they can be of the HC or SC date Type.
2132 -- So make a call to the new proc to get the appropriate Select
2133 -- and update columns
2134 -- ntungare Thu Aug 2 03:42:18 PDT 2007
2135 --
2136 If ((Substr(UPPER(p_parentchild_element_tab(element_cntr).parent_database_column),1,8) <> 'SEQUENCE') AND
2137 (Substr(UPPER(p_parentchild_element_tab(element_cntr).parent_database_column),1,7) <> 'COMMENT')) THEN
2138
2139 DATE_SELECT_UPDATE(p_parent_result_column => UPPER(p_parentchild_element_tab(element_cntr).parent_database_column),
2140 p_child_result_column => UPPER(p_parentchild_element_tab(element_cntr).child_database_column),
2141 p_parent_plan_id => p_parent_plan_id,
2142 p_child_plan_id => p_child_plan_id,
2143 p_var => l_var,
2144 p_select_column => select_column,
2145 p_update_column => update_column);
2146
2147 End If;
2148 -- bug 6266477
2149 -- Moved if block below for easier framing of
2150 -- the select clause.
2151 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2152 --
2153 IF(l_append) THEN
2154 l_update_clause := l_update_clause || l_comma;
2155 --
2156 -- bug 6266477
2157 -- Added the following to execute the query
2158 -- to fetch all the parent result column values
2159 -- in a single hit to qa_results table
2160 -- The string is built as 1=<result_column_value1>@2=result_column_value2>
2161 -- so that the result_to_array can be reused to collect into an array.
2162 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2163 --
2164 l_sql_string := l_sql_string || ' || ''@';
2165 l_sql_string := l_sql_string || element_cntr || '='' || '
2166 || 'replace(' || NVL(select_column, p_parentchild_element_tab(element_cntr).parent_database_column) || ', ''@'', ''@@'')';
2167 ELSE
2168 l_sql_string := l_sql_string || '''' || element_cntr || '='' || '
2169 || 'replace(' || NVL(select_column, p_parentchild_element_tab(element_cntr).parent_database_column) || ', ''@'', ''@@'')';
2170 END IF;
2171
2172 --
2173 -- bug 6266439
2174 -- Making use of the select columns string
2175 -- ntungare Thu Aug 2 03:42:18 PDT 2007
2176 --
2177 /*
2178 l_sql_string := 'SELECT ' || p_parentchild_element_tab(element_cntr).parent_database_column
2179 || ' FROM qa_results '
2180 || ' WHERE plan_id= :p_parent_plan_id'
2181 || ' AND collection_id= :p_parent_collection_id'
2182 || ' AND occurrence= :p_parent_occurrence';
2183 */
2184 --
2185 -- bug 626477
2186 -- Commented out the execution of the built string,
2187 -- since this query needs to be executed
2188 -- only once to better performance.
2189 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2190 --
2191 /*
2192 l_sql_string := 'SELECT ' || NVL(select_column, p_parentchild_element_tab(element_cntr).parent_database_column)
2193 || ' FROM qa_results '
2194 || ' WHERE plan_id= :p_parent_plan_id'
2195 || ' AND collection_id= :p_parent_collection_id'
2196 || ' AND occurrence= :p_parent_occurrence';
2197
2198 BEGIN
2199 EXECUTE IMMEDIATE l_sql_string INTO l_value
2200 USING p_parent_plan_id,p_parent_collection_id,p_parent_occurrence;
2201 EXCEPTION
2202 WHEN OTHERS THEN RETURN 'F';
2203 END;
2204 */
2205 -- anagarwa Fri May 24 11:09:43 PDT 2002
2206 -- bug 2388986. Though not directly related to this bug, it was found
2207 -- during the analysis/review. If there's a single quote in value then
2208 -- this whole thing will fail. adding dequote prevents such catastrophic
2209 -- scenarios.
2210
2211 -- Bug 2976810. Instead of the literal value concatenation and execution using
2212 -- EXECUTE IMMEDIATE, we'll pack these values into an array, bind them and
2213 -- and execute using DBMS_SQL.execute. kabalakr
2214
2215 -- l_update_clause := l_update_clause || cur_rec.child_database_column ||
2216 -- ' = ' || ''''||qa_core_pkg.dequote(l_value) ||'''';
2217
2218 --
2219 -- bug 6266439
2220 -- Making use of the update columns string
2221 -- ntungare Thu Aug 2 03:45:10 PDT 2007
2222 --
2223 /*
2224 l_update_clause := l_update_clause ||
2225 p_parentchild_element_tab(element_cntr).child_database_column ||
2226 ' = :'||to_char(l_var);
2227 */
2228 l_update_clause := l_update_clause ||
2229 p_parentchild_element_tab(element_cntr).child_database_column ||
2230 ' = '||NVL(update_column, ':'||to_char(l_var));
2231 --
2232 -- bug 6266477
2233 -- Commented the below assignment
2234 -- since it will happen after statement execution
2235 -- outside the loop.
2236 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2237 --
2238 -- l_bind_var(l_var) := l_value;
2239 l_var := l_var + 1;
2240
2241 l_append := TRUE;
2242 END LOOP;
2243
2244 IF( l_update_clause IS NULL) THEN
2245 -- this will happen only if the element_cursor does not fetch any records.
2246 RETURN 'T';
2247 END IF;
2248
2249 --
2250 -- bug 6266477
2251 -- Execute the select statement here to hit the table
2252 -- QA_RESULTS only once to improve performance and get
2253 -- the values into anl_bind_var array.
2254 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2255 --
2256 l_sql_string := 'Select ' || l_sql_string
2257 || ' FROM qa_results '
2258 || ' WHERE plan_id= :p_parent_plan_id'
2259 || ' AND collection_id= :p_parent_collection_id'
2260 || ' AND occurrence= :p_parent_occurrence';
2261 BEGIN
2262 EXECUTE IMMEDIATE l_sql_string INTO l_value
2263 USING p_parent_plan_id,p_parent_collection_id,p_parent_occurrence;
2264 EXCEPTION
2265 WHEN OTHERS THEN RETURN 'F';
2266 END;
2267
2268 l_bind_var := qa_txn_grp.result_to_array(l_value);
2269
2270 l_update_clause := 'UPDATE qa_results SET ' || l_update_clause
2271 || ' WHERE plan_id= :p_child_plan_id'
2272 || ' AND collection_id= :p_child_collection_id'
2273 || ' AND occurrence= :p_child_occurrence';
2274
2275 BEGIN
2276
2277 c1 := dbms_sql.open_cursor;
2278 dbms_sql.parse(c1, l_update_clause, dbms_sql.native);
2279
2280 l_var := l_bind_var.FIRST;
2281
2282 WHILE (l_var IS NOT NULL) LOOP
2283 --
2284 -- bug 6266477
2285 -- Replaced bind statement since, l_bind_val is
2286 -- an object of qa_txn_grp.ElementsArray which
2287 -- will have 2 fields and we are interested
2288 -- only in the value field.
2289 -- skolluku Sun Oct 14 03:26:31 PDT 2007
2290 --
2291 -- dbms_sql.bind_variable(c1, ':' || to_char(l_var), l_bind_var(l_var));
2292 dbms_sql.bind_variable(c1, ':' || to_char(l_var), l_bind_var(l_var).value);
2293 l_var := l_bind_var.NEXT(l_var);
2294 END LOOP;
2295
2296 dbms_sql.bind_variable(c1, ':p_child_plan_id', p_child_plan_id);
2297 dbms_sql.bind_variable(c1, ':p_child_collection_id', p_child_collection_id);
2298 dbms_sql.bind_variable(c1, ':p_child_occurrence', p_child_occurrence);
2299
2300 ignore := dbms_sql.execute(c1);
2301
2302 --bug# 5510747 shkalyan. Added close cursor
2303 dbms_sql.close_cursor(c1);
2304
2305 EXCEPTION
2306 WHEN OTHERS THEN
2307 --
2308 -- Bug 4675642.
2309 -- The cursor c1 was not being closed in case of error during processing the records. Doing
2310 -- that now.
2311 -- ntungare Sun Oct 16 21:38:29 PDT 2005
2312 --
2313 IF dbms_sql.is_open(c1)
2314 THEN
2315 dbms_sql.close_cursor(c1);
2316 END IF;
2317 RETURN 'F';
2318 END;
2319 Return 'T';
2320 END perform_child_update;
2321
2322 FUNCTION update_child(p_parent_plan_id IN NUMBER,
2323 p_parent_collection_id IN NUMBER,
2324 p_parent_occurrence IN NUMBER,
2325 p_child_plan_id IN NUMBER,
2326 p_child_collection_id IN NUMBER,
2327 p_child_occurrence IN NUMBER)
2328 RETURN VARCHAR2 IS
2329
2330 -- the following cursor contains sql text used for the view
2331 -- qa_pc_result_columns_v. I added link_flag in where clause.
2332
2333 -- anagarwa Mon Dec 16 16:55:09 PST 2002
2334 -- Bug 2701777
2335 -- added parent_enabled_flag and child_enabled_flag to where clause
2336 -- to limit working on onlly those elements that are enabled.
2337
2338 CURSOR element_cursor IS
2339 SELECT qprc.parent_database_column,
2340 qprc.child_database_column
2341 FROM
2342 qa_pc_result_columns_v qprc
2343 WHERE
2344 qprc.parent_plan_id = p_parent_plan_id and
2345 qprc.child_plan_id = p_child_plan_id and
2346 qprc.element_relationship_type = 1 and
2347 parent_enabled_flag = 1 and
2348 child_enabled_flag = 1;
2349
2350 -- suramasw.Bug 3561911.
2351
2352 -- The following cursor was added to generate sequence numbers
2353 -- for sequence elements in child plan which donot have copy
2354 -- relation from the parent plan in date entry mode 'Automatic'.
2355
2356 -- The cursor does the following(starting from the inner join)
2357 -- 1.get the child plan collection elements char_id's which have
2358 -- copy relation with the parent plan and when the date entry
2359 -- mode is 'Automatic'.
2360 -- 2.get the child plan collection elements char_ids which are
2361 -- of datatype sequence and which donot belong to the set of
2362 -- values fetched in step 1 mentioned above.
2363 -- 3.get the result_column_name(SEQUENCE1, SEQUENCE2, ......)
2364 -- for the values fetched in step 2 mentioned above.
2365
2366 /* Bug 3678910. Commenting out the changes done for bug 3561911.
2367 Please see the bug for more info. kabalakr.
2368
2369 CURSOR seq_cursor is
2370 SELECT qpc.char_id,
2371 qpc.result_column_name
2372 FROM qa_chars qc,
2373 qa_plan_chars qpc
2374 WHERE qpc.plan_id = p_child_plan_id
2375 AND qpc.char_id NOT IN
2376 (SELECT child_char_id
2377 FROM qa_pc_element_relationship qper,
2378 qa_pc_plan_relationship qppr
2379 WHERE qper.plan_relationship_id = qppr.plan_relationship_id
2380 AND qppr.parent_plan_id = p_parent_plan_id
2381 AND qppr.child_plan_id = p_child_plan_id
2382 AND qppr.data_entry_mode = 2)
2383 AND qpc.char_id = qc.char_id
2384 AND qc.datatype =5;
2385
2386 l_seq VARCHAR2(2000);
2387
2388 */
2389
2390
2391 -- 5114865
2392 -- Collection to hold the PC relationship elements
2393 l_element_cursor_tab QA_PARENT_CHILD_PKG.g_parentchild_elementtab_type;
2394
2395 -- Counter for the PC elements
2396 l_element_cntr PLS_INTEGER := 1;
2397
2398 l_ret_val VARCHAR2(10);
2399
2400 BEGIN
2401 -- Bug 5114865
2402 -- Collecting the child plan elements which are
2403 -- to be updated into a collection that would be
2404 -- passed to perform_child_update to processing
2405 -- ntungare Wed Mar 8 09:04:26 PST 2006
2406 --
2407 FOR cur_rec IN element_cursor LOOP
2408 l_element_cursor_tab(l_element_cntr).parent_database_column:= cur_rec.parent_database_column;
2409 l_element_cursor_tab(l_element_cntr).child_database_column := cur_rec.child_database_column;
2410 l_element_cntr := l_element_cntr + 1;
2411 END LOOP;
2412
2413 -- Bug 5114865
2414 -- Calling the proedure to perform the update
2415 -- ntungare Wed Mar 8 09:04:26 PST 2006
2416 --
2417 l_ret_val := perform_child_update
2418 (p_parentchild_element_tab => l_element_cursor_tab,
2419 p_parent_plan_id => p_parent_plan_id ,
2420 p_parent_collection_id => p_parent_collection_id,
2421 p_parent_occurrence => p_parent_occurrence,
2422 p_child_plan_id => p_child_plan_id ,
2423 p_child_collection_id => p_child_collection_id,
2424 p_child_occurrence => p_child_occurrence);
2425
2426 If l_ret_val = 'F'
2427 THEN RETURN 'F';
2428 END IF;
2429
2430 RETURN 'T';
2431 END update_child;
2432
2433 -- bug 5114865
2434 -- New Function to get a list of all the elements
2435 -- in the Child Plan that get the value from a seq
2436 -- type element in the Parent plan or from a char
2437 -- element having a sequence Ancestor
2438 -- ntungare Wed Mar 22 01:13:53 PST 2006
2439 --
2440 FUNCTION get_seq_rel_elements (p_parent_plan_id IN NUMBER,
2441 p_child_plan_id IN NUMBER,
2442 p_topmostRel_flag IN BOOLEAN,
2443 p_parent_elements_tab IN QA_PARENT_CHILD_PKG.g_parentchild_elementtab_type,
2444 p_elements_tab OUT NOCOPY QA_PARENT_CHILD_PKG.g_parentchild_elementtab_type)
2445
2446 RETURN BOOLEAN AS
2447
2448 l_parent_datatype NUMBER;
2449 l_childdbcolname VARCHAR2(1000);
2450 l_prev_parentdbcolname VARCHAR2(1000);
2451
2452 -- Cursor to fetch the Char elements in the child plan
2453 -- having sequence ancestor but not a direct Seq-char
2454 -- relation
2455 Cursor element_cur(p_parentdbcol VARCHAR2) IS
2456 SELECT qprc.parent_database_column parent_database_column,
2457 qprc.child_database_column child_database_column
2458 FROM
2459 qa_pc_result_columns_v qprc
2460 WHERE
2461 qprc.parent_plan_id = p_parent_plan_id and
2462 qprc.child_plan_id = p_child_plan_id and
2463 qprc.element_relationship_type = 1 and
2464 parent_enabled_flag = 1 and
2465 child_dataType <> 5 and
2466 child_enabled_flag = 1 and
2467 parent_database_column = p_parentdbcol ;
2468
2469 elements_tab_count PLS_INTEGER;
2470 BEGIN
2471 -- Fetching the Sequence to Char Relation Elements
2472 SELECT qprc.parent_database_column parent_database_column,
2473 qprc.child_database_column child_database_column
2474 BULK COLLECT INTO p_elements_tab
2475 FROM
2476 qa_pc_result_columns_v qprc
2477 WHERE
2478 qprc.parent_plan_id = p_parent_plan_id and
2479 qprc.child_plan_id = p_child_plan_id and
2480 qprc.element_relationship_type = 1 and
2481 parent_enabled_flag = 1 and
2482 child_dataType <> 5 and
2483 child_enabled_flag = 1 and
2484 parent_dataType = 5 ;
2485
2486 -- A topmost plan-child combination will only have
2487 -- Seq-Char copy relation. However, further down the
2488 -- hierarchy the copy relationship can be between
2489 -- two char elements, the one on the parent having a
2490 -- Sequence Ancestor. The following section of code
2491 -- fetches these relations
2492 -- ntungare
2493 If p_topmostRel_flag = FALSE THEN
2494 elements_tab_count := NVL(p_elements_tab.LAST,0);
2495
2496 -- Looping through the elements that have been copied onto the
2497 -- Current parent plan, when it was processed as a child, and
2498 -- Checking if any of these have to be futher copied down on to
2499 -- the Current Child plan.
2500 FOR cntr in 1..p_parent_elements_tab.COUNT
2501 LOOP
2502 -- Fetching the values from the Cursor defined above
2503 -- passing the Parent and Child Plan Id and the Parent
2504 -- DB columns and setting the Child DB column where they need
2505 -- to be copied .
2506 FOR elem in element_cur(p_parent_elements_tab(cntr).child_database_column)
2507 LOOP
2508 elements_tab_count := elements_tab_count +1;
2509 p_elements_tab(elements_tab_count).parent_database_column := elem.parent_database_column;
2510 p_elements_tab(elements_tab_count).child_database_column := elem.child_database_column;
2511 END LOOP;
2512 END LOOP;
2513 END IF;
2514
2515 -- Checking if any P-C relations exist
2516 -- If they do then the function return
2517 -- TRUE after wich furhter processing can
2518 -- be done.
2519 IF p_elements_tab.COUNT <> 0 THEN
2520 RETURN TRUE;
2521 ELSE RETURN FALSE;
2522 END IF;
2523 END get_seq_rel_elements;
2524
2525 -- Bug 5114865
2526 -- New Procedure to get a list of the elements that
2527 -- have been copied onto the plan Id passed when it
2528 -- is processed as a child plan.
2529 -- The elements those have been copied at every level
2530 -- are stored in the Collection nested in p_parentchild_Tab
2531 -- ntungare Wed Mar 22 01:14:24 PST 2006
2532 --
2533 PROCEDURE get_parent_elementscopied(p_parentchild_Tab IN QA_PARENT_CHILD_PKG.ParentChildTabTyp,
2534 p_current_plan_id IN NUMBER,
2535 p_parent_elements_tab OUT NOCOPY QA_PARENT_CHILD_PKG.g_parentchild_elementtab_type)
2536 AS
2537 BEGIN
2538 -- Looping through all the P-C relations
2539 -- Till we reach a level where the Plan Id passed
2540 -- has been a child plan
2541 For cntr in 1..p_parentchild_Tab.COUNT
2542 LOOP
2543 If p_current_plan_id = p_parentchild_Tab(cntr).child_plan_id
2544 THEN
2545 -- If the level if found then the elements
2546 -- those have been copied in it when it was a child
2547 -- are returned in a collection.
2548 -- These are the only elements whose values may or
2549 -- maynot have to be propagated further to the
2550 -- subsequent Children, if such a relationship exists
2551 p_parent_elements_tab := p_parentchild_Tab(cntr).parentelement_tab;
2552 EXIT;
2553 END IF;
2554 END LOOP;
2555 END get_parent_elementscopied;
2556
2557
2558 -- Bug 5114865
2559 -- Function to copy the values from the Parent to the Child plans
2560 -- only when the source element in the Parent plan is of the
2561 -- Sequence Type and that in the child is of the Char Type
2562 -- ntungare Wed Mar 22 01:15:26 PST 2006
2563 --
2564 FUNCTION update_sequence_child(p_ParentChild_Tab IN QA_PARENT_CHILD_PKG.ParentChildTabTyp)
2565 RETURN VARCHAR2 IS
2566
2567 Type Num_tab_Typ is table of NUMBER INDEX BY BINARY_INTEGER;
2568 parentCol_DataType_Tab Num_tab_Typ;
2569 parentwithSeq_flag BOOLEAN;
2570
2571 l_ParentChild_Tab QA_PARENT_CHILD_PKG.ParentChildTabTyp;
2572 l_elements_toprocess_tab QA_PARENT_CHILD_PKG.g_parentchild_elementtab_type;
2573 l_parent_elements_tab QA_PARENT_CHILD_PKG.g_parentchild_elementtab_type;
2574
2575 l_ret_val VARCHAR2(10);
2576
2577 l_element_cntr PLS_INTEGER := 1;
2578
2579 l_topmostRel_flag BOOLEAN;
2580 l_topmost_plan_id NUMBER;
2581
2582 BEGIN
2583 l_ParentChild_Tab := p_ParentChild_Tab;
2584 parentwithSeq_flag := FALSE;
2585 l_topmostRel_flag := TRUE;
2586
2587 --Getting the Topmost Plan Id
2588 l_topmost_plan_id := l_ParentChild_Tab(1).parent_plan_id;
2589
2590 -- Looping through the P-C plan combinations to be processed
2591 For cntr in 1..l_ParentChild_Tab.COUNT
2592 LOOP
2593 -- If the current Parent Plan Id is the same as the
2594 -- Topmost plan id then setting the flag accordingly
2595 -- This flag would determine if we need to look at what
2596 -- elements have been copied to the Current Parent plan
2597 -- when it was processed as a child, or not, as it would
2598 -- have no meaning for the Topmost level Plan.
2599 If l_ParentChild_Tab(cntr).parent_plan_id = l_topmost_plan_id
2600 THEN l_topmostRel_flag := TRUE;
2601 ELSE l_topmostRel_flag := FALSE;
2602 END IF;
2603
2604 -- Getting the elements copied to the current Parent Plan
2605 -- during its processing as a child Plan.
2606 -- For the Topmost level plan, this would be of no meaning
2607 IF l_topmostRel_flag = FALSE THEN
2608 get_parent_elementscopied(p_ParentChild_Tab => l_ParentChild_Tab,
2609 p_current_plan_id => l_ParentChild_Tab(cntr).parent_plan_id,
2610 p_parent_elements_tab => l_parent_elements_tab);
2611 END IF;
2612
2613 -- Getting a list of the the elements in the child plan
2614 -- that either get the value from a sequence element in
2615 -- the parent plan or a Char element which is turn may
2616 -- have received the data from a sequence element
2617 --
2618 parentwithSeq_flag := get_seq_rel_elements
2619 (p_parent_plan_id => l_ParentChild_Tab(cntr).parent_plan_id,
2620 p_child_plan_id => l_ParentChild_Tab(cntr).child_plan_id,
2621 p_topmostRel_flag => l_topmostRel_flag,
2622 p_parent_elements_tab => l_parent_elements_tab,
2623 p_elements_tab => l_elements_toprocess_tab);
2624
2625 -- Processing the list of elements obtained from above
2626 -- and captured in l_pc_elementstoprocess_tab
2627 -- The parentwithSeq_flag would be TRUE only if any of
2628 -- the elements of the Child Plan have copy relations
2629 -- with Seq Type elements or with Char elements with Seq
2630 -- Type ancestors, in the parent plan
2631 --
2632 IF parentwithSeq_flag THEN
2633 l_ret_val := perform_child_update
2634 (p_parentchild_element_tab => l_elements_toprocess_tab,
2635 p_parent_plan_id => l_ParentChild_Tab(cntr).parent_plan_id,
2636 p_parent_collection_id => l_ParentChild_Tab(cntr).parent_collection_id,
2637 p_parent_occurrence => l_ParentChild_Tab(cntr).parent_occurrence,
2638 p_child_plan_id => l_ParentChild_Tab(cntr).child_plan_id,
2639 p_child_collection_id => l_ParentChild_Tab(cntr).child_collection_id,
2640 p_child_occurrence => l_ParentChild_Tab(cntr).child_occurrence);
2641
2642 If l_ret_val = 'F'
2643 THEN RETURN 'F';
2644 END IF;
2645
2646 -- Resetting the flag value
2647 parentwithSeq_flag := FALSE;
2648
2649 -- Copying the list of the elements copied to the
2650 -- Child plan into the nested collection in l_ParentChild_Tab
2651 -- as this would be looked up when the Current Child plan is
2652 -- processed as a Parent Plan
2653 --
2654 l_ParentChild_Tab(cntr).parentelement_tab:= l_elements_toprocess_tab;
2655
2656 -- Emptying the elements collection
2657 l_elements_toprocess_tab.DELETE;
2658 END IF;
2659 END LOOP;
2660 RETURN 'T';
2661 END update_sequence_child;
2662
2663 PROCEDURE get_criteria_values(p_parent_plan_id IN NUMBER,
2664 p_parent_collection_id IN NUMBER,
2665 p_parent_occurrence IN NUMBER,
2666 p_organization_id IN NUMBER,
2667 x_criteria_values OUT NOCOPY VARCHAR2) IS
2668
2669
2670 CURSOR parent_cur IS
2671 /*
2672 anagarwa Tue Jul 16 18:36:52 PDT 2002
2673 Bug 2465920 reports that when hardcoded elements have to be copied to
2674 history or automatic plans in collection imports, it (histor/automatic
2675 functionality) fails.
2676 By selecting form_field instead of database_column we can fix it.
2677 However, item, comp_item, locator and comp_locator don't exist in
2678 QA_RESULTS_V. So we add special handling for these later.
2679 */
2680 --SELECT char_id,database_column
2681 SELECT char_id, replace(form_field, 'DISPLAY' , 'CHARACTER') database_column,
2682 datatype
2683 FROM qa_pc_plan_columns_v
2684 WHERE plan_id = p_parent_plan_id;
2685
2686 --
2687 -- bug 6266477
2688 -- Increased the width of the variables
2689 -- l_res_value, select_clause to 32000
2690 -- skolluku Mon Oct 15 02:57:40 PDT 2007
2691 --
2692 l_res_value VARCHAR2(32000);
2693 l_string VARCHAR2(32000);
2694 l_append BOOLEAN;
2695
2696 select_clause VARCHAR2(32000);
2697 from_clause CONSTANT VARCHAR2(80) := ' FROM QA_RESULTS_V ';
2698 where_clause VARCHAR2(5000);
2699 query_clause VARCHAR2(32000);
2700 -- anagarwa Tue Jul 16 18:36:52 PDT 2002
2701 -- Bug 2465920: new variable to handle item, comp_item, locator and
2702 -- comp_locator
2703 column_name VARCHAR2(150);
2704
2705
2706 -- Bug 3776542. Performance issue due to use of literals in the SQL to fetch
2707 -- criteria value from QA_RESULTS_V. Earlier we were using reference cursor to
2708 -- fetch the value with a SQL that had literals. After fix, we are using EXECUTE_IMMEDIATE
2709 -- with SQL containing bind variables. This ref cursor is needed no more, hence commenting
2710 -- it out.Thu Jul 29 02:02:03 PDT 2004.
2711 -- srhariha.
2712
2713 -- Type resCurTyp IS REF CURSOR; --define weak REF CURSOR type
2714 -- res_cur resCurTyp; --define cursor variable
2715
2716 BEGIN
2717
2718 -- Bug 3776542. Performance issue due to use of literals in the SQL. Modified the
2719 -- string to include bind variables.
2720 -- srhariha.Thu Jul 29 02:02:03 PDT 2004.
2721 l_append := FALSE;
2722 where_clause := ' WHERE plan_id = ' || ':p_parent_plan_id' ||
2723 ' AND collection_id = ' ||':p_parent_collection_id' ||
2724 ' AND occurrence = ' || ':p_parent_occurrence';
2725
2726 -- finding out the values for each element of parent record
2727 FOR parent_rec IN parent_cur LOOP
2728 -- anagarwa Tue Jul 16 18:36:52 PDT 2002
2729 -- Bug 2465920: item, comp_item, locator and comp_locator don't exist in
2730 -- QA_REULTS_V so we select id's instead.
2731 column_name := parent_rec.database_column;
2732 IF column_name = 'ITEM' THEN
2733 column_name := 'ITEM_ID';
2734
2735 ELSIF column_name = 'COMP_ITEM' THEN
2736 column_name := 'COMP_ITEM_ID';
2737
2738 ELSIF column_name = 'LOCATOR' THEN
2739 column_name := 'LOCATOR_ID';
2740
2741 ELSIF column_name = 'COMP_LOCATOR' THEN
2742 column_name := 'COMP_LOCATOR_ID';
2743
2744 -- Bug 2694385. Added bill_reference,routing_reference,to_locator since
2745 -- these elements will not present in qa_results_v.
2746 -- rponnusa Wed Dec 18 05:38:40 PST 2002
2747
2748 ELSIF column_name = 'BILL_REFERENCE' THEN
2749 column_name := 'BILL_REFERENCE_ID';
2750
2751 ELSIF column_name = 'ROUTING_REFERENCE' THEN
2752 column_name := 'ROUTING_REFERENCE_ID';
2753
2754 ELSIF column_name = 'TO_LOCATOR' THEN
2755 column_name := 'TO_LOCATOR_ID';
2756
2757 -- Bug 3424886 ksoh Mon Feb 9 13:39:41 PST 2004
2758 -- need to convert hardcoded dates to canonical string
2759 ELSIF (substr(column_name, 1, 9) <> 'CHARACTER') AND
2760 (parent_rec.datatype = qa_ss_const.datetime_datatype) THEN
2761 column_name := 'FND_DATE.DATE_TO_CANONICAL(' || column_name || ')';
2762 END IF;
2763 --
2764 -- bug 6266477
2765 -- Commenting the below code since the handling is done
2766 -- differently to avoid multiple hits to QA_RESULTS_V
2767 -- skolluku Mon Oct 15 02:57:40 PDT 2007
2768 --
2769 /*select_clause := 'SELECT ' || column_name;
2770 query_clause := select_clause || from_clause || where_clause;
2771
2772 -- Bug 3776542. Performance issue due to use of literals in the SQL to fetch
2773 -- criteria value from QA_RESULTS_V. Earlier we were using reference cursor to
2774 -- fetch the value with a SQL that had literals. After fix, we are using EXECUTE_IMMEDIATE
2775 -- with SQL containing bind variables. This ref cursor is needed no more, hence commenting
2776 -- it out.
2777 -- srhariha.Thu Jul 29 02:02:03 PDT 2004
2778
2779 --OPEN res_cur FOR query_clause ;
2780 --FETCH res_cur INTO l_res_value;
2781 --CLOSE res_cur;
2782 EXECUTE IMMEDIATE query_clause
2783 INTO l_res_value
2784 USING p_parent_plan_id,
2785 p_parent_collection_id,
2786 p_parent_occurrence;
2787
2788 IF (l_append) THEN
2789 l_string := l_string || '@';
2790 END IF;
2791 */
2792
2793
2794 -- Bug 2694385. Commented existing IF condition and added following code with
2795 -- bill_reference,routing_reference,to_locator
2796 -- rponnusa Wed Dec 18 05:38:40 PST 2002
2797
2798 /*
2799 IF ((parent_rec.char_id = 10) or parent_rec.char_id = 60) then
2800 l_res_value := qa_flex_util.item(p_organization_id , l_res_value);
2801 ELSIF ((parent_rec.char_id = 15) or (parent_rec.char_id = 65)) then
2802 l_res_value := qa_flex_util.locator(p_organization_id, l_res_value);
2803 END IF;
2804 */
2805 -- Bug 6266477
2806 -- Commented below code.
2807 -- skollluku Mon Oct 15 02:57:40 PDT 2007
2808 /*IF parent_rec.char_id IN (qa_ss_const.item, qa_ss_const.comp_item,
2809 qa_ss_const.routing_reference, qa_ss_const.bill_reference) THEN
2810 l_res_value := qa_flex_util.item(p_organization_id , l_res_value);
2811
2812 ELSIF parent_rec.char_id IN (qa_ss_const.locator, qa_ss_const.comp_locator,
2813 qa_ss_const.to_locator) THEN
2814 l_res_value := qa_flex_util.locator(p_organization_id, l_res_value);
2815 END IF;
2816
2817 -- Bug 2403395
2818 -- If the l_res_value contains '@' character then doubly encode it.
2819 -- rponnusa Wed Jun 5 00:49:14 PDT 2002
2820 l_res_value := replace(l_res_value,'@','@@');
2821
2822 l_string := l_string || parent_rec.char_id || '=' || l_res_value;
2823 */
2824 --
2825 -- bug 6266477
2826 -- Added the below code to enhance performance
2827 -- by hitting the view QA_RESULTS_V just once
2828 -- skolluku Mon Oct 15 02:57:40 PDT 2007
2829 --
2830 IF parent_rec.char_id IN (qa_ss_const.item, qa_ss_const.comp_item,
2831 qa_ss_const.routing_reference, qa_ss_const.bill_reference) THEN
2832 column_name := 'qa_flex_util.item(' || p_organization_id || ', ' || column_name || ')';
2833
2834 ELSIF parent_rec.char_id IN (qa_ss_const.locator, qa_ss_const.comp_locator,
2835 qa_ss_const.to_locator) THEN
2836 column_name := 'qa_flex_util.locator(' || p_organization_id || ', ' || column_name || ')';
2837 END IF;
2838
2839 column_name := 'replace(' || column_name || ', ''@'', ''@@'')';
2840 if (l_append) then
2841 l_string := l_string || ' || ''@';
2842 l_string := l_string || parent_rec.char_id || '='' || ' || column_name;
2843 else
2844 l_string := l_string || '''' || parent_rec.char_id || '='' || ' || column_name;
2845 end if;
2846
2847 l_append := TRUE;
2848
2849 END LOOP;
2850 --
2851 -- bug 6266477
2852 -- Executing the statement outside the loop
2853 -- to improve performance.
2854 -- skolluku Mon Oct 15 02:57:40 PDT 2007
2855 --
2856 select_clause := 'SELECT ' || l_string;
2857 query_clause := select_clause || from_clause || where_clause;
2858 EXECUTE IMMEDIATE query_clause
2859 INTO l_res_value
2860 USING p_parent_plan_id,
2861 p_parent_collection_id,
2862 p_parent_occurrence;
2863 --
2864 -- bug 6266477
2865 -- Modified since l_res_value needs be
2866 -- assigned to x_criteria_values
2867 -- skolluku Mon Oct 15 02:57:40 PDT 2007
2868 --
2869 -- x_criteria_values := l_string;
2870 x_criteria_values := l_res_value;
2871
2872 END get_criteria_values;
2873
2874
2875
2876 PROCEDURE insert_history_auto_rec(p_parent_plan_id IN NUMBER,
2877 p_txn_header_id IN NUMBER,
2878 p_relationship_type IN NUMBER,
2879 p_data_entry_mode IN NUMBER) IS
2880
2881 CURSOR plan_cur IS
2882 SELECT 1
2883 FROM qa_pc_plan_relationship
2884 WHERE parent_plan_id = p_parent_plan_id
2885 AND plan_relationship_type = p_relationship_type
2886 AND data_entry_mode = p_data_entry_mode;
2887
2888 CURSOR res_cur IS
2889 SELECT collection_id,occurrence,organization_id
2890 FROM qa_results
2891 WHERE plan_id = p_parent_plan_id
2892 AND txn_header_id = p_txn_header_id;
2893
2894
2895 l_dummy NUMBER := -99;
2896 l_spec_id NUMBER;
2897 x_status VARCHAR2(1);
2898 l_status VARCHAR2(1);
2899
2900 l_criteria_values VARCHAR2(32000);
2901 l_child_plan_ids VARCHAR2(10000);
2902
2903 -- variables declared for bug 2302539
2904 l_child_txn_header_id NUMBER;
2905 l_fire_action BOOLEAN := FALSE;
2906
2907 BEGIN
2908 IF(QA_PARENT_CHILD_PKG.is_parent_child_plan(p_parent_plan_id ) = 'F') THEN
2909 -- don't do anything
2910 RETURN;
2911 END IF;
2912 OPEN plan_cur;
2913 FETCH plan_cur INTO l_dummy;
2914 CLOSE plan_cur;
2915
2916 IF(l_dummy <> 1) THEN
2917 -- no history or automatic child plans
2918 RETURN;
2919 END IF;
2920
2921 -- Bug 2302539
2922 -- Parent and child records txn_header_id should be different in order to fire
2923 -- actions for the child plans, since action firing for the parent record
2924 -- was taken care in collection import code. We just needs to fire actions
2925 -- for the child records.
2926 -- rponnusa Tue May 28 01:52:47 PDT 2002
2927 FOR c1 in (SELECT mtl_material_transactions_s.nextval txn_header_id FROM DUAL) LOOP
2928
2929 l_child_txn_header_id := c1.txn_header_id;
2930 EXIT;
2931 END LOOP;
2932
2933 FOR import_rec IN res_cur LOOP
2934 get_criteria_values(p_parent_plan_id,
2935 import_rec.collection_id,
2936 import_rec.occurrence,
2937 import_rec.organization_id,
2938 l_criteria_values);
2939 l_status := evaluate_criteria(p_parent_plan_id,
2940 l_criteria_values,
2941 p_relationship_type,
2942 p_data_entry_mode,
2943 l_child_plan_ids);
2944
2945 IF(l_status = 'T') THEN
2946
2947 insert_automatic_records(p_parent_plan_id,
2948 import_rec.collection_id,
2949 import_rec.occurrence,
2950 l_child_plan_ids,
2951 p_relationship_type,
2952 p_data_entry_mode,
2953 l_criteria_values,
2954 import_rec.organization_id,
2955 l_spec_id,
2956 x_status,
2957 l_child_txn_header_id);
2958 l_fire_action := TRUE;
2959 END IF;
2960
2961
2962 END LOOP;
2963
2964 -- Bug 2302539
2965 -- enable and fire actions only if atleast one history/automatic record is inserted.
2966 -- Passing child_txn_header_id to fire actions for the child plans.
2967 -- rponnusa Tue May 28 01:52:47 PDT 2002
2968
2969 IF l_fire_action THEN
2970 enable_fire_for_txn_hdr_id(l_child_txn_header_id);
2971 END IF;
2972
2973 END insert_history_auto_rec;
2974
2975 FUNCTION is_parent_saved(p_plan_id IN NUMBER,
2976 p_collection_id IN NUMBER,
2977 p_occurrence IN NUMBER)
2978 RETURN VARCHAR2 IS
2979
2980 -- Return true if the given parent record is saved in enable status
2981
2982 CURSOR c IS
2983 SELECT 1
2984 FROM qa_results
2985 WHERE plan_id = p_plan_id
2986 AND collection_id = p_collection_id
2987 AND occurrence = p_occurrence
2988 AND status = 2;
2989
2990 l_status NUMBER := -99;
2991 BEGIN
2992 OPEN c;
2993 FETCH c INTO l_status;
2994 CLOSE c;
2995 IF (l_status = 1) THEN
2996 RETURN 'T';
2997 ELSE
2998 RETURN 'F';
2999 END IF;
3000
3001 END is_parent_saved;
3002
3003 FUNCTION update_all_children(p_parent_plan_id IN NUMBER,
3004 p_parent_collection_id IN NUMBER,
3005 p_parent_occurrence IN NUMBER)
3006 RETURN VARCHAR2 IS
3007
3008 l_return_value VARCHAR2(1);
3009 l_dummy VARCHAR2(1);
3010
3011 -- anagarwa Fri May 24 09:57:43 PDT 2002
3012 -- bug 2388986
3013 -- the cursor was incorrect because it was updating all children including
3014 -- history records. this is incorrect as instead of just inserting a new
3015 -- record for history, all previour records are updated with new data.
3016 -- This in turn causes the audit trail to be lost thereby defeating the
3017 -- whole purpose of having history plans!
3018 -- I've added a new join with qa_pc_plan_relationship to ensure this does
3019 -- NOT happen for history plans.
3020 -- IT IS EXTREMELY IMPORTANT TO ENSURE THAT A SINGLE PAIR OF PARENT CHILD
3021 -- PLANS FORM A SINGLE RELATIONSHIP. IF NOT THAT THIS JOIN WILL FAIL !
3022 CURSOR children_cur IS
3023 select qprr.child_plan_id,
3024 qprr.child_collection_id,
3025 qprr.child_occurrence
3026 from qa_pc_results_relationship qprr,
3027 qa_pc_plan_relationship qpr
3028 where qprr.parent_occurrence = p_parent_occurrence
3029 and qprr.parent_plan_id = p_parent_plan_id
3030 and qprr.parent_collection_id = p_parent_collection_id
3031 and qpr.parent_plan_id = qprr.parent_plan_id
3032 and qpr.child_plan_id = qprr.child_plan_id
3033 and qpr.data_entry_mode <> 4;
3034
3035 BEGIN
3036 l_return_value := 'T';
3037 l_dummy := 'T';
3038
3039 FOR children_rec IN children_cur
3040 LOOP
3041 l_return_value :=
3042 update_child ( p_parent_plan_id,
3043 p_parent_collection_id,
3044 p_parent_occurrence,
3045 children_rec.child_plan_id,
3046 children_rec.child_collection_id,
3047 children_rec.child_occurrence);
3048
3049 --check if the fetched child has any children
3050 IF (descendants_exist(children_rec.child_plan_id,
3051 children_rec.child_collection_id,
3052 children_rec.child_occurrence) = 'T')
3053 THEN
3054 --Recursive call
3055 l_dummy :=
3056 update_all_children(children_rec.child_plan_id,
3057 children_rec.child_collection_id,
3058 children_rec.child_occurrence);
3059 END IF;
3060 END LOOP;
3061
3062 RETURN l_return_value;
3063
3064 END update_all_children;
3065
3066
3067 FUNCTION applicable_child_plans_eqr( p_plan_id IN NUMBER ,
3068 p_criteria_values IN VARCHAR2)
3069 RETURN VARCHAR2 IS
3070
3071 ret_flag VARCHAR2(10);
3072 child_plan_list VARCHAR2(1000);
3073
3074 BEGIN
3075
3076 ret_flag := evaluate_child_lov_criteria (p_plan_id, p_criteria_values,
3077 child_plan_list);
3078
3079 RETURN child_plan_list;
3080
3081
3082 END applicable_child_plans_eqr;
3083
3084 FUNCTION applicable_child_plans(p_plan_id IN NUMBER,
3085 p_criteria_values IN VARCHAR2)
3086 RETURN VARCHAR2
3087 IS
3088 --similar to evaluate_child_lov_criteria except no data_entry_mode
3089 -- restriction
3090 CURSOR c IS
3091 SELECT qpr.plan_relationship_id,
3092 qpr.child_plan_id,
3093 qpr.data_entry_mode
3094 FROM qa_plans qp,
3095 qa_pc_plan_relationship qpr
3096 WHERE qpr.parent_plan_id = p_plan_id
3097 AND qpr.child_plan_id = qp.plan_id
3098 AND qpr.plan_relationship_type = 1
3099 AND ((qp.effective_to IS NULL AND TRUNC(SYSDATE) >= qp.effective_from)
3100 OR (qp.effective_from IS NULL AND TRUNC(SYSDATE) <= qp.effective_to)
3101 OR (qp.effective_from IS NOT NULL AND qp.effective_to IS NOT NULL
3102 AND TRUNC(SYSDATE) BETWEEN qp.effective_from AND qp.effective_to)
3103 OR (qp.effective_from IS NULL AND qp.effective_to IS NULL));
3104 l_separator CONSTANT VARCHAR2(1) := '@';
3105 l_subseparator CONSTANT VARCHAR2(1) := '=';
3106 l_child_plan_id NUMBER;
3107 l_data_entry_mode NUMBER;
3108 l_plan_relationship_id NUMBER;
3109 l_childexist BOOLEAN;
3110 l_return_string VARCHAR2(4000);
3111 l_elements qa_txn_grp.ElementsArray;
3112 BEGIN
3113 l_childexist := FALSE;
3114
3115 l_elements := qa_txn_grp.result_to_array(p_criteria_values);
3116 OPEN c;
3117 LOOP
3118 FETCH c INTO l_plan_relationship_id, l_child_plan_id, l_data_entry_mode;
3119 IF (c%NOTFOUND) THEN
3120 EXIT;
3121 END IF;
3122
3123 IF (qa_parent_child_pkg.criteria_matched(l_plan_relationship_id,
3124 l_elements) = 'T') THEN
3125 IF (l_childexist) THEN
3126 l_return_string := l_return_string || l_separator
3127 || l_child_plan_id || l_subseparator
3128 || l_data_entry_mode;
3129 ELSE
3130 l_return_string := l_child_plan_id || l_subseparator
3131 || l_data_entry_mode;
3132 l_childexist := TRUE;
3133 END IF;
3134 END IF;
3135 END LOOP;
3136
3137 CLOSE c;
3138 RETURN l_return_string;
3139 END;
3140
3141
3142
3143 --anagarwa
3144 -- Bug 3195431
3145 -- only copy elements are context elements. So
3146 -- element_relationship type added to the cursor
3147 FUNCTION is_context_element( p_plan_id IN NUMBER ,
3148 p_char_id IN NUMBER,
3149 p_parent_plan_id IN NUMBER,
3150 p_txn_or_child_flag IN NUMBER)
3151 RETURN VARCHAR2 IS
3152
3153 CURSOR c IS SELECT 1
3154 FROM qa_pc_result_columns_v
3155 WHERE child_plan_id = p_plan_id and
3156 child_char_id = p_char_id and
3157 parent_plan_id = p_parent_plan_id and
3158 ELEMENT_RELATIONSHIP_TYPE = 1;
3159
3160
3161 l_context VARCHAR2(1);
3162 ret_val NUMBER;
3163
3164
3165 BEGIN
3166 l_context := 'N';
3167
3168 OPEN c;
3169 FETCH c INTO ret_val;
3170 IF(c%NOTFOUND) THEN
3171 l_context := 'N';
3172 ELSIF ret_val = 1 THEN
3173 l_context := 'Y';
3174 END IF;
3175 CLOSE c;
3176
3177 RETURN l_context;
3178
3179 END is_context_element;
3180
3181
3182
3183 FUNCTION get_parent_vo_attribute_name(p_child_char_id IN NUMBER,
3184 p_plan_id IN NUMBER)
3185 RETURN VARCHAR2 IS
3186
3187 CURSOR c IS SELECT parent_char_id
3188 FROM qa_pc_result_columns_v
3189 WHERE parent_plan_id = p_plan_id and
3190 child_char_id = p_child_char_id and
3191 element_relationship_type = 1;
3192
3193 l_parent_char_id NUMBER;
3194
3195
3196 BEGIN
3197
3198 OPEN c;
3199 FETCH c INTO l_parent_char_id;
3200 IF(c%NOTFOUND) THEN
3201 CLOSE c;
3202 RETURN NULL;
3203 END IF;
3204 CLOSE c;
3205
3206 RETURN qa_ak_mapping_api.get_vo_attribute_name(l_parent_char_id,
3207 p_plan_id);
3208
3209 END get_parent_vo_attribute_name;
3210
3211 FUNCTION get_layout_mode (p_parent_plan_id IN NUMBER,
3212 p_child_plan_id IN NUMBER)
3213 RETURN NUMBER IS
3214 CURSOR c is
3215 SELECT layout_mode
3216 FROM qa_pc_plan_relationship
3217 WHERE parent_plan_id = p_parent_plan_id
3218 AND child_plan_id = p_child_plan_id;
3219
3220 l_layout_mode NUMBER := 0;
3221
3222 BEGIN
3223
3224 OPEN c;
3225 FETCH c INTO l_layout_mode;
3226 IF(c%NOTFOUND) THEN
3227 CLOSE c;
3228 RETURN -1;
3229 END IF;
3230 CLOSE c;
3231 RETURN l_layout_mode;
3232
3233 END get_layout_mode;
3234
3235 FUNCTION ssqr_post_actions(p_txn_hdr_id IN NUMBER,
3236 p_plan_id IN NUMBER,
3237 p_transaction_number IN NUMBER,
3238 x_sequence_string OUT NOCOPY VARCHAR2)
3239 RETURN VARCHAR2 IS
3240
3241 x_status VARCHAR2(10) ;
3242
3243 BEGIN
3244
3245 --initialize the sequence string to empty value
3246 x_sequence_string := '';
3247 x_status := '';
3248
3249 QA_SEQUENCE_API.generate_seq_for_DDE(p_txn_hdr_id, p_plan_id,
3250 x_status, x_sequence_string);
3251
3252
3253 -- generate sequences
3254
3255 -- call enable and fire actions
3256
3257 IF p_transaction_number > 0 THEN
3258 -- do nothing in case of transaction.
3259 RETURN x_status;
3260 ELSE
3261 enable_fire_for_txn_hdr_id(p_txn_hdr_id);
3262 RETURN x_status;
3263 END IF;
3264
3265 END;
3266 FUNCTION count_updated(p_plan_id IN NUMBER,
3267 p_txn_header_id IN NUMBER) RETURN NUMBER IS
3268 ---
3269 --- Bug 3095436: Self Service Quality project
3270 --- Simple function to count the number of rows updated in a plan
3271 --- with a particular txn_header_id
3272 --- Used by the Plan Search VO
3273 ---
3274 cnt NUMBER;
3275
3276 cursor c is
3277 select count(plan_id)
3278 from qa_results
3279 where plan_id = p_plan_id
3280 and txn_header_id = p_txn_header_id;
3281
3282 BEGIN
3283 open c;
3284 fetch c into cnt;
3285 if (c%notfound) then
3286 return 0;
3287 else
3288 return cnt;
3289 end if;
3290 close c;
3291
3292 END count_updated;
3293
3294 FUNCTION get_vud_allowed ( p_plan_id IN NUMBER)
3295 RETURN VARCHAR2 IS
3296 ---
3297 --- Bug 3095436: Self Service Quality project
3298 --- Simple function to tell if the current user has privilege to
3299 --- view, update or delete results in a particular plan
3300 --- Used by the Plan Search VO
3301 ---
3302
3303 BEGIN
3304
3305 IF (qa_web_txn_api.allowed_for_plan('QA_RESULTS_VIEW', p_plan_id) = 'T') or
3306 (qa_web_txn_api.allowed_for_plan('QA_RESULTS_DELETE', p_plan_id) = 'T') or
3307 (qa_web_txn_api.allowed_for_plan('QA_RESULTS_UPDATE', p_plan_id) = 'T') THEN
3308 RETURN 'T';
3309 ELSE
3310 RETURN 'F';
3311 END IF;
3312
3313 END get_vud_allowed;
3314
3315 --12.1 QWB Usaibilty Improvements
3316 -- Overloaded this function so as to cause minimum
3317 -- impact to the existing code
3318 FUNCTION update_parent(p_parent_plan_id IN NUMBER,
3319 p_parent_collection_id IN NUMBER,
3320 p_parent_occurrence IN NUMBER,
3321 p_child_plan_id IN NUMBER,
3322 p_child_collection_id IN NUMBER,
3323 p_child_occurrence IN NUMBER,
3324 p_child_txn_hdr_id IN NUMBER)
3325 RETURN VARCHAR2 IS
3326 agg_elements VARCHAR2(4000);
3327 agg_val VARCHAR2(4000);
3328 BEGIN
3329 return update_parent(
3330 p_parent_plan_id,
3331 p_parent_collection_id,
3332 p_parent_occurrence,
3333 p_child_plan_id,
3334 p_child_collection_id,
3335 p_child_occurrence,
3336 p_child_txn_hdr_id,
3337 agg_elements,
3338 agg_val);
3339 END update_parent;
3340
3341 -- anagarwa Fri Jan 23 12:10:04 PST 2004
3342 -- Bug 3384986 Actions for CAR master not fired when child is updated
3343 -- This is a copy of update_parent above with one extra param, txn_header_id
3344 -- In SSQR when we update the child record, then we call this to update parent
3345 -- and since now we would ike to fire background actions of parent, we update the
3346 -- txn_header_id too.
3347 -- NOTE: I did not modify the existing update_parent but duplicated the code
3348 -- because changing the parameters of existing procedure/function is strongly
3349 -- discouraged per Safe Spec Guide located at
3350 -- http://www-apps.us.oracle.com/%7Epwallack/SafeSpecs.htm
3351
3352 -- Bug 4343758
3353 -- R12 OAF Txn Integration Project
3354 -- Added p_commit parameter since we do not want to commit by default
3355 -- If invoked from OAF Pages.
3356 -- shkalyan 05/13/2005.
3357 FUNCTION update_parent(p_parent_plan_id IN NUMBER,
3358 p_parent_collection_id IN NUMBER,
3359 p_parent_occurrence IN NUMBER,
3360 p_child_plan_id IN NUMBER,
3361 p_child_collection_id IN NUMBER,
3362 p_child_occurrence IN NUMBER,
3363 p_child_txn_hdr_id IN NUMBER,
3364 x_agg_elements OUT NOCOPY VARCHAR2,
3365 x_agg_val OUT NOCOPY VARCHAR2)
3366 RETURN VARCHAR2 IS
3367
3368 l_sql_string VARCHAR2(32000);
3369 l_update_parent_sql VARCHAR2(32000);
3370 l_value NUMBER;
3371
3372 -- anagarwa Mon Dec 16 16:55:09 PST 2002
3373 -- Bug 2701777
3374 -- added parent_enabled_flag and child_enabled_flag to where clause
3375 -- to limit working on onlly those elements that are enabled.
3376 CURSOR element_cursor IS
3377 SELECT parent_database_column,
3378 child_database_column,
3379 element_relationship_type,
3380 parent_char_id
3381 FROM qa_pc_result_columns_v
3382 WHERE parent_plan_id = p_parent_plan_id
3383 AND child_plan_id = p_child_plan_id
3384 AND element_relationship_type in (2,3,4,5,6,7,8)
3385 AND parent_enabled_flag = 1
3386 AND child_enabled_flag = 1;
3387
3388
3389 BEGIN
3390
3391 FOR cur_rec IN element_cursor LOOP
3392
3393 -- build the required sql string
3394
3395 l_sql_string := 'FROM qa_results qr, qa_pc_results_relationship pc'
3396 || ' WHERE qr.plan_id=pc.child_plan_id'
3397 || ' AND qr.collection_id=pc.child_collection_id'
3398 || ' AND qr.occurrence=pc.child_occurrence'
3399 || ' AND pc.parent_occurrence= :p_parent_occurrence'
3400 || ' AND pc.child_plan_id= :p_child_plan_id'
3401 --
3402 -- bug 5682448
3403 -- Added the extra condititon to aggregate only the
3404 -- enabled records in stauts 2 or NULL
3405 -- ntungare Wed Feb 21 07:36:09 PST 2007
3406 --
3407 || ' AND (qr.status = 2 OR qr.status IS NULL)';
3408
3409 -- Bug 2427337. Fix here is not related this bug. To use aggregate functions
3410 -- on a element which is stored in character col in qa_results table, we need
3411 -- to use to_number function, or else, unwanted value will be returned.
3412 -- rponnusa Tue Jun 25 06:15:48 PDT 2002
3413
3414 IF (cur_rec.element_relationship_type = 2 ) THEN -- sum
3415 l_sql_string := 'SELECT SUM(to_number(qr.'||cur_rec.child_database_column||')) ' || l_sql_string;
3416 ELSIF (cur_rec.element_relationship_type = 3 ) THEN -- average or Mean
3417 l_sql_string := 'SELECT AVG(to_number(qr.'||cur_rec.child_database_column||')) ' || l_sql_string;
3418 ELSIF (cur_rec.element_relationship_type = 4 ) THEN -- std. deviation
3419 l_sql_string := 'SELECT STDDEV(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
3420
3421 ELSIF (cur_rec.element_relationship_type = 5 ) THEN -- min
3422 l_sql_string := 'SELECT MIN(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
3423 ELSIF (cur_rec.element_relationship_type = 6 ) THEN -- max
3424 l_sql_string := 'SELECT MAX(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
3425 ELSIF (cur_rec.element_relationship_type = 7 ) THEN -- variance
3426 l_sql_string := 'SELECT VARIANCE(to_number(qr.'|| cur_rec.child_database_column||')) ' || l_sql_string;
3427 ELSIF (cur_rec.element_relationship_type = 8 ) THEN -- count
3428 -- anagarwa Tue Feb 18 11:13:20 PST 2003
3429 -- Bug 2789847
3430 -- Count may be done on non numeric elements like Sequence Numbers and
3431 -- even Nonconformance Status, Source etc.
3432 -- A to_number will cause an exception in such a case and is hence
3433 -- removed from sql statement.
3434 l_sql_string := 'SELECT COUNT(qr.'|| cur_rec.child_database_column||') ' || l_sql_string;
3435 END IF;
3436 -- find out the aggregate value for the element in child plan.
3437 BEGIN
3438 EXECUTE IMMEDIATE l_sql_string INTO l_value
3439 USING p_parent_occurrence,p_child_plan_id;
3440 EXCEPTION
3441 WHEN OTHERS THEN raise;
3442
3443 END;
3444
3445 -- Bug 2716973
3446 -- When the child aggregate relationship element value is updated to parent record,
3447 -- Post-Forms-Commit Trigger error raised if child element contain null value.
3448 -- rponnusa Sun Jan 12 23:59:07 PST 2003
3449
3450 l_value := NVL(l_value,0);
3451
3452 -- See 2624112
3453 -- The maximum allowed precision is now expanded to 12.
3454 -- Rounding to 12...
3455 -- rkunchal Thu Oct 17 22:51:45 PDT 2002
3456
3457 -- rounding off to 6 digits is required since, for a number field, the maximum allowd
3458 -- decimal places is 6.
3459
3460 -- l_value := round(l_value,6);
3461 l_value := round(l_value,12);
3462
3463 -- now we need to update the parent record. Build the sql here.
3464
3465 -- Bug 4270911. CU2 SQL Literal fix.TD #19
3466 -- Use bind variable for child txn hdr id.
3467 -- srhariha. Fri Apr 15 05:55:04 PDT 2005.
3468
3469 l_update_parent_sql := 'UPDATE qa_results SET '
3470 || cur_rec.parent_database_column || ' = :l_value'
3471 || ' ,txn_header_id = :p_child_txn_hdr_id'
3472 || ' WHERE plan_id= :p_parent_plan_id'
3473 || ' AND collection_id= :p_parent_collection_id'
3474 || ' AND occurrence= :p_parent_occurrence';
3475 BEGIN
3476 EXECUTE IMMEDIATE l_update_parent_sql
3477 USING l_value,p_child_txn_hdr_id,p_parent_plan_id,p_parent_collection_id,p_parent_occurrence;
3478
3479 -- 12.1 QWB Usability improvements
3480 -- Building a list of the Aggregated parent plan elements
3481 --
3482 x_agg_elements := x_agg_elements ||','||
3483 qa_ak_mapping_api.get_vo_attribute_name(cur_rec.parent_char_id, p_parent_plan_id);
3484 -- 12.1 QWB Usability improvements
3485 -- Building a list of the Aggregated values
3486 --
3487 x_agg_val := x_agg_val ||','|| l_value;
3488 EXCEPTION
3489 WHEN OTHERS THEN raise;
3490 END;
3491
3492
3493 END LOOP;
3494 -- we are returning true when the parent record is updated or
3495 -- there is no aggregate relationship defined for the parent,child plans.
3496
3497 -- Bug 2300962. Needs explicit commit, if called from post-database-commit trigger
3498 -- bug 5306909
3499 -- Commenting this COMMIT as this Update_parent function
3500 -- with the Txn_header_id is called from QWB
3501 -- wherein the Commits are appropriately handled
3502 -- ntungare
3503 --
3504 -- COMMIT;
3505
3506 RETURN 'T';
3507
3508 END update_parent;
3509
3510 -- Bug 3536025. Adding a new procedure insert_history_auto_rec_QWB,which will be
3511 -- called from qltssreb.pls (Quality Workbench). This procedure is very much
3512 -- similar to insert_history_auto_rec ,except this procedure doesnot changes
3513 -- the child plan's txn_header_id and doesnot fire actions for child plans.
3514 -- srhariha. Wed May 26 22:31:28 PDT 2004
3515
3516 -- Bug 3681815.
3517 -- Removing the old procedure insert_history_auto_rec_QWB with the new code
3518 -- saugupta Tue, 15 Jun 2004 05:23:07 -0700 PDT
3519 --This procedure is similar to the insert_history_auto_rec but is
3520 --simplified for the needs of the SSQR post/update results processing.
3521 --The primary differences are that this procedure is limited to a single
3522 --parent row, the children have the same txn_header_id as the parent, and
3523 --the results are not enabled/don't have actions fired. This
3524 --enabling/action firing is deferred to the ssqr_post_actions() method.
3525 --Instead, this procedure checks for children using the criteria and then
3526 --passes off to insert_automatic_records to actually create the child
3527 --result rows and relationship rows.
3528 --ilawler Thu Jun 10 17:24:08 2004
3529
3530 PROCEDURE insert_history_auto_rec_QWB(p_plan_id IN NUMBER,
3531 p_collection_id IN NUMBER,
3532 p_occurrence IN NUMBER,
3533 p_organization_id IN NUMBER,
3534 p_txn_header_id IN NUMBER,
3535 p_relationship_type IN NUMBER,
3536 p_data_entry_mode IN NUMBER,
3537 x_status OUT NOCOPY VARCHAR2) IS
3538
3539 CURSOR child_check_cur(c_plan_id NUMBER) IS
3540 SELECT 'T'
3541 FROM qa_pc_plan_relationship
3542 WHERE parent_plan_id = c_plan_id
3543 AND plan_relationship_type = p_relationship_type
3544 AND data_entry_mode = p_data_entry_mode;
3545
3546 l_status VARCHAR2(1);
3547 l_criteria_values VARCHAR2(32000);
3548 l_child_plan_ids VARCHAR2(10000);
3549
3550 BEGIN
3551 --sanity check, make sure this plan has relevant children
3552 BEGIN
3553 OPEN child_check_cur(p_plan_id);
3554 FETCH child_check_cur INTO l_status;
3555 CLOSE child_check_cur;
3556 EXCEPTION
3557 WHEN OTHERS THEN
3558 l_status := 'F';
3559 END;
3560
3561 IF (l_status <> 'T' OR l_status is NULL) THEN
3562 -- no child plans with type and entry mode provided
3563 RETURN;
3564 END IF;
3565
3566 --check plan's values against child plans' criteria to get a list of
3567 --applicable children in l_child_plan_ids
3568 get_criteria_values(p_parent_plan_id => p_plan_id,
3569 p_parent_collection_id => p_collection_id,
3570 p_parent_occurrence => p_occurrence,
3571 p_organization_id => p_organization_id,
3572 x_criteria_values => l_criteria_values);
3573
3574 l_status := evaluate_criteria(p_plan_id => p_plan_id,
3575 p_criteria_values => l_criteria_values,
3576 p_relationship_type => p_relationship_type,
3577 p_data_entry_mode => p_data_entry_mode,
3578 x_child_plan_ids => l_child_plan_ids);
3579
3580 IF (l_status = 'T') THEN
3581
3582 --when evaluate_criteria returns T, we have children that need to be
3583 --created so call insert_automatic_records to do the grunt child row
3584 --creation.
3585 insert_automatic_records(p_plan_id => p_plan_id,
3586 p_collection_id => p_collection_id,
3587 p_occurrence => p_occurrence,
3588 p_child_plan_ids => l_child_plan_ids,
3589 p_relationship_type => p_relationship_type,
3590 p_data_entry_mode => p_data_entry_mode,
3591 p_criteria_values => l_criteria_values,
3592 p_org_id => p_organization_id,
3593 p_spec_id => null,
3594 x_status => l_status,
3595 p_txn_header_id => p_txn_header_id);
3596
3597 --make sure the insert_automatic succeeded
3598 IF (l_status <> 'T') THEN
3599 x_status := l_status;
3600 RETURN;
3601 END IF;
3602 END IF;
3603
3604 --don't worry about firing actions, this is handled in
3605 --ssqr_post_actions
3606
3607 x_status := 'T';
3608 RETURN;
3609
3610 END insert_history_auto_rec_QWB;
3611
3612 -- The following procedure was added to remove the entry
3613 -- from QA_PC_RESULTS_RELATIONSHIP table when the user
3614 -- deletes the record from the child plan and saves the
3615 -- child plan. This procedure is called from procedure
3616 -- key_delete_dependent_rows in QLTRES.pld.
3617 -- Bug 3646166.suramasw.
3618
3619 PROCEDURE DELETE_RELATIONSHIP_ROW(p_child_plan_id IN NUMBER,
3620 p_child_occurrence IN NUMBER) IS
3621
3622 BEGIN
3623
3624 DELETE FROM qa_pc_results_relationship
3625 WHERE child_plan_id = p_child_plan_id
3626 AND child_occurrence = p_child_occurrence;
3627
3628 END;
3629
3630 -- Bug 4343758
3631 -- R12 OAF Txn Integration Project
3632 -- Function to delete a Result Row and and it's parent child relationship
3633 -- shkalyan 05/13/2005.
3634 FUNCTION delete_row(
3635 p_plan_id IN NUMBER,
3636 p_collection_id IN NUMBER,
3637 p_occurrence IN NUMBER,
3638 p_enabled IN NUMBER := NULL) RETURN VARCHAR2
3639 IS
3640
3641 l_api_name CONSTANT VARCHAR2(30) := 'DELETE_ROW';
3642 l_parent_plan_id NUMBER;
3643 l_parent_collection_id NUMBER;
3644 l_parent_occurrence NUMBER;
3645
3646 l_return_status VARCHAR2(1);
3647
3648 -- Bug 4343758. OA Framework Integration project.
3649 -- Cursor to fetch relationship details.
3650 -- srhariha. Tue May 24 22:56:13 PDT 2005.
3651
3652 CURSOR c1 IS
3653 SELECT parent_plan_id,
3654 parent_collection_id,
3655 parent_occurrence
3656 FROM QA_PC_RESULTS_RELATIONSHIP
3657 WHERE child_plan_id = p_plan_id
3658 AND child_collection_id = p_collection_id
3659 AND child_occurrence = p_occurrence;
3660
3661 agg_elements VARCHAR2(4000);
3662 agg_val VARCHAR2(4000);
3663
3664 BEGIN
3665
3666 IF ( FND_LOG.level_procedure >= FND_LOG.g_current_runtime_level ) THEN
3667 FND_LOG.string
3668 (
3669 FND_LOG.level_procedure,
3670 g_pkg_name || '.' || l_api_name,
3671 'ENTERING PROCEDURE: P_PLAN_ID: ' || p_plan_id || ' P_COLLECTION_ID: ' || p_collection_id || ' P_OCCURRENCE: ' || p_occurrence || ' P_ENABLED: ' || p_enabled
3672 );
3673 END IF;
3674
3675 DELETE QA_RESULTS
3676 WHERE occurrence = p_occurrence
3677 AND plan_id = p_plan_id
3678 AND collection_id = p_collection_id;
3679
3680 IF ( FND_LOG.level_statement >= FND_LOG.g_current_runtime_level ) THEN
3681 FND_LOG.string
3682 (
3683 FND_LOG.level_statement,
3684 g_pkg_name || '.' || l_api_name,
3685 'DELETED ROW IN QA RESULTS. GETTING PARENT'
3686 );
3687 END IF;
3688
3689 -- Bug 4343758. Oa Framework Integration project.
3690 -- Use cursor to fetch relationship details.
3691 -- srhariha. Tue May 24 22:56:13 PDT 2005.
3692 l_parent_plan_id := null;
3693
3694 OPEN C1;
3695 FETCH C1 INTO l_parent_plan_id,l_parent_collection_id,l_parent_occurrence;
3696 CLOSE C1;
3697
3698 IF ( l_parent_plan_id IS NOT NULL ) THEN
3699 IF ( FND_LOG.level_statement >= FND_LOG.g_current_runtime_level ) THEN
3700 FND_LOG.string
3701 (
3702 FND_LOG.level_statement,
3703 g_pkg_name || '.' || l_api_name,
3704 'BEFORE DELETING RELATIONSHIP ROW FOR CHILD'
3705 );
3706 END IF;
3707
3708 delete_relationship_row
3709 (
3710 p_child_plan_id => p_plan_id,
3711 p_child_occurrence => p_occurrence
3712 );
3713
3714 IF ( FND_LOG.level_statement >= FND_LOG.g_current_runtime_level ) THEN
3715 FND_LOG.string
3716 (
3717 FND_LOG.level_statement,
3718 g_pkg_name || '.' || l_api_name,
3719 'BEFORE UPDATING PARENT FOR AGGREGATION PLAN_ID: ' || l_parent_plan_id || ' COLLECTION_ID: ' || l_parent_collection_id || ' OCCURRENCE: ' || l_parent_occurrence || ' FOR AGGREGATION '
3720 );
3721 END IF;
3722
3723 -- 12.1 QWB Usability Improvements
3724 -- Added 2 new parameters to get a list of Aggregated elements
3725 -- and their values
3726 --
3727 l_return_status :=
3728 aggregate_parent
3729 (
3730 p_parent_plan_id => l_parent_plan_id,
3731 p_parent_collection_id => l_parent_collection_id,
3732 p_parent_occurrence => l_parent_occurrence,
3733 p_child_plan_id => p_plan_id,
3734 p_child_collection_id => TO_NUMBER( NULL ),
3735 p_child_occurrence => TO_NUMBER( NULL ),
3736 p_commit => 'F',
3737 x_agg_elements => agg_elements,
3738 x_agg_val => agg_val
3739 );
3740 END IF;
3741
3742 IF ( FND_LOG.level_procedure >= FND_LOG.g_current_runtime_level ) THEN
3743 FND_LOG.string
3744 (
3745 FND_LOG.level_procedure,
3746 g_pkg_name || '.' || l_api_name,
3747 'EXITING PROCEDURE: SUCCESS'
3748 );
3749 END IF;
3750
3751 RETURN 'T';
3752
3753 END delete_row;
3754
3755
3756 -- Bug 4345779. Audits Copy UI project.
3757 -- Code Review feedback incorporation. CR Ref 4.9.5, 4.9.6 and 4.9.7
3758 -- Modularization. Parent child API's must be defined in parent pkg.
3759 -- srhariha. Tue Jul 12 02:12:17 PDT 2005.
3760
3761 --
3762 -- Parent-Child collections API. Operaters on collection of records.
3763 --
3764
3765
3766 -- Bug 4345779. Audits Copy UI project.
3767 -- Code Review feedback incorporation. CR Ref 4.10.1
3768 -- Using static SQL.
3769 -- srhariha. Thu Sep 29 00:09:40 PDT 2005.
3770
3771 PROCEDURE create_relationship_for_coll
3772 ( p_parent_plan_id NUMBER,
3773 p_parent_collection_id NUMBER,
3774 p_parent_occurrence NUMBER,
3775 p_child_plan_id NUMBER,
3776 p_child_collection_id NUMBER,
3777 p_org_id NUMBER) IS
3778
3779 l_sql_string VARCHAR2(1000);
3780
3781 -- Bug 4345779. Audits Copy UI project.
3782 -- Code Review feedback incorporation. CR Ref 4.9.1
3783 -- l_api_name must be declared as constant.
3784 -- srhariha. Tue Jul 12 02:12:17 PDT 2005.
3785
3786 l_api_name CONSTANT VARCHAR2(40) := 'CREATE_RELATIONSHIP ()';
3787
3788 BEGIN
3789 INSERT INTO QA_PC_RESULTS_RELATIONSHIP (PARENT_PLAN_ID,
3790 PARENT_COLLECTION_ID,
3791 PARENT_OCCURRENCE,
3792 CHILD_PLAN_ID,
3793 CHILD_COLLECTION_ID,
3794 CHILD_OCCURRENCE,
3795 ENABLED_FLAG,
3796 LAST_UPDATE_DATE,
3797 LAST_UPDATED_BY,
3798 CREATION_DATE,
3799 CREATED_BY,
3800 LAST_UPDATE_LOGIN,
3801 CHILD_TXN_HEADER_ID)
3802 SELECT p_parent_plan_id,
3803 p_parent_collection_id,
3804 p_parent_occurrence,
3805 QR.PLAN_ID,
3806 QR.COLLECTION_ID,
3807 QR.OCCURRENCE,
3808 2,
3809 SYSDATE,
3810 FND_GLOBAL.USER_ID,
3811 SYSDATE,
3812 FND_GLOBAL.USER_ID,
3813 FND_GLOBAL.USER_ID,
3814 QR.TXN_HEADER_ID
3815 FROM QA_RESULTS QR
3816 WHERE QR.PLAN_ID = p_child_plan_id
3817 AND QR.COLLECTION_ID = p_child_collection_id
3818 AND QR.ORGANIZATION_ID = p_org_id;
3819
3820
3821 EXCEPTION
3822
3823 WHEN OTHERS THEN
3824 IF ( FND_MSG_PUB.Check_Msg_Level( FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR ) ) THEN
3825 FND_MSG_PUB.Add_Exc_Msg
3826 (
3827 p_pkg_name => g_pkg_name,
3828 p_procedure_name => l_api_name,
3829 p_error_text => SUBSTR(SQLERRM,1,240)
3830 );
3831 END IF;
3832
3833 IF ( FND_LOG.level_procedure >= FND_LOG.g_current_runtime_level ) THEN
3834 FND_LOG.string
3835 (
3836 FND_LOG.level_procedure,
3837 g_pkg_name || '.' || l_api_name,
3838 'EXITING PROCEDURE: ERROR'
3839 );
3840 END IF;
3841
3842 RAISE;
3843
3844 END create_relationship_for_coll;
3845
3846
3847 PROCEDURE get_copy_result_cols(p_parent_plan_id NUMBER,
3848 p_child_plan_id NUMBER,
3849 x_parent_rc_str OUT NOCOPY VARCHAR2,
3850 x_child_rc_str OUT NOCOPY VARCHAR2 ) IS
3851
3852 CURSOR C IS
3853 SELECT qprc.parent_database_column,
3854 qprc.child_database_column
3855 FROM qa_pc_result_columns_v qprc
3856 WHERE qprc.parent_plan_id = p_parent_plan_id and
3857 qprc.child_plan_id = p_child_plan_id and
3858 qprc.element_relationship_type = 1 and
3859 parent_enabled_flag = 1 and
3860 child_enabled_flag = 1;
3861
3862 p_rc DBMS_SQL.VARCHAR2_TABLE;
3863 c_rc DBMS_SQL.VARCHAR2_TABLE;
3864
3865
3866 BEGIN
3867
3868 OPEN C;
3869 FETCH C BULK COLLECT INTO p_rc,c_rc;
3870 CLOSE C;
3871
3872 if(p_rc is null OR c_rc is null) then
3873 return;
3874 end if;
3875
3876
3877 FOR i IN p_rc.FIRST .. p_rc.LAST LOOP
3878 x_parent_rc_str := x_parent_rc_str || p_rc(i);
3879 x_child_rc_str := x_child_rc_str || c_rc(i);
3880
3881 IF (i <> p_rc.LAST) THEN
3882 x_parent_rc_str := x_parent_rc_str || ', ';
3883 x_child_rc_str := x_child_rc_str || ', ';
3884 END IF;
3885
3886
3887 END LOOP;
3888
3889
3890
3891 END get_copy_result_cols;
3892
3893 PROCEDURE copy_from_parent_for_coll
3894 (p_parent_plan_id NUMBER,
3895 p_parent_collection_id NUMBER,
3896 p_parent_occurrence NUMBER,
3897 p_child_plan_id NUMBER,
3898 p_child_collection_id NUMBER,
3899 p_org_id NUMBER) IS
3900
3901 l_sql_string VARCHAR2(32000);
3902 l_src_string VARCHAR2(32000);
3903 l_dest_string VARCHAR2(32000);
3904 -- Bug 4345779. Audits Copy UI project.
3905 -- Code Review feedback incorporation. CR Ref 4.9.1
3906 -- l_api_name must be declared as constant.
3907 -- srhariha. Tue Jul 12 02:12:17 PDT 2005.
3908
3909 l_api_name CONSTANT VARCHAR2(40) := 'COPY_FROM_PARENT_FOR_COLL';
3910 BEGIN
3911
3912 -- get parent and child result column names
3913 get_copy_result_cols(p_parent_plan_id => p_parent_plan_id,
3914 p_child_plan_id => p_child_plan_id,
3915 x_parent_rc_str => l_src_string,
3916 x_child_rc_str => l_dest_string);
3917
3918 l_sql_string := ' UPDATE QA_RESULTS ' ||
3919 ' SET ( ' || l_dest_string || ' ) = ' ||
3920 ' ( SELECT ' || l_src_string || ' ' ||
3921 ' FROM QA_RESULTS QR1 ' ||
3922 ' WHERE QR1.PLAN_ID = :1 ' ||
3923 ' AND QR1.COLLECTION_ID = :2' ||
3924 ' AND QR1.OCCURRENCE = :3) ' ||
3925 ' WHERE PLAN_ID = :4 ' ||
3926 ' AND COLLECTION_ID = :5 ';
3927
3928 EXECUTE IMMEDIATE l_sql_string USING p_parent_plan_id,
3929 p_parent_collection_id,
3930 p_parent_occurrence,
3931 p_child_plan_id,
3932 p_child_collection_id;
3933
3934 EXCEPTION
3935
3936 WHEN OTHERS THEN
3937 IF ( FND_MSG_PUB.Check_Msg_Level( FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR ) ) THEN
3938 FND_MSG_PUB.Add_Exc_Msg
3939 (
3940 p_pkg_name => g_pkg_name,
3941 p_procedure_name => l_api_name,
3942 p_error_text => SUBSTR(SQLERRM,1,240)
3943 );
3944 END IF;
3945
3946 IF ( FND_LOG.level_procedure >= FND_LOG.g_current_runtime_level ) THEN
3947 FND_LOG.string
3948 (
3949 FND_LOG.level_procedure,
3950 g_pkg_name || '.' || l_api_name,
3951 'EXITING PROCEDURE: ERROR'
3952 );
3953 END IF;
3954
3955 RAISE;
3956 END copy_from_parent_for_coll;
3957
3958 -- Bug 4345779. Audits Copy UI project.
3959 -- Code Review feedback incorporation. CR Ref 4.10.2
3960 -- Rewriting the logic based on new interesting algo
3961 -- suggested by Bryan.
3962 -- srhariha. Thu Sep 29 00:09:40 PDT 2005.
3963
3964 PROCEDURE create_history_for_coll (
3965 p_plan_id NUMBER,
3966 p_collection_id NUMBER,
3967 p_org_id NUMBER,
3968 p_txn_header_id NUMBER) IS
3969
3970 l_sql_string VARCHAR2(32000);
3971
3972
3973 CURSOR c(x_plan_id NUMBER) IS
3974 SELECT child_plan_id
3975 FROM qa_pc_plan_relationship
3976 WHERE parent_plan_id = x_plan_id
3977 AND data_entry_mode = 4;
3978
3979 l_src_string VARCHAR2(32000);
3980 l_dest_string VARCHAR2(32000);
3981 -- Bug 4345779. Audits Copy UI project.
3982 -- Code Review feedback incorporation. CR Ref 4.9.1
3983 -- l_api_name must be declared as constant.
3984 -- srhariha. Tue Jul 12 02:12:17 PDT 2005.
3985
3986 l_api_name CONSTANT VARCHAR2(40) := 'CREATE_HISTORY';
3987
3988 BEGIN
3989
3990 -- get history plan id
3991
3992 FOR hst_rec IN c(p_plan_id) LOOP
3993
3994 INSERT INTO QA_PC_RESULTS_RELATIONSHIP (
3995 PARENT_PLAN_ID,
3996 PARENT_COLLECTION_ID,
3997 PARENT_OCCURRENCE,
3998 CHILD_PLAN_ID ,
3999 CHILD_COLLECTION_ID,
4000 CHILD_OCCURRENCE,
4001 ENABLED_FLAG,
4002 LAST_UPDATE_DATE,
4003 LAST_UPDATED_BY,
4004 CREATION_DATE,
4005 CREATED_BY ,
4006 LAST_UPDATE_LOGIN,
4007 CHILD_TXN_HEADER_ID)
4008 SELECT QR.PLAN_ID,
4009 QR.COLLECTION_ID,
4010 QR.OCCURRENCE,
4011 hst_rec.child_plan_id,
4012 p_collection_id,
4013 QA_OCCURRENCE_S.NEXTVAL,
4014 2,
4015 SYSDATE,
4016 FND_GLOBAL.USER_ID,
4017 SYSDATE,
4018 FND_GLOBAL.USER_ID,
4019 FND_GLOBAL.USER_ID,
4020 p_txn_header_id
4021 FROM QA_RESULTS QR
4022 WHERE QR.PLAN_ID = p_plan_id
4023 AND QR.COLLECTION_ID = p_collection_id
4024 AND QR.ORGANIZATION_ID = p_org_id;
4025
4026
4027
4028 -- get parent and child result column names
4029 get_copy_result_cols(p_parent_plan_id => p_plan_id,
4030 p_child_plan_id => hst_rec.child_plan_id,
4031 x_parent_rc_str => l_src_string,
4032 x_child_rc_str => l_dest_string);
4033
4034
4035 l_sql_string := ' INSERT INTO qa_results ( collection_id, ' ||
4036 ' occurrence, ' ||
4037 ' last_update_date, ' ||
4038 ' qa_last_update_date, '||
4039 ' last_updated_by, ' ||
4040 ' qa_last_updated_by, ' ||
4041 ' creation_date, ' ||
4042 ' qa_creation_date, ' ||
4043 ' created_by, ' ||
4044 ' last_update_login, ' ||
4045 ' qa_created_by, ' ||
4046 ' status, ' ||
4047 ' transaction_number, ' ||
4048 ' organization_id, ' ||
4049 ' plan_id, ' ||
4050 ' txn_header_id, ' ||
4051 l_dest_string || ')' ||
4052 ' SELECT QPRR.CHILD_COLLECTION_ID, ' ||
4053 ' QPRR.CHILD_OCCURRENCE, ' ||
4054 ' sysdate, ' ||
4055 ' sysdate, ' ||
4056 ' fnd_global.user_id, ' ||
4057 ' fnd_global.user_id, ' ||
4058 ' sysdate, ' ||
4059 ' sysdate, ' ||
4060 ' fnd_global.user_id, ' ||
4061 ' fnd_global.user_id, ' ||
4062 ' fnd_global.user_id, ' ||
4063 ' 2, ' ||
4064 ' -1, ' ||
4065 ' QR.ORGANIZATION_ID, ' ||
4066 ' QPRR.CHILD_PLAN_ID, ' ||
4067 ' QPRR.CHILD_TXN_HEADER_ID, ' ||
4068 l_src_string || ' ' ||
4069 ' FROM QA_RESULTS QR, QA_PC_RESULTS_RELATIONSHIP QPRR ' ||
4070 ' WHERE QPRR.CHILD_PLAN_ID = :1 ' ||
4071 ' AND QPRR.CHILD_COLLECTION_ID = :2 ' ||
4072 ' AND QPRR.PARENT_PLAN_ID = :3 ' ||
4073 ' AND QPRR.PARENT_COLLECTION_ID = :4 ' ||
4074 ' AND QPRR.PARENT_OCCURRENCE = QR.OCCURRENCE ';
4075
4076 EXECUTE IMMEDIATE l_sql_string USING hst_rec.child_plan_id,
4077 p_collection_id,
4078 p_plan_id,
4079 p_collection_id;
4080
4081
4082
4083 END LOOP; -- hst_rec
4084
4085 EXCEPTION
4086
4087 WHEN OTHERS THEN
4088 IF ( FND_MSG_PUB.Check_Msg_Level( FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR ) ) THEN
4089 FND_MSG_PUB.Add_Exc_Msg
4090 (
4091 p_pkg_name => g_pkg_name,
4092 p_procedure_name => l_api_name,
4093 p_error_text => SUBSTR(SQLERRM,1,240)
4094 );
4095 END IF;
4096
4097 IF ( FND_LOG.level_procedure >= FND_LOG.g_current_runtime_level ) THEN
4098 FND_LOG.string
4099 (
4100 FND_LOG.level_procedure,
4101 g_pkg_name || '.' || l_api_name,
4102 'EXITING PROCEDURE: ERROR'
4103 );
4104 END IF;
4105
4106 RAISE;
4107
4108
4109 END create_history_for_coll;
4110
4111
4112 -- Bug 4502450. R12 Esig Status support in Multirow UQR
4113 -- saugupta Wed, 24 Aug 2005 08:40:56 -0700 PDT
4114
4115 -- Function returns only all ancestors i.e parent and grandparent plan rows
4116 -- for a given child plan and does not retrun child itself.
4117 FUNCTION get_ancestors( p_child_plan_id IN NUMBER,
4118 p_child_occurrence IN NUMBER,
4119 p_child_collection_id IN NUMBER,
4120 x_parent_plan_ids OUT NOCOPY dbms_sql.number_table,
4121 x_parent_collection_ids OUT NOCOPY dbms_sql.number_table,
4122 x_parent_occurrences OUT NOCOPY dbms_sql.number_table)
4123 RETURN VARCHAR2
4124 IS
4125
4126 BEGIN
4127 -- check for NULL values
4128 IF( p_child_plan_id IS NULL OR
4129 p_child_occurrence IS NULL OR
4130 p_child_collection_id IS NULL) THEN
4131 -- return False
4132 RETURN 'F';
4133 END IF;
4134
4135 -- Given a child occurrence this query finds all the parents
4136 -- and grandparent records, therefore ancestors, of the child record.
4137 -- These are returned in the three output PL/SQL tables.
4138 -- The child record itself is not included in the output.
4139 SELECT parent_plan_id, parent_collection_id, parent_occurrence
4140 BULK COLLECT INTO x_parent_plan_ids, x_parent_collection_ids, x_parent_occurrences
4141 FROM qa_pc_results_relationship
4142 START WITH child_plan_id = p_child_plan_id
4143 AND child_occurrence = p_child_occurrence
4144 AND child_collection_id = p_child_collection_id
4145 CONNECT BY PRIOR parent_occurrence = child_occurrence;
4146
4147 IF (SQL%FOUND) THEN
4148 RETURN 'T';
4149 ELSE
4150 RETURN 'F';
4151 END IF;
4152
4153
4154 END get_ancestors;
4155
4156 --
4157 -- Bug 5435657
4158 -- New procedure to update the Aggregate values on
4159 -- all the ancestors of the plan_id passed, in case
4160 -- such a P-C relationship exists
4161 -- ntungare Wed Aug 2 20:53:40 PDT 2006
4162 --
4163 PROCEDURE update_all_ancestors(p_parent_plan_id IN NUMBER,
4164 p_parent_collection_id IN NUMBER,
4165 p_parent_occurrence IN NUMBER) IS
4166
4167 l_parent_plan_id_tab DBMS_SQL.NUMBER_TABLE;
4168 l_parent_collection_id_tab DBMS_SQL.NUMBER_TABLE;
4169 l_parent_occurrence_tab DBMS_SQL.NUMBER_TABLE;
4170
4171 l_current_child_planid NUMBER;
4172 l_current_child_collid NUMBER;
4173 l_current_child_occrid NUMBER;
4174 l_current_parent_planid NUMBER;
4175 l_current_parent_collid NUMBER;
4176 l_current_parent_occrid NUMBER;
4177
4178 BEGIN
4179 -- Calling the function get_ancestors to get a
4180 -- List of the Ancestors if they exist
4181 IF ( QA_PARENT_CHILD_PKG.get_ancestors(
4182 p_parent_plan_id,
4183 p_parent_occurrence,
4184 p_parent_collection_id,
4185 l_parent_plan_id_tab,
4186 l_parent_collection_id_tab,
4187 l_parent_occurrence_tab) = 'T') THEN
4188
4189 l_current_child_planid := p_parent_plan_id;
4190 l_current_child_collid := p_parent_collection_id;
4191 l_current_child_occrid := p_parent_occurrence;
4192
4193 -- Ancestors exist for the plan_id passed so
4194 -- Need to check if an aggregate P-C relationship
4195 -- exists and do the aggregation
4196 -- Looping through all the ancestors
4197 For ancestors_cntr in 1..l_parent_plan_id_tab.COUNT
4198 LOOP
4199 l_current_parent_planid := l_parent_plan_id_tab(ancestors_cntr);
4200 l_current_parent_collid := l_parent_collection_id_tab(ancestors_cntr);
4201 l_current_parent_occrid := l_parent_occurrence_tab(ancestors_cntr);
4202
4203 -- Calling the procedure to check for aggregate relationships
4204 -- and do the agrregation
4205 IF(QA_PARENT_CHILD_PKG.update_parent
4206 (l_current_parent_planid,
4207 l_current_parent_collid,
4208 l_current_parent_occrid,
4209 l_current_child_planid,
4210 l_current_child_collid,
4211 l_current_child_occrid)='T')
4212 THEN
4213 NULL;
4214 END IF;
4215
4216 -- Assigning the Current Parrent plan Id, Collection Id
4217 -- and the occurrences as the Child plan Plan id,
4218 -- Collcetion Id and occurrences, for the next round of
4219 -- processing of the ancestors collection
4220 --
4221 l_current_child_planid := l_current_parent_planid;
4222 l_current_child_collid := l_current_parent_collid;
4223 l_current_child_occrid := l_current_parent_occrid;
4224 END LOOP; -- End of Ancestors Loop
4225
4226 END If; -- End of If ancestors Found
4227 END update_all_ancestors;
4228
4229 --
4230 -- bug 6134920
4231 -- Added a new procedure to delete all the status
4232 -- 1 invalid child records, generated during an
4233 -- incomplete txn
4234 -- ntungare Tue Jul 10 23:08:22 PDT 2007
4235 --
4236 PROCEDURE delete_invalid_children(p_txn_header_id IN NUMBER) IS
4237 PRAGMA AUTONOMOUS_TRANSACTION;
4238
4239 TYPE child_plan_id_tab_typ IS TABLE OF qa_pc_results_relationship.child_plan_id%TYPE
4240 INDEX BY BINARY_INTEGER;
4241 TYPE child_collection_id_tab_typ IS TABLE OF qa_pc_results_relationship.child_collection_id%TYPE
4242 INDEX BY BINARY_INTEGER;
4243 TYPE child_occurrence_tab_typ IS TABLE OF qa_pc_results_relationship.child_occurrence%TYPE
4244 INDEX BY BINARY_INTEGER;
4245
4246 child_plan_id_tab child_plan_id_tab_typ;
4247 child_collection_id_tab child_collection_id_tab_typ;
4248 child_occurrence_tab child_occurrence_tab_typ;
4249
4250 BEGIN
4251 DELETE FROM qa_results
4252 WHERE txn_header_id = p_txn_header_id
4253 AND status = 1
4254 RETURNING plan_id, collection_id, occurrence
4255 BULK COLLECT INTO child_plan_id_tab,
4256 child_collection_id_tab,
4257 child_occurrence_tab;
4258
4259 FORALL cntr in 1..child_plan_id_tab.COUNT
4260 DELETE from qa_pc_results_relationship
4261 WHERE child_txn_header_id = p_txn_header_id
4262 AND child_plan_id = child_plan_id_tab(cntr)
4263 AND child_collection_id = child_collection_id_tab(cntr)
4264 AND child_occurrence = child_occurrence_tab(cntr);
4265
4266 COMMIT;
4267 END delete_invalid_children;
4268
4269 -- 12.1 QWB Usability Improvements
4270 -- New method to check if a Parent Plan record
4271 -- has any applicable child plan into which data can be
4272 -- entered.
4273 --
4274 FUNCTION has_enterable_child(p_plan_id in number,
4275 p_collection_id in number,
4276 p_occurrence in number)
4277 RETURN varchar2 as
4278 TYPE plan_det IS RECORD (char_id varchar2(200),
4279 res_col_name varchar2(200)) ;
4280
4281 TYPE res_col_tab_typ IS TABLE OF plan_det INDEX BY binary_integer;
4282 res_col_tab res_col_tab_typ;
4283 str varchar2(32767);
4284 result_string varchar2(32767);
4285
4286 plans qa_txn_grp.ElementsArray;
4287
4288 cntr NUMBER;
4289 BEGIN
4290 -- Getting the list of the result_column_names from the
4291 -- qa_plan_chars table
4292 SELECT char_id, result_column_name
4293 BULK COLLECT INTO res_col_tab
4294 FROM qa_plan_chars
4295 WHERE plan_id = p_plan_id;
4296
4297 -- building the select query
4298 FOR cntr in 1..res_col_tab.count
4299 LOOP
4300 str := res_col_tab(cntr).char_id ||
4301 '=''||REPLACE('||res_col_tab(cntr).res_col_name||
4302 ',''@'',''@@'')||''@'||str;
4303 END LOOP;
4304 str := rtrim(str, '||''@');
4305
4306 -- Use the columns list built above to query
4307 -- qa_results table, to build the result_string
4308 EXECUTE IMMEDIATE
4309 'Select '''||str||
4310 ' from qa_results where plan_id = :plan_id and
4311 collection_id = :collection_id and
4312 occurrence = :occurrence'
4313 INTO result_string USING p_plan_id,
4314 p_collection_id ,
4315 p_occurrence;
4316
4317 -- Pass the result string to the applicable_child_plans
4318 -- to get a list of applicable Child plans for the entered data
4319 -- and convert the list of plans returned as a string
4320 -- into an array
4321 plans := qa_txn_grp.result_to_array(
4322 qa_parent_child_pkg.applicable_child_plans(p_plan_id,
4323 result_string));
4324
4325 cntr := plans.first;
4326
4327 -- looping through the child plans list to check
4328 -- if there is any non History child plan
4329 WHILE cntr <= plans.LAST
4330 LOOP
4331 IF plans(cntr).VALUE <>4
4332 THEN RETURN 'CHILD_Y';
4333 END IF;
4334 cntr := plans.next(cntr);
4335 END LOOP;
4336 RETURN 'CHILD_N';
4337 END has_enterable_child;
4338
4339 -- 12.1 QWB Usability Improvements
4340 -- New method to check if there aare any updatable child records
4341 --
4342 FUNCTION child_exists_for_update(p_plan_id IN NUMBER,
4343 p_collection_id IN NUMBER,
4344 p_occurrence IN NUMBER)
4345 RETURN VARCHAR2 AS
4346 --
4347 -- removed the Immediate plans check
4348 -- ntungare
4349 --
4350 CURSOR cur is
4351 select 'UPDATE_CHILD_Y'
4352 from qa_pc_results_relationship qpc,
4353 qa_results qr,
4354 qa_pc_plan_relationship qpr
4355 where qpc.parent_plan_id = p_plan_id and
4356 qpc.parent_collection_id = p_collection_id and
4357 qpc.parent_occurrence = p_occurrence and
4358 qpc.child_plan_id = qr.plan_id and
4359 qpc.child_collection_id = qr.collection_id and
4360 qpc.child_occurrence = qr.occurrence and
4361 (qr.status = 2 or qr.status is NULL) and
4362 qpr.parent_plan_id = p_plan_id and
4363 qpr.child_plan_id = qpc.child_plan_id and
4364 qpr.data_entry_mode <> 4 and
4365 qa_web_txn_api.allowed_for_plan('QA_RESULTS_UPDATE', qpc.child_plan_id) = 'T';
4366 --rownum =1;
4367
4368 has_child VARCHAR2(100) :='UPDATE_CHILD_N';
4369 BEGIN
4370 /*
4371 This procedure has a bit of a complexity in the form that if the
4372 Criteria defined for the P-C relationship is changed later, then
4373 the child data that has already been collected would be no longer
4374 be applicable, in which case the child records though present in
4375 the relationship table should be ignored. For this we need to
4376 make a call to the "has_enterable" procedure to check for the
4377 applicable children, which would be a severe overhead. A better
4378 way is to prevent the user from changing the criteria if Child
4379 records that match the criteria have already been collected.
4380 */
4381 OPEN cur;
4382 FETCH cur INTO has_child;
4383 CLOSE cur;
4384
4385 RETURN has_child;
4386 END child_exists_for_update;
4387
4388 -- 12.1 QWB usability Improvements
4389 -- New method to get a count of child records
4390 -- present for any parent plan record
4391 --
4392 FUNCTION getChildCount(p_plan_id IN NUMBER,
4393 p_collection_id IN NUMBER,
4394 p_occurrence IN NUMBER)
4395 RETURN NUMBER AS
4396
4397 childCount NUMBER := 0;
4398 BEGIN
4399 SELECT count(*) INTO childCount
4400 FROM qa_pc_results_relationship qpc,
4401 qa_results qr
4402 WHERE qpc.parent_plan_id = p_plan_id and
4403 qpc.parent_collection_id = p_collection_id and
4404 qpc.parent_occurrence = p_occurrence and
4405 qpc.child_plan_id = qr.plan_id and
4406 qpc.child_collection_id = qr.collection_id and
4407 qpc.child_occurrence = qr.occurrence and
4408 (qr.status = 2 or qr.status is NULL);
4409
4410 RETURN childCount;
4411 end getChildCount;
4412
4413 -- 12.1 Quality Inline Transaction INtegration
4414 -- New method to identify whether a plan has
4415 -- child plans associated with it or not
4416 --
4417 FUNCTION has_child(p_plan_id IN NUMBER)
4418 RETURN INTEGER AS
4419
4420 childCount NUMBER;
4421 BEGIN
4422 SELECT count(*) INTO childCount
4423 FROM qa_pc_plan_relationship
4424 WHERE parent_plan_id=p_plan_id;
4425 IF childCount > 0 THEN
4426 RETURN 1;
4427 ELSE
4428 RETURN 2;
4429 END IF;
4430 END has_child;
4431
4432 -- 12.1 QWB Usability Improvements project
4433 -- Function to update all the History
4434 -- Child records corresponding to a parent record
4435 FUNCTION update_hist_children(p_parent_plan_id IN NUMBER,
4436 p_parent_collection_id IN NUMBER,
4437 p_parent_occurrence IN NUMBER)
4438 RETURN VARCHAR2 IS
4439
4440 l_return_value VARCHAR2(1);
4441 l_dummy VARCHAR2(1);
4442
4443 CURSOR children_cur IS
4444 select qprr.child_plan_id,
4445 qprr.child_collection_id,
4446 qprr.child_occurrence
4447 from qa_pc_results_relationship qprr,
4448 qa_pc_plan_relationship qpr
4449 where qprr.parent_occurrence = p_parent_occurrence
4450 and qprr.parent_plan_id = p_parent_plan_id
4451 and qprr.parent_collection_id = p_parent_collection_id
4452 and qpr.parent_plan_id = qprr.parent_plan_id
4453 and qpr.child_plan_id = qprr.child_plan_id
4454 and qpr.data_entry_mode = 4;
4455
4456 BEGIN
4457 l_return_value := 'T';
4458 l_dummy := 'T';
4459
4460 FOR children_rec IN children_cur
4461 LOOP
4462 l_return_value :=
4463 update_child ( p_parent_plan_id,
4464 p_parent_collection_id,
4465 p_parent_occurrence,
4466 children_rec.child_plan_id,
4467 children_rec.child_collection_id,
4468 children_rec.child_occurrence);
4469 END LOOP;
4470
4471 RETURN l_return_value;
4472 END update_hist_children;
4473
4474 -- Bug 7436465.FP for Bug 7035041.pdube Fri Sep 26 03:46:20 PDT 2008
4475 -- Inroduced this procedure to check if any child record exists for parent record.
4476 FUNCTION IF_CHILD_RECORD_EXISTS( p_plan_id IN NUMBER,
4477 p_collection_id IN NUMBER,
4478 p_occurrence IN NUMBER) RETURN result_column_name_tab_typ IS
4479 result_column_name_tab result_column_name_tab_typ;
4480 BEGIN
4481 SELECT REPLACE(DECODE(QC.HARDCODED_COLUMN, NULL ,QAPC.RESULT_COLUMN_NAME,QC.DEVELOPER_NAME),
4482 'CHARACTER','DISPLAY') FORM_FIELD
4483 BULK COLLECT INTO result_column_name_tab
4484 FROM qa_pc_plan_relationship qppr,
4485 qa_pc_criteria qpc,
4486 qa_results qr,
4487 qa_plan_chars qapc,
4488 qa_chars qc
4489 WHERE qpc.plan_relationship_id = qppr.plan_relationship_id
4490 AND qapc.char_id = qpc.char_id
4491 AND qapc.char_id = qc.char_id
4492 AND qr.occurrence = p_occurrence
4493 AND qr.collection_id = p_collection_id
4494 AND qr.plan_id = p_plan_id
4495 AND qr.plan_id = qapc.plan_id
4496 AND qppr.parent_plan_id = qr.plan_id
4497 AND EXISTS
4498 (SELECT 1 FROM
4499 qa_pc_results_relationship qprr
4500 WHERE qppr.child_plan_id = qprr.child_plan_id
4501 AND qppr.parent_plan_id = qprr.parent_plan_id
4502 AND qppr.child_plan_id = qprr.child_plan_id
4503 AND qprr.parent_plan_id = qr.plan_id
4504 AND qprr.parent_collection_id = p_collection_id
4505 AND qprr.parent_occurrence = p_occurrence
4506 AND qprr.parent_plan_id = p_plan_id
4507 AND ROWNUM = 1);
4508
4509 RETURN result_column_name_tab;
4510 EXCEPTION
4511 WHEN OTHERS THEN
4512 RAISE;
4513 RETURN result_column_name_tab;
4514 END IF_CHILD_RECORD_EXISTS;
4515
4516 END QA_PARENT_CHILD_PKG;