1 PACKAGE BODY qa_validation_api AS
2 /* $Header: qltvalb.plb 120.40.12020000.3 2013/02/11 14:14:03 ntungare ship $ */
3
4 g_dependency_matrix DependencyArray;
5
6 --
7 -- Mapping between an internal validation error message code
8 -- and the AOL message name.
9 --
10 g_message_map dbms_sql.varchar2s;
11
12 g_restrict_subinv_code NUMBER;
13 g_restrict_locators_code NUMBER;
14 g_location_control_code NUMBER;
15 g_revision_qty_cntrl_code NUMBER;
16
17 g_comp_restrict_subinv_code NUMBER;
18 g_comp_restrict_locators_code NUMBER;
19 g_comp_location_control_code NUMBER;
20 g_comp_revision_qty_cntrl_code NUMBER;
21
22 -- Added the following for NCM Hardcode Elements.
23 -- suramasw Thu Oct 31 10:48:59 PST 2002.
24 -- Bug 2449067.
25
26 g_bill_restrict_subinv_code NUMBER;
27 g_bill_restrict_locators_code NUMBER;
28 g_bill_location_control_code NUMBER;
29 g_bill_revision_qty_cntrl_code NUMBER;
30
31 g_rout_restrict_subinv_code NUMBER;
32 g_rout_restrict_locators_code NUMBER;
33 g_rout_location_control_code NUMBER;
34 g_rout_revision_qty_cntrl_code NUMBER;
35
36 -- End of inclusions for NCM Hardcode Elements.
37
38
39 g_comp_item_id NUMBER;
40 g_item_id NUMBER;
41 g_org_id NUMBER;
42 g_transaction_number NUMBER;
43 g_transaction_id NUMBER;
44 g_lot_number VARCHAR2(150);
45 g_line_id NUMBER DEFAULT null;
46 g_wip_entity_id NUMBER;
47 g_po_header_id NUMBER;
48 --
49 -- bug 9652549 CLM changes
50 --
51 g_po_line_number VARCHAR2(240);
52 g_subinventory VARCHAR2(15);
53 -- Bug 9773026
54 -- Global variable to store RMA Header Id.
55 -- skolluku
56 g_rma_header_id NUMBER;
57
58 --
59 -- bug 11659488
60 -- Global variable to store sales_order_id
61 g_sales_order_id NUMBER;
62 --
63 -- See Bug 2588213
64 -- To support the element Maintenance Op Seq Number
65 -- to be used along with Maintenance Workorder
66 -- rkunchal Mon Sep 23 23:46:28 PDT 2002
67 -- Added the following global variable
68 --
69 g_work_order_id NUMBER;
70
71 -- Added the following for NCM Hardcode Elements.
72 -- suramasw Thu Oct 31 10:48:59 PST 2002.
73 -- Bug 2449067.
74
75 g_bill_reference_id NUMBER;
76 g_routing_reference_id NUMBER;
77 g_to_subinventory VARCHAR2(15);
78
79 --
80 -- Bug 6126260
81 -- Needed for validating the dependent
82 -- elements of componenet subinventory
83 -- like comp_locator.
84 -- bhsankar Mon Jul 16 05:51:51 PDT 2007
85 --
86 g_comp_subinventory VARCHAR2(15);
87
88 --
89 -- Bug 2672396. Added g_project_id because task is a dependent element.
90 -- We will need to keep a cache copy of project_id when it is validated
91 -- to be used to validate task_number later.
92 -- bso Mon Nov 25 17:29:56 PST 2002
93 --
94 g_project_id NUMBER;
95
96 -- End of inclusions for NCM Hardcode Elements.
97
98 -- R12 OPM Deviations. Bug 4345503 Start
99 g_process_batch_id NUMBER;
100 g_process_batchstep_id NUMBER;
101 g_process_activity_id NUMBER;
102 g_process_resource_id NUMBER;
103 -- R12 OPM Deviations. Bug 4345503 End
104
105 --
106 -- Bug 4635316.
107 -- Global variable to store the application user_id.
108 -- ntungare Wed Sep 28 05:59:14 PDT 2005.
109 --
110 g_user_id number;
111
112
113
114 -- Bug 4558205. Lot/Serial Validation.
115 g_revision VARCHAR2(10);
116 -- End 4558205.
117
118
119 -- Bug 4558205. Lot/Serial Validation.
120 -- Init procedure for global variables.
121 -- srhariha. Tue Sep 27 05:07:58 PDT 2005.
122
123 PROCEDURE init_globals IS
124
125 BEGIN
126 g_lot_number := NULL;
127 g_revision := NULL;
128 END init_globals;
129
130 -- End 4558205.
131
132 PROCEDURE populate_dependency_matrix IS
133
134 BEGIN
135
136 g_dependency_matrix(1).element_id := qa_ss_const.item;
137 g_dependency_matrix(1).parent := qa_ss_const.production_line;
138
139 g_dependency_matrix(2).element_id := qa_ss_const.to_op_seq_num;
140 g_dependency_matrix(2).parent := qa_ss_const.job_name;
141
142 g_dependency_matrix(3).element_id := qa_ss_const.to_op_seq_num;
143 g_dependency_matrix(3).parent := qa_ss_const.production_line;
144
145 g_dependency_matrix(4).element_id := qa_ss_const.from_op_seq_num;
146 g_dependency_matrix(4).parent := qa_ss_const.job_name;
147
148 g_dependency_matrix(5).element_id := qa_ss_const.from_op_seq_num;
149 g_dependency_matrix(5).parent := qa_ss_const.production_line;
150
151 g_dependency_matrix(6).element_id := qa_ss_const.to_intraoperation_step;
152 g_dependency_matrix(6).parent := qa_ss_const.to_op_seq_num;
153
154 g_dependency_matrix(7).element_id := qa_ss_const.from_intraoperation_step;
155 g_dependency_matrix(7).parent := qa_ss_const.from_op_seq_num;
156
157 g_dependency_matrix(8).element_id := qa_ss_const.uom;
158 g_dependency_matrix(8).parent := qa_ss_const.item;
159
160 g_dependency_matrix(9).element_id := qa_ss_const.revision;
161 g_dependency_matrix(9).parent := qa_ss_const.item;
162
163 g_dependency_matrix(10).element_id := qa_ss_const.subinventory;
164 g_dependency_matrix(10).parent := qa_ss_const.item;
165
166 g_dependency_matrix(11).element_id := qa_ss_const.locator;
167 g_dependency_matrix(11).parent := qa_ss_const.subinventory;
168
169 g_dependency_matrix(12).element_id := qa_ss_const.lot_number;
170 g_dependency_matrix(12).parent := qa_ss_const.item;
171
172 g_dependency_matrix(13).element_id := qa_ss_const.serial_number;
173 g_dependency_matrix(13).parent := qa_ss_const.item;
174
175 g_dependency_matrix(14).element_id := qa_ss_const.comp_uom;
176 g_dependency_matrix(14).parent := qa_ss_const.comp_item;
177
178 g_dependency_matrix(15).element_id := qa_ss_const.comp_revision;
179 g_dependency_matrix(15).parent := qa_ss_const.comp_item;
180
181 g_dependency_matrix(16).element_id := qa_ss_const.po_line_num;
182 g_dependency_matrix(16).parent := qa_ss_const.po_number;
183
184 g_dependency_matrix(17).element_id := qa_ss_const.po_shipment_num;
185 g_dependency_matrix(17).parent := qa_ss_const.po_line_num;
186
187 g_dependency_matrix(18).element_id := qa_ss_const.po_release_num;
188 g_dependency_matrix(18).parent := qa_ss_const.po_number;
189
190 g_dependency_matrix(19).element_id := qa_ss_const.order_line;
191 g_dependency_matrix(19).parent := qa_ss_const.sales_order;
192
193 g_dependency_matrix(20).element_id := qa_ss_const.task_number;
194 g_dependency_matrix(20).parent := qa_ss_const.project_number;
195
196 g_dependency_matrix(21).element_id := qa_ss_const.serial_number;
197 g_dependency_matrix(21).parent := qa_ss_const.lot_number;
198
199 g_dependency_matrix(22).element_id := qa_ss_const.contract_line_number;
200 g_dependency_matrix(22).parent := qa_ss_const.contract_number;
201
202 g_dependency_matrix(23).element_id := qa_ss_const.deliverable_number;
203 g_dependency_matrix(23).parent := qa_ss_const.contract_line_number;
204
205 g_dependency_matrix(24).element_id := qa_ss_const.asset_number;
206 g_dependency_matrix(24).parent := qa_ss_const.asset_group;
207
208 --
209 -- See Bug 2588213
210 -- To support the element Maintenance Op Seq Number
211 -- to be used along with Maintenance Workorder
212 -- rkunchal Mon Sep 23 23:46:28 PDT 2002
213 --
214 g_dependency_matrix(25).element_id := qa_ss_const.maintenance_op_seq;
215 g_dependency_matrix(25).parent := qa_ss_const.work_order;
216
217 -- Start of inclusions for NCM Hardcode Elements.
218 -- suramasw Thu Oct 31 10:48:59 PST 2002.
219 -- Bug 2449067.
220
221 g_dependency_matrix(26).element_id := qa_ss_const.to_subinventory;
222 g_dependency_matrix(26).parent := qa_ss_const.item;
223
224 g_dependency_matrix(27).element_id := qa_ss_const.to_locator;
225 g_dependency_matrix(27).parent := qa_ss_const.to_subinventory;
226
227 -- R12 OPM Deviations. Bug 4345503 Start
228 g_dependency_matrix(28).element_id := qa_ss_const.process_batchstep_num;
229 g_dependency_matrix(28).parent := qa_ss_const.process_batch_num;
230
231 g_dependency_matrix(29).element_id := qa_ss_const.process_operation;
232 g_dependency_matrix(29).parent := qa_ss_const.process_batch_num;
233
234 g_dependency_matrix(30).element_id := qa_ss_const.process_activity;
235 g_dependency_matrix(30).parent := qa_ss_const.process_batch_num;
236
237 g_dependency_matrix(31).element_id := qa_ss_const.process_resource;
238 g_dependency_matrix(31).parent := qa_ss_const.process_batch_num;
239
240 g_dependency_matrix(32).element_id := qa_ss_const.process_parameter;
241 g_dependency_matrix(32).parent := qa_ss_const.process_batch_num;
242 -- R12 OPM Deviations. Bug 4345503 End
243
244 --dgupta: Start R12 EAM Integration. Bug 4345492
245 --Ensure that sequence number (within brackets) is unique when merged
246 g_dependency_matrix(33).element_id := qa_ss_const.asset_instance_number;
247 g_dependency_matrix(33).parent := qa_ss_const.asset_group;
248 --dgupta: End R12 EAM Integration. Bug 4345492
249
250 END populate_dependency_matrix;
251
252
253 FUNCTION flag_is_set (all_flags IN VARCHAR2, flag_in_question IN VARCHAR2)
254 RETURN BOOLEAN IS
255
256 pos NUMBER;
257
258 BEGIN
259
260 IF instr(all_flags, flag_in_question, 1, 1) > 0 THEN
261 RETURN TRUE;
262 ELSE
263 RETURN FALSE;
264 END IF;
265
266 END flag_is_set;
267
268
269 FUNCTION parent (element_id IN NUMBER)
270 RETURN BOOLEAN IS
271
272 BEGIN
273
274 -- Earlier we have populated an array with the elements
275 -- that have least one element dependent on them
276 --
277 -- This PARENT function should simply look through
278 -- this list to and return if that exists
279
280
281 FOR i IN 1..g_dependency_matrix.count LOOP
282
283 IF g_dependency_matrix(i).parent = element_id THEN
284 RETURN TRUE;
285 END IF;
286
287 END LOOP;
288
289 RETURN FALSE;
290
291 END parent;
292
293
294 -- Bug 3397484 ksoh Tue Jan 27 13:54:38 PST 2004
295 -- order ordered_array by prompt_sequence, need to pass plan_id in
296 FUNCTION populate_elements (row_elements IN ElementsArray, p_plan_id IN NUMBER)
297 RETURN ElementInfoArray IS
298
299 i NUMBER;
300 indx NUMBER;
301 ordered_array ElementInfoArray;
302
303 CURSOR c IS
304 select char_id
305 from qa_plan_chars
306 where plan_id = p_plan_id
307 and enabled_flag = 1
308 order by prompt_sequence;
309
310 BEGIN
311
312 -- This function takes the row_elements array that is passed
313 -- by the user of validate_row and copies the ids and validation
314 -- flags to the ordered_array. The ordered_array has continuous
315 -- indexing (e.g. 1,2,3,4..) unlike row_elements which is sparsed
316 -- (e.g. 4, 10, 120)
317
318 -- i := row_elements.FIRST;
319
320 -- ordered_array is being processed from index 1
321
322 -- ordered_array(ordered_array.count).id := 0;
323
324 -- WHILE (i <> row_elements.LAST) LOOP
325 OPEN c;
326 LOOP
327 FETCH c INTO i;
328 EXIT WHEN c%NOTFOUND;
329 indx := ordered_array.count;
330 -- bug 3419514 ksoh Wed Feb 4 12:19:04 PST 2004
331 -- must skip if row_elements(i) does not exist.
332 -- It would not exist for the following case:
333 -- say Quantity is in the history plan
334 -- but not in relationship with the parent plan.
335 -- From qapcb, when we call post_result_with_no_validation,
336 -- we pass only elements in pc history relationship.
337 -- And thus row_elements(i).validation_flag would fail for Quantity
338 -- old check does not cover this case
339 -- IF (i <= row_elements.LAST) THEN
340 IF row_elements.EXISTS(i) THEN
341 ordered_array(indx).id := i;
342 ordered_array(indx).validation_flag := nvl(row_elements(i).validation_flag, 'invalid');
343 END IF;
344 -- i := row_elements.NEXT(i);
345
346 END LOOP;
347
348 -- indx := ordered_array.count;
349 -- ordered_array(indx).id := i;
350 -- ordered_array(indx).validation_flag := nvl(row_elements(i).validation_flag, 'invalid');
351
352 RETURN ordered_array;
353
354 END populate_elements;
355
356
357 FUNCTION direct_child(x IN NUMBER, y IN NUMBER) RETURN BOOLEAN IS
358 --
359 -- Determine if x is a direct child of y. Implemented as simple
360 -- linear lookup.
361 --
362 BEGIN
363
364 FOR i IN 1..g_dependency_matrix.count LOOP
365 IF x = g_dependency_matrix(i).element_id AND
366 y = g_dependency_matrix(i).parent THEN
367 RETURN TRUE;
368 END IF;
369 END LOOP;
370 RETURN FALSE;
371
372 END direct_child;
373
374
375 FUNCTION descendant(x IN NUMBER, y IN NUMBER) RETURN BOOLEAN IS
376 --
377 -- Determine if x is a descendant of y. This is the logic:
378 -- x is a descendant of y either
379 -- 1. x is a direct child or
380 -- 2. x is the child of some z and z is a descendant of y.
381 --
382 BEGIN
383
384 IF direct_child(x, y) THEN
385 RETURN TRUE;
386 END IF;
387
388 FOR i IN 1..g_dependency_matrix.count LOOP
389 IF x = g_dependency_matrix(i).element_id AND
390 descendant(g_dependency_matrix(i).parent, y) THEN
391 RETURN TRUE;
392 END IF;
393 END LOOP;
394
395 RETURN FALSE;
396
397 END descendant;
398
399
400 PROCEDURE pushdown ( position IN NUMBER, element_id IN NUMBER, assorted_array
401 IN OUT NOCOPY ElementInfoArray) IS
402
403 BEGIN
404
405 FOR i IN REVERSE position..assorted_array.count-1 LOOP
406 assorted_array(i+1).id := assorted_array(i).id;
407 END LOOP;
408
409 assorted_array(position).id := element_id;
410
411 END pushdown;
412
413
414 PROCEDURE determine_navigation_order (ordered_array IN OUT
415 NOCOPY ElementInfoArray) IS
416
417 KEY NUMBER;
418 ancestor BOOLEAN;
419
420 assorted_array ElementInfoArray;
421
422 BEGIN
423
424 ancestor := false;
425
426 FOR j IN 0..ordered_array.count-1 LOOP
427
428 IF parent(ordered_array(j).id) THEN
429
430 -- If parent, then check if any of the children is present
431 -- in the already assorted list
432
433 FOR t IN 0..assorted_array.count-1 LOOP
434
435 IF descendant (assorted_array(t).id, ordered_array(j).id) THEN
436 ancestor := TRUE;
437 pushdown(t, ordered_array(j).id, assorted_array);
438 exit;
439 END IF;
440 END LOOP;
441 END IF;
442
443 IF NOT ancestor THEN
444 assorted_array(assorted_array.count).id := ordered_array(j).id;
445 END IF;
446
447 ancestor := FALSE;
448
449 END LOOP;
450
451 FOR q IN 0..assorted_array.count-1 LOOP
452 ordered_array(q).id := assorted_array(q).id;
453 -- dbms_output.put_line(ordered_array(q).id);
454 END LOOP;
455
456 END determine_navigation_order;
457
458
459 PROCEDURE append_errors (element_id IN NUMBER, element_error_list IN
460 ErrorArray, row_error_list IN OUT NOCOPY ErrorArray) IS
461
462 ind NUMBER;
463 i NUMBER;
464
465 BEGIN
466
467 ind := row_error_list.count + 1;
468
469 --
470 -- Bug 5331420
471 -- Corrected small issue with this routine before the above
472 -- bug fix can continue. The indexes for element_error_list
473 -- is not linear, so we should use WHILE loop instead of FOR.
474 -- bso Thu Jun 15 16:22:54 PDT 2006
475 --
476 -- FOR i IN 1..element_error_list.count LOOP
477 --
478
479 i := element_error_list.FIRST;
480 WHILE i IS NOT NULL LOOP
481
482 IF (element_error_list(i).error_code <> ok) THEN
483
484 row_error_list(ind).element_id := element_id;
485 row_error_list(ind).error_code :=
486 element_error_list(i).error_code;
487
488 ind := ind + 1;
489
490 END IF;
491 i := element_error_list.NEXT(i);
492
493 END LOOP;
494
495 END append_errors;
496
497
498 FUNCTION no_errors (error_array IN ErrorArray)
499 RETURN BOOLEAN IS
500
501 BEGIN
502
503
504 FOR i IN 1..error_array.count LOOP
505 IF error_array(i).error_code <> ok THEN
506 RETURN FALSE;
507 END IF;
508 END LOOP;
509
510 RETURN TRUE;
511
512 END no_errors;
513
514
515 FUNCTION validate_enabled (plan_id IN NUMBER, element_id IN NUMBER)
516 RETURN NUMBER IS
517
518 flag NUMBER;
519
520 BEGIN
521
522 flag := qa_plan_element_api.get_enabled_flag(plan_id, element_id);
523
524 IF (flag = 1) THEN
525 RETURN ok;
526 ELSE
527 RETURN not_enabled_error;
528 END IF;
529
530 EXCEPTION
531 WHEN OTHERS THEN
532 RETURN no_data_found_error;
533
534 END validate_enabled;
535
536
537 FUNCTION validate_mandatory_revision (plan_id IN NUMBER,
538 element_id IN NUMBER,
539 value IN NUMBER)
540 RETURN NUMBER IS
541
542 revision_flag NUMBER;
543
544 BEGIN
545
546 IF (element_id = qa_ss_const.revision) THEN
547 revision_flag := g_revision_qty_cntrl_code;
548
549 ELSIF (element_id = qa_ss_const.comp_revision) THEN
550 revision_flag := g_comp_revision_qty_cntrl_code;
551 END IF;
552
553 IF ( revision_flag = 1) and (value is not NULL) THEN
554 return not_revision_controlled_error;
555 END IF;
556
557 IF ( revision_flag = 2) and (value is NULL) THEN
558 return mandatory_revision_error;
559 END IF;
560
561 RETURN ok;
562
563 EXCEPTION
564 WHEN OTHERS THEN
565 RETURN unknown_error;
566
567 END validate_mandatory_revision;
568
569 -- anagarwa Mon Feb 24 17:08:57 PST 2003
570 -- Bug 2808693
571 -- Overloaded method validate_mandatory_revision.
572 -- Here value is of type VARCHAR2 to support data being entered from selfservice
573
574 FUNCTION validate_mandatory_revision (plan_id IN NUMBER,
575 element_id IN NUMBER,
576 value IN VARCHAR2)
577 RETURN NUMBER IS
578
579 revision_flag NUMBER;
580
581 BEGIN
582
583 IF (element_id = qa_ss_const.revision) THEN
584 revision_flag := g_revision_qty_cntrl_code;
585
586 ELSIF (element_id = qa_ss_const.comp_revision) THEN
587 revision_flag := g_comp_revision_qty_cntrl_code;
588 END IF;
589
590 IF ( revision_flag = 1) and (value is not NULL) THEN
591 return not_revision_controlled_error;
592 END IF;
593
594 IF ( revision_flag = 2) and (value is NULL) THEN
595 return mandatory_revision_error;
596 END IF;
597
598 RETURN ok;
599
600 EXCEPTION
601 WHEN OTHERS THEN
602 RETURN unknown_error;
603
604 END validate_mandatory_revision;
605
606
607 FUNCTION validate_mandatory_locator (plan_id IN NUMBER,
608 element_id IN NUMBER,
609 value IN NUMBER)
610 RETURN NUMBER IS
611
612 BEGIN
613
614 --
615 -- delay mandatory validation until we validate
616 -- the locator keyflex
617 --
618
619 RETURN ok;
620
621 END validate_mandatory_locator;
622
623
624 -- The Function validate_mandatory_locator has been overloaded.
625 -- The overloading is required because History record insert procedure
626 -- is called by Parent child call, locator values is passed as locator
627 -- name (like 6.6.6..)and not as locator_id.
628 -- Bug 2700230.suramasw Mon Dec 23 03:06:30 PST 2002.
629
630 FUNCTION validate_mandatory_locator (plan_id IN NUMBER,
631 element_id IN NUMBER,
632 value IN VARCHAR2)
633 RETURN NUMBER IS
634
635 BEGIN
636
637 --
638 -- delay mandatory validation until we validate
639 -- the locator keyflex
640 --
641
642 RETURN ok;
643
644 END validate_mandatory_locator;
645
646
647 FUNCTION validate_mandatory (row_record IN RowRecord, element_id IN NUMBER,
648 value IN VARCHAR2)
649 RETURN NUMBER IS
650
651 element_name VARCHAR2(240);
652 m_flag NUMBER;
653
654 BEGIN
655
656 IF (element_id = qa_ss_const.revision) or
657 (element_id = qa_ss_const.comp_revision) THEN
658
659 RETURN validate_mandatory_revision(row_record.plan_id, element_id,
660 value);
661
662 END IF;
663
664 -- Modified the code below to enable History Records to be created
665 -- when History Relationship is present.
666 -- Bug 2700230.suramasw Mon Dec 23 03:06:30 PST 2002.
667
668 /*
669 IF (element_id = qa_ss_const.locator) or
670 (element_name = qa_ss_const.comp_locator) THEN
671 */
672
673 IF (element_id IN( qa_ss_const.locator,qa_ss_const.to_locator,
674 qa_ss_const.comp_locator)) THEN
675
676 RETURN validate_mandatory_locator(row_record.plan_id, element_id,
677 value);
678 END IF;
679
680
681 m_flag := qa_plan_element_api.get_mandatory_flag(row_record.plan_id,
682 element_id);
683
684 IF ( (m_flag = 2) or (value IS NOT NULL) ) THEN
685 RETURN ok;
686 END IF;
687
688 RETURN mandatory_error;
689
690 EXCEPTION
691 WHEN OTHERS THEN
692 RETURN no_data_found_error;
693
694 END validate_mandatory;
695
696
697 FUNCTION validate_kf_item (row_elements IN ElementsArray,
698 row_record IN RowRecord, element_id IN NUMBER, value IN VARCHAR2,
699 result_holder IN OUT NOCOPY ResultRecord)
700 RETURN NUMBER IS
701
702 id NUMBER;
703 error_code NUMBER;
704 x_where_clause VARCHAR2(500);
705
706 CURSOR c2 (i_id NUMBER, o_id NUMBER) IS
707 select restrict_subinventories_code, restrict_locators_code,
708 location_control_code, revision_qty_control_code
709 from mtl_system_items
710 where inventory_item_id = i_id
711 and organization_id = o_id;
712
713 BEGIN
714 IF (value is NULL) THEN
715 RETURN ok;
716 END IF;
717
718 -- Bug 3593287
719 --
720 -- Item validation needs to be revised. The original
721 -- implementation was not correct. The subsequent bug
722 -- fix 3506231 is also not correct, introducing new bug
723 -- 3593287. The proper design is this
724 --
725 -- if Production Line is in plan and is not null then
726 -- we should restrict item further by wip production line
727 -- or flow production line
728 --
729 -- This is an exact rephrase from QLTRES mimicing the Forms
730 -- validation logic. Nowhere do we involve sales order line.
731 --
732 -- In addition, we want to make absolutely certain that
733 -- Bug 3506231 does not recur. To prevent that always
734 -- check row_elements.exists(i) before accessing
735 -- row_elements(i).value
736 --
737 -- bso Mon Apr 26 18:15:10 PDT 2004
738 --
739 -- original comment now obsolete:
740 -- if production line is in the plan then
741 -- if so line number is in the plan then
742 -- if the vlaue for so line number is NULL then
743 -- x_where_clause := NULL;
744 --
745
746 IF (qa_plan_element_api.element_in_plan(row_record.plan_id,
747 qa_ss_const.production_line) AND
748 row_elements.exists(qa_ss_const.production_line) AND
749 row_elements(qa_ss_const.production_line).value IS NOT NULL) THEN
750
751 x_where_clause :=
752 'inventory_item_id IN ' ||
753 '((SELECT primary_item_id ' ||
754 'FROM wip_repetitive_items_v ' ||
755 'WHERE organization_id = ' || g_org_id || ' AND ' ||
756 'line_code = ''' ||
757 row_elements(qa_ss_const.production_line).value ||
758 ''') ' ||
759 'UNION ALL ' ||
760 '(SELECT assembly_item_id '||
761 'FROM bom_operational_routings_v '||
762 'WHERE organization_id = ' || g_org_id || ' AND ' ||
763 'line_code = ''' ||
764 row_elements(qa_ss_const.production_line).value ||
765 '''))';
766
767 ELSE
768 x_where_clause := NULL;
769 END IF;
770
771 IF (
772 FND_FLEX_KEYVAL.validate_segs(
773 operation => 'CHECK_COMBINATION',
774 key_flex_code => 'MSTK',
775 appl_short_name => 'INV',
776 structure_number => '101',
777 concat_segments => value,
778 data_set => g_org_id,
779 where_clause => x_where_clause)) THEN
780
781 id := FND_FLEX_KEYVAL.combination_id;
782
783 IF (id = 0) THEN
784 RETURN item_keyflex_error;
785 END IF;
786
787 OPEN c2 (id, g_org_id);
788 FETCH c2 INTO g_restrict_subinv_code, g_restrict_locators_code,
789 g_location_control_code, g_revision_qty_cntrl_code;
790 CLOSE c2;
791
792 result_holder.id := id;
793 g_item_id := id;
794
795 RETURN ok;
796
797 ELSE
798 RETURN item_keyflex_error;
799
800 -- NEED FURTHER WORK: FND_FLEX_KEYVAL.error_message
801
802 END IF;
803
804 EXCEPTION
805 WHEN OTHERS THEN
806 RETURN item_keyflex_error;
807
808 END validate_kf_item;
809
810 -- Bug 5248191. Wrote a new method to validate Asset Group
811 -- as Asset Group may be in production/maintenance org.
812 -- saugupta Wed, 02 Aug 2006 01:42:09 -0700 PDT
813 FUNCTION validate_kf_asset_group (row_elements IN ElementsArray,
814 row_record IN RowRecord, element_id IN NUMBER, value IN VARCHAR2,
815 result_holder IN OUT NOCOPY ResultRecord)
816 RETURN NUMBER IS
817
818 id NUMBER;
819 error_code NUMBER;
820 x_where_clause VARCHAR2(500);
821
822 CURSOR c2 (i_value VARCHAR2, o_id NUMBER) IS
823 SELECT restrict_subinventories_code, restrict_locators_code,
824 location_control_code, revision_qty_control_code,inventory_item_id
825 FROM mtl_system_items_kfv msi, mtl_parameters mp
826 WHERE msi.concatenated_segments = i_value
827 AND msi.organization_id = mp.organization_id
828 AND mp.maint_organization_id = o_id
829 AND rownum = 1;
830 BEGIN
831
832 IF (value is NULL) THEN
833 RETURN ok;
834 END IF;
835
836 OPEN c2 (value, g_org_id);
837 FETCH c2 INTO g_restrict_subinv_code, g_restrict_locators_code,
838 g_location_control_code, g_revision_qty_cntrl_code,id;
839 IF c2%NOTFOUND THEN
840 CLOSE c2;
841 RETURN item_keyflex_error;
842 END IF;
843 CLOSE c2;
844
845 result_holder.id := id;
846 g_item_id := id;
847
848 RETURN ok;
849
850 EXCEPTION
851 WHEN OTHERS THEN
852 RETURN item_keyflex_error;
853 END validate_kf_asset_group;
854
855 FUNCTION validate_kf_comp_item (row_elements IN ElementsArray, row_record IN
856 RowRecord, element_id IN NUMBER, value IN VARCHAR2, result_holder IN OUT
857 NOCOPY ResultRecord)
858 RETURN NUMBER IS
859
860 id NUMBER;
861 error_code NUMBER;
862 x_where_clause VARCHAR2(500);
863
864 CURSOR c2 (i_id NUMBER, o_id NUMBER) IS
865 select restrict_subinventories_code, restrict_locators_code,
866 location_control_code, revision_qty_control_code
867 from mtl_system_items
868 where inventory_item_id = i_id
869 and organization_id = o_id;
870
871 BEGIN
872
873 IF (value is NULL) THEN
874 RETURN ok;
875 END IF;
876
877 -- Bug 3506231.suramasw.
878 -- Bug 3593287
879 --
880 -- A large chunk of code is removed due to error in
881 -- initial implementation. See validate_kf_item for more
882 -- info. For Component Item, we will use a simple relaxed
883 -- validation. Since the validation API is not being used
884 -- as LOV, it will suffice to give a relaxed superset
885 -- validation instead of a very accurate one. See QLTRES
886 -- for precise comp item LOV conditions which is dependent
887 -- on either WIP or BOM depending on what elements are
888 -- present in the plan.
889 --
890 -- bso Mon Apr 26 19:56:05 PDT 2004
891 --
892 -- x_where_clause := NULL;
893
894 IF (
895 FND_FLEX_KEYVAL.validate_segs(
896 operation => 'CHECK_COMBINATION',
897 key_flex_code => 'MSTK',
898 appl_short_name => 'INV',
899 structure_number => '101',
900 concat_segments => value,
901 data_set => g_org_id,
902 where_clause => x_where_clause)) THEN
903
904 id := FND_FLEX_KEYVAL.combination_id;
905
906 IF (id = 0) THEN
907 RETURN comp_item_keyflex_error;
908 END IF;
909
910 OPEN c2 (id, g_org_id);
911 FETCH c2 INTO g_comp_restrict_subinv_code,
912 g_comp_restrict_locators_code, g_comp_location_control_code,
913 g_comp_revision_qty_cntrl_code;
914 CLOSE c2;
915
916 result_holder.id := id;
917 g_comp_item_id := id;
918
919 RETURN ok;
920
921 ELSE
922 RETURN comp_item_keyflex_error;
923
924 -- NEED FURTHER WORK: FND_FLEX_KEYVAL.error_message
925
926 END IF;
927
928 EXCEPTION
929 WHEN OTHERS THEN
930 RETURN comp_item_keyflex_error;
931
932 END validate_kf_comp_item;
933
934
935 FUNCTION validate_kf_locator (row_elements IN ElementsArray, row_record IN
936 RowRecord, element_id IN NUMBER, value IN VARCHAR2, result_holder IN OUT
937 NOCOPY ResultRecord)
938 RETURN NUMBER IS
939
940 error_code NUMBER;
941 stock_locator NUMBER;
942 negative_inv NUMBER;
943 locator_type NUMBER;
944 locator_flag NUMBER;
945 mandatory_flag NUMBER;
946 id NUMBER;
947 x_where_clause VARCHAR2(500);
948
949 CURSOR C1 (org_id NUMBER) IS
950 select stock_locator_control_code, negative_inv_receipt_code
951 from mtl_parameters
952 where organization_id = org_id;
953
954
955 -- Bug 3381173. The cursor C2 was based on the view mtl_subinventories_val_v,
956 -- which is only for storage subs. Based the cursor on mtl_secondary_inventories
957 -- and added the where clause to differentiate receiving subs.
958 -- kabalakr Tue Jan 27 02:18:59 PST 2004.
959
960 CURSOR C2 (org_id NUMBER) IS
961 select locator_type
962 FROM mtl_secondary_inventories
963 WHERE organization_id = org_id
964 AND ((((SUBINVENTORY_TYPE <> 2) OR (SUBINVENTORY_TYPE IS NULL))
965 AND nvl(disable_date, sysdate+1) > sysdate)
966 OR (SUBINVENTORY_TYPE = 2))
967 AND secondary_inventory_name = g_subinventory;
968
969 /*
970 CURSOR C2 (org_id NUMBER) IS
971 select locator_type
972 from mtl_subinventories_val_v
973 where organization_id = org_id
974 and secondary_inventory_name = g_subinventory;
975 */
976
977 BEGIN
978
979 OPEN C1(g_org_id);
980 FETCH C1 INTO stock_locator, negative_inv;
981 CLOSE C1;
982
983 OPEN C2(g_org_id);
984 FETCH C2 INTO locator_type;
985 CLOSE C2;
986
987 locator_flag := qltinvcb.control(org_control => stock_locator,
988 sub_control => locator_type,
989 item_control => g_location_control_code,
990 restrict_flag => g_restrict_locators_code,
991 neg_flag => negative_inv);
992
993 IF locator_flag = 1 THEN
994 IF value IS NULL THEN
995 RETURN ok;
996 ELSE
997 RETURN not_locator_controlled_error;
998 END IF;
999 END IF;
1000
1001 mandatory_flag := qa_plan_element_api.get_mandatory_flag(
1002 row_record.plan_id, element_id);
1003
1004 IF ( (mandatory_flag = 1) and (value IS NULL) ) THEN
1005
1006 IF NOT flag_is_set(row_elements(element_id).validation_flag,
1007 background_element)
1008 AND NOT flag_is_set(row_elements(element_id).validation_flag,
1009 valid_element) THEN
1010 RETURN mandatory_error;
1011 ELSE
1012 RETURN ok;
1013 END IF;
1014 END IF;
1015
1016 IF locator_flag = 2 THEN
1017
1018 IF g_restrict_locators_code = 1 THEN
1019 x_where_clause := '(disable_date > sysdate or disable_date is null)
1020 and subinventory_code = ' ||
1021 '''' || g_subinventory || '''' ||
1022 ' and inventory_location_id in
1023 (select secondary_locator
1024 from mtl_secondary_locators
1025 where inventory_item_id = g_item_id and
1026 organization_id = ' ||
1027 '''' || g_org_id || '''' ||
1028 ' and subinventory_code = ' ||
1029 '''' || g_subinventory || '''' || '))';
1030
1031 ELSIF g_restrict_locators_code = 2 THEN
1032 x_where_clause := '(disable_date > sysdate or disable_date is null)
1033 and subinventory_code = ' ||
1034 '''' || g_subinventory || '''';
1035
1036 ELSE
1037 x_where_clause := null;
1038
1039 END IF;
1040
1041 IF (
1042 FND_FLEX_KEYVAL.validate_segs(
1043 operation => 'CHECK_COMBINATION',
1044 appl_short_name => 'INV',
1045 key_flex_code => 'MTLL',
1046 structure_number => '101',
1047 concat_segments => value,
1048 values_or_ids => 'V',
1049 data_set => g_org_id,
1050 where_clause => x_where_clause)) THEN
1051
1052 id := FND_FLEX_KEYVAL.combination_id;
1053 END IF;
1054 END IF;
1055
1056 IF locator_flag = 3 THEN
1057 IF (
1058 FND_FLEX_KEYVAL.validate_segs(
1059 operation => 'CREATE_COMBINATION',
1060 appl_short_name => 'INV',
1061 key_flex_code => 'MTLL',
1062 structure_number => '101',
1063 concat_segments => value,
1064 values_or_ids => 'V',
1065 data_set => g_org_id,
1066 where_clause => x_where_clause)) THEN
1067
1068 id := FND_FLEX_KEYVAL.combination_id;
1069 END IF;
1070
1071 END IF;
1072
1073 IF (id = 0) THEN
1074 RETURN locator_keyflex_error;
1075 END IF;
1076
1077 result_holder.id := id;
1078
1079 RETURN ok;
1080
1081 EXCEPTION
1082 WHEN OTHERS THEN
1083 RETURN locator_keyflex_error;
1084
1085 END validate_kf_locator;
1086
1087
1088 FUNCTION validate_kf_comp_locator (row_elements IN ElementsArray, row_record
1089 IN RowRecord, element_id IN NUMBER, value IN VARCHAR2, result_holder IN
1090 OUT NOCOPY ResultRecord)
1091 RETURN NUMBER IS
1092
1093 error_code NUMBER;
1094 stock_locator NUMBER;
1095 negative_inv NUMBER;
1096 locator_type NUMBER;
1097 locator_flag NUMBER;
1098 mandatory_flag NUMBER;
1099 id NUMBER;
1100 x_where_clause VARCHAR2(500);
1101
1102 CURSOR C1 (org_id NUMBER) IS
1103 select stock_locator_control_code, negative_inv_receipt_code
1104 from mtl_parameters
1105 where organization_id = org_id;
1106
1107 --
1108 -- Bug 6126260
1109 -- In the where clause replaced g_subinventory
1110 -- with g_comp_subinventory for getting locator type
1111 -- for the component subinventory
1112 -- bhsankar Mon Jul 16 05:51:51 PDT 2007
1113 --
1114 CURSOR C2 (org_id NUMBER) IS
1115 select locator_type
1116 from mtl_subinventories_val_v
1117 where organization_id = org_id
1118 and secondary_inventory_name = g_comp_subinventory;
1119
1120 BEGIN
1121
1122 OPEN C1(g_org_id);
1123 FETCH C1 INTO stock_locator, negative_inv;
1124 CLOSE C1;
1125
1126 OPEN C2(g_org_id);
1127 FETCH C2 INTO locator_type;
1128 CLOSE C2;
1129
1130 locator_flag := qltinvcb.control(
1131 org_control => stock_locator,
1132 sub_control => locator_type,
1133 item_control => g_comp_location_control_code,
1134 restrict_flag => g_comp_restrict_locators_code,
1135 neg_flag => negative_inv);
1136
1137 IF locator_flag = 1 THEN
1138 IF value IS NULL THEN
1139 RETURN ok;
1140 ELSE
1141 RETURN not_locator_controlled_error;
1142 END IF;
1143 END IF;
1144
1145 mandatory_flag := qa_plan_element_api.get_mandatory_flag(
1146 row_record.plan_id, element_id);
1147
1148 IF ( (mandatory_flag = 1) and (value IS NULL) ) THEN
1149 RETURN mandatory_error;
1150 END IF;
1151
1152 IF locator_flag = 2 THEN
1153 --
1154 -- Bug 6126260
1155 -- In the where clause replaced g_subinventory
1156 -- with g_comp_subinventory for getting locator type
1157 -- for the component subinventory
1158 -- bhsankar Mon Jul 16 05:51:51 PDT 2007
1159 --
1160 IF g_restrict_locators_code = 1 THEN
1161 x_where_clause := '(disable_date > sysdate or disable_date is null)
1162 and subinventory_code = ' ||
1163 '''' || g_comp_subinventory || '''' ||
1164 ' and inventory_location_id in
1165 (select secondary_locator
1166 from mtl_secondary_locators
1167 where inventory_item_id = x_item_id and
1168 organization_id = ' ||
1169 '''' || g_org_id || '''' ||
1170 ' and subinventory_code = ' ||
1171 '''' || g_comp_subinventory || '''' || '))';
1172
1173 ELSIF g_restrict_locators_code = 2 THEN
1174 x_where_clause := '(disable_date > sysdate or disable_date is null)
1175 and subinventory_code = ' ||
1176 '''' || g_comp_subinventory || '''';
1177
1178 ELSE
1179 x_where_clause := null;
1180
1181 END IF;
1182
1183 IF (
1184 FND_FLEX_KEYVAL.validate_segs(
1185 operation => 'CHECK_COMBINATION',
1186 appl_short_name => 'INV',
1187 key_flex_code => 'MTLL',
1188 structure_number => '101',
1189 concat_segments => value,
1190 values_or_ids => 'V',
1191 data_set => g_org_id,
1192 where_clause => x_where_clause)) THEN
1193
1194 id := FND_FLEX_KEYVAL.combination_id;
1195 END IF;
1196 END IF;
1197
1198 IF locator_flag = 3 THEN
1199 IF (
1200 FND_FLEX_KEYVAL.validate_segs(
1201 operation => 'CREATE_COMBINATION',
1202 appl_short_name => 'INV',
1203 key_flex_code => 'MTLL',
1204 structure_number => '101',
1205 concat_segments => value,
1206 values_or_ids => 'V',
1207 data_set => g_org_id,
1208 where_clause => x_where_clause)) THEN
1209
1210 id := FND_FLEX_KEYVAL.combination_id;
1211 END IF;
1212
1213 END IF;
1214
1215 IF (id = 0) THEN
1216 RETURN comp_locator_keyflex_error;
1217 END IF;
1218
1219 result_holder.id := id;
1220
1221 RETURN ok;
1222
1223 EXCEPTION
1224 WHEN OTHERS THEN
1225 RETURN comp_locator_keyflex_error;
1226
1227 END validate_kf_comp_locator;
1228
1229 -- Start of inclusions for NCM Hardcode Elements.
1230 -- suramasw Thu Oct 31 10:48:59 PST 2002.
1231 -- Bug 2449067.
1232
1233 FUNCTION validate_kf_bill_reference (row_elements IN ElementsArray,
1234 row_record IN RowRecord, element_id IN NUMBER, value IN VARCHAR2,
1235 result_holder IN OUT NOCOPY ResultRecord)
1236 RETURN NUMBER IS
1237
1238 id NUMBER;
1239 error_code NUMBER;
1240 x_where_clause VARCHAR2(240) := NULL;
1241
1242 CURSOR c2 (i_id NUMBER, o_id NUMBER) IS
1243 select restrict_subinventories_code, restrict_locators_code,
1244 location_control_code, revision_qty_control_code
1245 from mtl_system_items
1246 where inventory_item_id = i_id
1247 and organization_id = o_id;
1248
1249 BEGIN
1250
1251 IF (value is NULL) THEN
1252 RETURN ok;
1253 END IF;
1254
1255 IF (
1256 FND_FLEX_KEYVAL.validate_segs(
1257 operation => 'CHECK_COMBINATION',
1258 key_flex_code => 'MSTK',
1259 appl_short_name => 'INV',
1260 structure_number => '101',
1261 concat_segments => value,
1262 data_set => g_org_id,
1263 where_clause => x_where_clause)) THEN
1264
1265 id := FND_FLEX_KEYVAL.combination_id;
1266
1267 IF (id = 0) THEN
1268 RETURN bill_reference_keyflex_error;
1269 END IF;
1270
1271 OPEN c2 (id, g_org_id);
1272 FETCH c2 INTO g_bill_restrict_subinv_code, g_bill_restrict_locators_code,
1273 g_bill_location_control_code, g_bill_revision_qty_cntrl_code;
1274 CLOSE c2;
1275
1276 result_holder.id := id;
1277 g_bill_reference_id := id;
1278
1279 RETURN ok;
1280
1281 ELSE
1282 RETURN bill_reference_keyflex_error;
1283
1284 -- NEED FURTHER WORK: FND_FLEX_KEYVAL.error_message
1285
1286 END IF;
1287 EXCEPTION
1288 WHEN OTHERS THEN
1289 RETURN bill_reference_keyflex_error;
1290
1291 END validate_kf_bill_reference;
1292
1293
1294
1295 FUNCTION validate_kf_routing_reference (row_elements IN ElementsArray,
1296 row_record IN RowRecord, element_id IN NUMBER, value IN VARCHAR2,
1297 result_holder IN OUT NOCOPY ResultRecord)
1298 RETURN NUMBER IS
1299
1300 id NUMBER;
1301 error_code NUMBER;
1302 x_where_clause VARCHAR2(240) := NULL;
1303
1304 CURSOR c2 (i_id NUMBER, o_id NUMBER) IS
1305 select restrict_subinventories_code, restrict_locators_code,
1306 location_control_code, revision_qty_control_code
1307 from mtl_system_items
1308 where inventory_item_id = i_id
1309 and organization_id = o_id;
1310
1311 BEGIN
1312
1313 IF (value is NULL) THEN
1314 RETURN ok;
1315 END IF;
1316
1317 IF (
1318 FND_FLEX_KEYVAL.validate_segs(
1319 operation => 'CHECK_COMBINATION',
1320 key_flex_code => 'MSTK',
1321 appl_short_name => 'INV',
1322 structure_number => '101',
1323 concat_segments => value,
1324 data_set => g_org_id,
1325 where_clause => x_where_clause)) THEN
1326
1327 id := FND_FLEX_KEYVAL.combination_id;
1328
1329 IF (id = 0) THEN
1330 RETURN rtg_reference_keyflex_error;
1331 END IF;
1332
1333 OPEN c2 (id, g_org_id);
1334 FETCH c2 INTO g_rout_restrict_subinv_code, g_rout_restrict_locators_code,
1335 g_rout_location_control_code, g_rout_revision_qty_cntrl_code;
1336 CLOSE c2;
1337
1338 result_holder.id := id;
1339 g_routing_reference_id := id;
1340
1341 RETURN ok;
1342 ELSE
1343 RETURN rtg_reference_keyflex_error;
1344
1345 -- NEED FURTHER WORK: FND_FLEX_KEYVAL.error_message
1346
1347 END IF;
1348
1349 EXCEPTION
1350 WHEN OTHERS THEN
1351 RETURN rtg_reference_keyflex_error;
1352
1353 END validate_kf_routing_reference;
1354
1355
1356 FUNCTION validate_kf_to_locator (row_elements IN ElementsArray, row_record IN
1357 RowRecord, element_id IN NUMBER, value IN VARCHAR2, result_holder IN OUT
1358 NOCOPY ResultRecord)
1359 RETURN NUMBER IS
1360
1361 error_code NUMBER;
1362 stock_locator NUMBER;
1363 negative_inv NUMBER;
1364 locator_type NUMBER;
1365 locator_flag NUMBER;
1366 mandatory_flag NUMBER;
1367 id NUMBER;
1368 x_where_clause VARCHAR2(500);
1369
1370 CURSOR C1 (org_id NUMBER) IS
1371 select stock_locator_control_code, negative_inv_receipt_code
1372 from mtl_parameters
1373 where organization_id = org_id;
1374
1375 CURSOR C2 (org_id NUMBER) IS
1376 select locator_type
1377 from mtl_subinventories_val_v
1378 where organization_id = org_id
1379 and secondary_inventory_name = g_to_subinventory;
1380
1381
1382 BEGIN
1383
1384 OPEN C1(g_org_id);
1385 FETCH C1 INTO stock_locator, negative_inv;
1386 CLOSE C1;
1387
1388 OPEN C2(g_org_id);
1389 FETCH C2 INTO locator_type;
1390 CLOSE C2;
1391
1392 locator_flag := qltinvcb.control(org_control => stock_locator,
1393 sub_control => locator_type,
1394 item_control => g_location_control_code,
1395 restrict_flag => g_restrict_locators_code,
1396 neg_flag => negative_inv);
1397
1398 IF locator_flag = 1 THEN
1399 IF value IS NULL THEN
1400 RETURN ok;
1401 ELSE
1402 RETURN not_locator_controlled_error;
1403 END IF;
1404 END IF;
1405
1406 mandatory_flag := qa_plan_element_api.get_mandatory_flag(
1407 row_record.plan_id, element_id);
1408
1409 IF ( (mandatory_flag = 1) and (value IS NULL) ) THEN
1410
1411 IF NOT flag_is_set(row_elements(element_id).validation_flag,
1412 background_element)
1413 AND NOT flag_is_set(row_elements(element_id).validation_flag,
1414 valid_element) THEN
1415 RETURN mandatory_error;
1416 ELSE
1417 RETURN ok;
1418 END IF;
1419 END IF;
1420
1421 IF locator_flag = 2 THEN
1422
1423 IF g_restrict_locators_code = 1 THEN
1424 x_where_clause := '(disable_date > sysdate or disable_date is null)
1425 and subinventory_code = ' ||
1426 '''' || g_to_subinventory || '''' ||
1427 ' and inventory_location_id in
1428 (select secondary_locator
1429 from mtl_secondary_locators
1430 where inventory_item_id = g_item_id and
1431 organization_id = ' ||
1432 '''' || g_org_id || '''' ||
1433 ' and subinventory_code = ' ||
1434 '''' || g_to_subinventory || '''' || '))';
1435
1436 ELSIF g_restrict_locators_code = 2 THEN
1437 x_where_clause := '(disable_date > sysdate or disable_date is null)
1438 and subinventory_code = ' ||
1439 '''' || g_to_subinventory || '''';
1440
1441 ELSE
1442 x_where_clause := null;
1443
1444 END IF;
1445
1446 IF (
1447 FND_FLEX_KEYVAL.validate_segs(
1448 operation => 'CHECK_COMBINATION',
1449 appl_short_name => 'INV',
1450 key_flex_code => 'MTLL',
1451 structure_number => '101',
1452 concat_segments => value,
1453 values_or_ids => 'V',
1454 data_set => g_org_id,
1455 where_clause => x_where_clause)) THEN
1456
1457 id := FND_FLEX_KEYVAL.combination_id;
1458 END IF;
1459 END IF;
1460
1461 IF locator_flag = 3 THEN
1462 IF (
1463 FND_FLEX_KEYVAL.validate_segs(
1464 operation => 'CREATE_COMBINATION',
1465 appl_short_name => 'INV',
1466 key_flex_code => 'MTLL',
1467 structure_number => '101',
1468 concat_segments => value,
1469 values_or_ids => 'V',
1470 data_set => g_org_id,
1471 where_clause => x_where_clause)) THEN
1472
1473 id := FND_FLEX_KEYVAL.combination_id;
1474 END IF;
1475
1476 END IF;
1477
1478 IF (id = 0) THEN
1479 RETURN to_locator_keyflex_error;
1480 END IF;
1481
1482 result_holder.id := id;
1483
1484 RETURN ok;
1485
1486 EXCEPTION
1487 WHEN OTHERS THEN
1488 RETURN to_locator_keyflex_error;
1489
1490 END validate_kf_to_locator;
1491
1492 -- End of inclusions for NCM Hardcode Elements.
1493
1494
1495
1496 FUNCTION validate_keyflex (row_elements IN ElementsArray,
1497 row_record IN RowRecord, element_id IN NUMBER, value IN VARCHAR2,
1498 result_holder IN OUT NOCOPY ResultRecord)
1499 RETURN NUMBER IS
1500
1501 error_code NUMBER;
1502
1503 BEGIN
1504 IF flag_is_set( row_elements(element_id).validation_flag, id_derived) THEN
1505 result_holder.id := row_elements(element_id).id;
1506
1507 -- added the following to include new hardcoded element followup activity
1508 -- saugupta
1509
1510 IF element_id IN (qa_ss_const.item, qa_ss_const.comp_item,
1511 qa_ss_const.asset_group, qa_ss_const.asset_activity, qa_ss_const.followup_activity) THEN
1512 g_item_id := row_elements(element_id).id;
1513 END IF;
1514
1515 ELSIF (element_id = qa_ss_const.item) THEN
1516 error_code := validate_kf_item(row_elements, row_record, element_id,
1517 value, result_holder);
1518
1519 ELSIF (element_id = qa_ss_const.comp_item) THEN
1520 error_code := validate_kf_comp_item(row_elements, row_record,
1521 element_id, value, result_holder);
1522
1523 ELSIF (element_id = qa_ss_const.locator) THEN
1524 error_code := validate_kf_locator(row_elements, row_record, element_id,
1525 value, result_holder);
1526
1527 ELSIF (element_id = qa_ss_const.comp_locator) THEN
1528 error_code := validate_kf_comp_locator(row_elements, row_record,
1529 element_id, value, result_holder);
1530
1531 -- Bug 5248191. Modified check for Asset Group to call new function
1532 -- saugupta Wed, 02 Aug 2006 01:44:07 -0700 PDT
1533 ELSIF (element_id = qa_ss_const.asset_group) THEN
1534 error_code := validate_kf_asset_group(row_elements, row_record,
1535 element_id, value, result_holder);
1536
1537 ELSIF (element_id = qa_ss_const.asset_activity) THEN
1538 error_code := validate_kf_item(row_elements, row_record,
1539 element_id, value, result_holder);
1540
1541 -- added the following to include new hardcoded element followup activity
1542 -- saugupta
1543
1544 ELSIF (element_id = qa_ss_const.followup_activity) THEN
1545 error_code := validate_kf_item(row_elements, row_record,
1546 element_id, value, result_holder);
1547
1548
1549 -- Added the following for NCM Hardcode Elements.
1550 -- suramasw Thu Oct 31 10:48:59 PST 2002.
1551 -- Bug 2449067.
1552
1553 ELSIF (element_id = qa_ss_const.bill_reference) THEN
1554 error_code := validate_kf_bill_reference(row_elements, row_record,
1555 element_id, value, result_holder);
1556
1557 ELSIF (element_id = qa_ss_const.routing_reference) THEN
1558 error_code := validate_kf_routing_reference(row_elements, row_record,
1559 element_id, value, result_holder);
1560
1561 ELSIF (element_id = qa_ss_const.to_locator) THEN
1562 error_code := validate_kf_to_locator(row_elements, row_record,
1563 element_id, value, result_holder);
1564
1565 -- End of inclusions for NCM Hardcode Elements.
1566
1567
1568 END IF;
1569
1570 RETURN error_code;
1571
1572 EXCEPTION
1573 WHEN OTHERS THEN
1574 RETURN keyflex_error;
1575
1576 END validate_keyflex;
1577
1578 --
1579 -- Added to the IF-ELSIF ladder for newly added collection elements
1580 -- for ASO project. New entries are appended after Party_Name
1581 -- rkunchal Thu Jul 25 01:43:48 PDT 2002
1582 --
1583
1584 FUNCTION get_normalized_id (element_id IN NUMBER, value IN VARCHAR2, x_org_id
1585 IN NUMBER)
1586 RETURN NUMBER IS
1587
1588 id NUMBER;
1589
1590 BEGIN
1591
1592 IF (element_id = qa_ss_const.department)
1593 OR (element_id = qa_ss_const.to_department) THEN
1594 id := qa_plan_element_api.get_department_id(x_org_id, value);
1595
1596 ELSIF (element_id = qa_ss_const.job_name) THEN
1597 id := qa_plan_element_api.get_job_id(x_org_id, value);
1598
1599 ELSIF (element_id = qa_ss_const.production_line) THEN
1600 id := qa_plan_element_api.get_production_line_id(x_org_id, value);
1601
1602 ELSIF (element_id = qa_ss_const.resource_code) THEN
1603 id := qa_plan_element_api.get_resource_code_id(x_org_id, value);
1604
1605 ELSIF (element_id = qa_ss_const.vendor_name) THEN
1606 id := qa_plan_element_api.get_supplier_id(value);
1607
1608 ELSIF (element_id = qa_ss_const.po_number) THEN
1609 id := qa_plan_element_api.get_po_number_id(value);
1610
1611 ELSIF (element_id = qa_ss_const.customer_name) THEN
1612 id := qa_plan_element_api.get_customer_id(value);
1613
1614 ELSIF (element_id = qa_ss_const.sales_order) THEN
1615 id := qa_plan_element_api.get_so_number_id(value);
1616
1617 -- bug 16214422
1618 g_sales_order_id := id;
1619
1620 ELSIF (element_id = qa_ss_const.order_line) THEN
1621 -- bug 16214422
1622 -- Get the SO line id based on the SO header Id as well
1623 --
1624 --id := qa_plan_element_api.get_so_line_number_id(value);
1625 id := qa_plan_element_api.get_so_line_number_id(value, g_sales_order_id);
1626
1627 ELSIF (element_id = qa_ss_const.po_release_num) THEN
1628 id := qa_plan_element_api.get_po_release_number_id(value,
1629 g_po_header_id);
1630
1631 ELSIF (element_id = qa_ss_const.project_number) THEN
1632 id := qa_plan_element_api.get_project_number_id(value);
1633 --
1634 -- Bug 2672396. Need to keep a cache of the returned project ID
1635 -- bso Mon Nov 25 17:29:56 PST 2002
1636 --
1637 g_project_id := id;
1638
1639 ELSIF (element_id = qa_ss_const.task_number) THEN
1640 --
1641 -- Bug 2672396. Added g_project_id because task is a dependent element.
1642 -- bso Mon Nov 25 17:29:56 PST 2002
1643 --
1644 id := qa_plan_element_api.get_task_number_id(value, g_project_id);
1645
1646 ELSIF (element_id = qa_ss_const.rma_number) THEN
1647 id := qa_plan_element_api.get_rma_number_id(value);
1648
1649 ELSIF (element_id = qa_ss_const.license_plate_number) THEN
1650 id := qa_plan_element_api.get_lpn_id(value);
1651
1652 -- added the following to include new hardcoded element Transfer license plate number
1653 -- saugupta
1654
1655 ELSIF (element_id = qa_ss_const.xfr_license_plate_number) THEN
1656 id := qa_plan_element_api.get_xfr_lpn_id(value);
1657
1658
1659 ELSIF (element_id = qa_ss_const.contract_number) THEN
1660 id := qa_plan_element_api.get_contract_id(value);
1661
1662 ELSIF (element_id = qa_ss_const.contract_line_number) THEN
1663 id := qa_plan_element_api.get_contract_line_id(value);
1664
1665 ELSIF (element_id = qa_ss_const.deliverable_number) THEN
1666 id := qa_plan_element_api.get_deliverable_id(value);
1667
1668 ELSIF (element_id = qa_ss_const.work_order) THEN
1669 id := qa_plan_element_api.get_work_order_id(x_org_id, value);
1670
1671 --dgupta: Start R12 EAM Integration. Bug 4345492
1672 ELSIF (element_id = qa_ss_const.asset_instance_number) THEN
1673 id := qa_plan_element_api.get_asset_instance_id(value);
1674 --dgupta: End R12 EAM Integration. Bug 4345492
1675
1676 ELSIF (element_id = qa_ss_const.party_name) THEN
1677 id := qa_plan_element_api.get_party_id(value);
1678
1679 ELSIF (element_id = qa_ss_const.item_instance) THEN
1680 id := qa_plan_element_api.get_item_instance_id(value);
1681
1682 ELSIF (element_id = qa_ss_const.service_request) THEN
1683 id := qa_plan_element_api.get_service_request_id(value);
1684
1685 ELSIF (element_id = qa_ss_const.maintenance_requirement) THEN
1686 id := qa_plan_element_api.get_maintenance_req_id(value);
1687
1688 ELSIF (element_id = qa_ss_const.rework_job) THEN
1689 id := qa_plan_element_api.get_rework_job_id(x_org_id, value);
1690
1691 ELSIF (element_id = qa_ss_const.counter_name) THEN
1692 id := qa_plan_element_api.get_counter_name_id(value);
1693
1694 -- Added the following for NCM Hardcode Elements.
1695 -- suramasw Thu Oct 31 10:48:59 PST 2002.
1696 -- Bug 2449067.
1697
1698 ELSIF (element_id = qa_ss_const.lot_status) THEN
1699 id := qa_plan_element_api.get_lot_status_id(value);
1700
1701 ELSIF (element_id = qa_ss_const.serial_status) THEN
1702 id := qa_plan_element_api.get_serial_status_id(value);
1703
1704 -- End of inclusions for NCM Hardcode Elements.
1705
1706 -- R12 OPM Deviations. Bug 4345503 Start
1707 ELSIF (element_id = qa_ss_const.process_batch_num) THEN
1708 id := qa_plan_element_api.get_process_batch_id(value, x_org_id);
1709 g_process_batch_id := id;
1710
1711 ELSIF (element_id = qa_ss_const.process_batchstep_num) THEN
1712 id := qa_plan_element_api.get_process_batchstep_id
1713 (value,g_process_batch_id);
1714 g_process_batchstep_id := id;
1715
1716 ELSIF (element_id = qa_ss_const.process_operation) THEN
1717 id := qa_plan_element_api.get_process_operation_id
1718 (value,g_process_batch_id,g_process_batchstep_id);
1719
1720 ELSIF (element_id = qa_ss_const.process_activity) THEN
1721 id := qa_plan_element_api.get_process_activity_id
1722 (value,g_process_batch_id,g_process_batchstep_id);
1723 g_process_activity_id := id;
1724
1725 ELSIF (element_id = qa_ss_const.process_resource) THEN
1726 id := qa_plan_element_api.get_process_resource_id
1727 (value,g_process_batch_id,
1728 g_process_batchstep_id, g_process_activity_id);
1729 g_process_resource_id := id;
1730 ELSIF (element_id = qa_ss_const.process_parameter) THEN
1731 id := qa_plan_element_api.get_process_parameter_id
1732 (value,g_process_resource_id);
1733
1734 -- R12 OPM Deviations. Bug 4345503 End
1735 --R12 DR Integration . Bug 4345489 start
1736 ELSIF (element_id = qa_ss_const.repair_order_number) THEN
1737 id := qa_plan_element_api.get_repair_line_id
1738 (value);
1739 ELSIF (element_id = qa_ss_const.jtf_task_number) THEN
1740 id := qa_plan_element_api.get_jtf_task_id(value);
1741 --R12 Dr Integration. Bug 4345489 end
1742 END IF;
1743
1744 RETURN id;
1745
1746 END get_normalized_id;
1747
1748
1749 FUNCTION validate_normalized (row_elements IN ElementsArray,
1750 row_record IN RowRecord, element_id IN NUMBER, value IN VARCHAR2,
1751 result_holder IN OUT NOCOPY ResultRecord)
1752 RETURN NUMBER IS
1753
1754
1755 id NUMBER;
1756 sql_statement VARCHAR2(1500);
1757
1758 BEGIN
1759
1760 --
1761 -- Bug 2617638.
1762 -- Added the second conjunct because value can be null if there
1763 -- is a valid id. We want the procedure to continue in that case
1764 -- or the result_holder will be empty.
1765 -- bso Tue Oct 8 18:42:49 PDT 2002
1766 --
1767 IF (value is NULL AND NOT
1768 flag_is_set(row_elements(element_id).validation_flag, id_derived)) THEN
1769 RETURN ok;
1770 END IF;
1771
1772
1773 IF (flag_is_set(row_elements(element_id).validation_flag, id_derived)) THEN
1774 id := row_elements(element_id).id;
1775 ELSE
1776 id := get_normalized_id (element_id, value, g_org_id);
1777 IF (id IS NULL) THEN
1778 RETURN id_not_found_error;
1779 END IF;
1780 END IF;
1781
1782 result_holder.id := id;
1783
1784 --
1785 -- See Bug 2588213
1786 -- To support the element Maintenance Op Seq Number
1787 -- to be used along with Maintenance Workorder
1788 -- rkunchal Mon Sep 23 23:46:28 PDT 2002
1789 -- Added to the IF ladder for Maintenance Workorder
1790 --
1791 IF (element_id = qa_ss_const.job_name) THEN
1792 g_wip_entity_id := id;
1793 ELSIF (element_id = qa_ss_const.po_number) THEN
1794 g_po_header_id := id;
1795 ELSIF (element_id = qa_ss_const.production_line) THEN
1796 g_line_id := id;
1797 ELSIF (element_id = qa_ss_const.work_order) THEN
1798 g_work_order_id := id;
1799 ELSIF (element_id = qa_ss_const.rma_number) THEN
1800 -- Bug 9773026. Assign RMA Header Id to the global variable.
1801 -- skolluku
1802 g_rma_header_id := id;
1803 --
1804 -- Bug 11659488
1805 -- Cache the Sales_order_id in the Global variable so that it can be used
1806 -- to filter the SO_line_numbers
1807 --
1808 ELSIF (element_id = qa_ss_const.sales_order) THEN
1809 g_sales_order_id := id;
1810 END IF;
1811
1812
1813 RETURN ok;
1814
1815 EXCEPTION
1816 WHEN OTHERS THEN
1817 RETURN id_not_found_error;
1818
1819 END validate_normalized;
1820
1821
1822 FUNCTION valid_against_sql (element_id IN NUMBER, x_org_id IN NUMBER,
1823 x_value IN VARCHAR2)
1824 RETURN BOOLEAN IS
1825
1826 result BOOLEAN;
1827
1828 BEGIN
1829
1830 -- Transaction Date is validated only in PO Inspection Transaction
1831
1832 IF (element_id = qa_ss_const.transaction_date) THEN
1833 result := qa_plan_element_api.validate_transaction_date(
1834 g_transaction_number);
1835 --
1836 -- Bug 8690822
1837 -- Separating the condition for UOM and Comp UOM,
1838 -- as Comp Item Id would have to be used for Comp UOM.
1839 -- skolluku
1840 --
1841 ELSIF (element_id = qa_ss_const.uom) THEN
1842 --OR (element_id = qa_ss_const.comp_uom) THEN
1843 result := qa_plan_element_api.validate_uom(
1844 x_org_id, g_item_id, x_value);
1845 --
1846 -- Bug 8690822
1847 -- Pass g_comp_item_id to validate_uom, as the validation has
1848 -- to be done for Comp UOM and not UOM.
1849 -- skolluku
1850 --
1851 ELSIF (element_id = qa_ss_const.comp_uom) THEN
1852 result := qa_plan_element_api.validate_uom(
1853 x_org_id, g_comp_item_id, x_value);
1854
1855 ELSIF (element_id = qa_ss_const.revision)
1856 OR (element_id = qa_ss_const.comp_revision) THEN
1857 result := qa_plan_element_api.validate_revision(
1858 x_org_id, g_item_id, x_value);
1859
1860 ELSIF (element_id = qa_ss_const.subinventory)
1861 OR (element_id = qa_ss_const.comp_subinventory) THEN
1862 result := qa_plan_element_api.validate_subinventory(
1863 x_org_id, x_value);
1864
1865 -- Bug 4558205. OA Framewok Integration UT bug fix.
1866 -- Lot and serial numbers are not validated in server
1867 -- side for stand alone QWB.
1868 -- srhariha. Tue Sep 27 03:14:23 PDT 2005.
1869
1870 ELSIF (element_id = qa_ss_const.lot_number) THEN
1871 IF(g_transaction_number is null) OR (g_transaction_number = -1) THEN
1872 result := qa_plan_element_api.validate_lot_num(x_org_id,
1873 g_item_id ,
1874 x_value);
1875 ELSE
1876 result := qa_plan_element_api.validate_lot_number(g_transaction_number,
1877 g_transaction_id,
1878 x_value);
1879 END IF;
1880
1881 ELSIF (element_id = qa_ss_const.serial_number) THEN
1882
1883 IF(g_transaction_number is null) OR (g_transaction_number = -1) THEN
1884
1885 result := qa_plan_element_api.validate_serial_num(x_org_id,
1886 g_item_id,
1887 g_lot_number,
1888 g_revision,
1889 x_value);
1890 ELSE
1891 result := qa_plan_element_api.validate_serial_number(g_transaction_number,
1892 g_transaction_id,
1893 g_lot_number,
1894 x_value);
1895 END IF;
1896
1897 -- End. Bug 4558205.
1898
1899 ELSIF (element_id = qa_ss_const.to_op_seq_num)
1900 OR (element_id = qa_ss_const.from_op_seq_num) THEN
1901 result := qa_plan_element_api.validate_op_seq_number(
1902 x_org_id, g_line_id,
1903 g_wip_entity_id, x_value);
1904
1905 --
1906 -- See Bug 2588213
1907 -- To support the element Maintenance Op Seq Number
1908 -- to be used along with Maintenance Workorder
1909 -- rkunchal Mon Sep 23 23:46:28 PDT 2002
1910 --
1911
1912 ELSIF (element_id = qa_ss_const.maintenance_op_seq) THEN
1913 result := qa_plan_element_api.validate_maintenance_op_seq(
1914 x_org_id, g_work_order_id, x_value);
1915 --
1916 -- End of inclusions for Bug 2588213
1917 --
1918
1919
1920 ELSIF (element_id = qa_ss_const.po_line_num) THEN
1921
1922 g_po_line_number := x_value;
1923 result := qa_plan_element_api.validate_po_line_number(
1924 g_po_header_id, x_value);
1925
1926 ELSIF (element_id = qa_ss_const.po_shipment_num) THEN
1927 result := qa_plan_element_api.validate_po_shipments(
1928 g_po_line_number,
1929 g_po_header_id, x_value);
1930
1931 ELSIF (element_id = qa_ss_const.receipt_num) THEN
1932 result := qa_plan_element_api.validate_receipt_number(x_value);
1933
1934 /*
1935 ELSIF (element_id = qa_ss_const.comp_serial_number) THEN
1936 result := TRUE;
1937
1938 ELSIF (element_id = qa_ss_const.comp_lot_number) THEN
1939 result := TRUE;
1940
1941 ELSIF (element_id = qa_ss_const.quantity) THEN
1942 result := TRUE;
1943
1944 ELSIF (element_id = qa_ss_const.asset_number) THEN
1945 result := TRUE;
1946 */
1947 -- Added the following for NCM Hardcode Elements.
1948 -- suramasw Thu Oct 31 10:48:59 PST 2002.
1949 -- Bug 2449067.
1950
1951 ELSIF (element_id = qa_ss_const.to_subinventory) THEN
1952 result := qa_plan_element_api.validate_to_subinventory(
1953 x_org_id, x_value);
1954
1955 /*
1956 ELSIF (element_id = qa_ss_const.lot_status) THEN
1957 result := qa_plan_element_api.validate_lot_status(x_value);
1958
1959 ELSIF (element_id = qa_ss_const.concurrent_request_id) THEN
1960 result := TRUE;
1961
1962 ELSIF (element_id = qa_ss_const.nonconformance_code) THEN
1963 result := TRUE;
1964
1965 ELSIF (element_id = qa_ss_const.date_opened) THEN
1966 result := TRUE;
1967
1968 ELSIF (element_id = qa_ss_const.date_closed) THEN
1969 result := TRUE;
1970
1971 ELSIF (element_id = qa_ss_const.days_to_close) THEN
1972 result := TRUE;
1973 */
1974 -- the above code and the code above to_subinventory procedure was commented
1975 -- out to directly put an else clause which validates to TRUE since there is no
1976 -- special validation - suramasw Thu Oct 24 05:14:54 PDT 2002
1977
1978 ELSE
1979 result := TRUE;
1980
1981
1982 END IF;
1983
1984 RETURN result;
1985
1986 END valid_against_sql;
1987
1988
1989 FUNCTION validate_values (plan_id IN NUMBER, element_id IN NUMBER,
1990 value IN VARCHAR2)
1991 RETURN NUMBER IS
1992
1993 sql_string VARCHAR2(1500);
1994 ok_flag varchar2(240);
1995
1996 -- Bug 3111310. Used to have a SQL that select from
1997 -- dual which is inefficient
1998 -- saugupta Aug 2003
1999
2000 CURSOR c1 (p_id NUMBER, e_id NUMBER, v VARCHAR2) IS
2001 select '1'
2002 from qa_plan_char_value_lookups
2003 where plan_id = p_id
2004 and char_id = e_id
2005 and short_code = v;
2006 BEGIN
2007
2008 IF (value is NULL) THEN
2009 RETURN ok;
2010 END IF;
2011
2012 OPEN c1(plan_id, element_id, value);
2013 FETCH c1 INTO ok_flag;
2014 CLOSE c1;
2015
2016 IF ok_flag = '1' THEN
2017 RETURN ok;
2018 ELSE
2019 RETURN no_values_error;
2020 END IF;
2021
2022 EXCEPTION
2023 WHEN OTHERS THEN
2024 RETURN no_data_found_error;
2025
2026 END validate_values;
2027
2028 -- Bug 4343758. OA Framework Integration project.
2029 -- Added a new procedure. If the primitive values are validated
2030 -- then it must be copied to package globals, which will be used
2031 -- to validate other dependent elements.
2032 -- srhariha. Thu May 26 02:38:04 PDT 2005.
2033
2034 PROCEDURE copy_primitive_to_global(p_element_id IN NUMBER, p_value IN VARCHAR2) IS
2035
2036 BEGIN
2037
2038 IF (p_element_id = qa_ss_const.subinventory) THEN
2039 g_subinventory := p_value;
2040
2041 ELSIF (p_element_id = qa_ss_const.lot_number) THEN
2042 g_lot_number := p_value;
2043
2044 -- Added the following condition to enable History Records
2045 -- to be created when History Relationship is present.
2046 -- Bug 2700230.suramasw Mon Dec 23 03:06:30 PST 2002.
2047
2048 ELSIF (p_element_id = qa_ss_const.to_subinventory) THEN
2049 g_to_subinventory := p_value;
2050
2051 -- Bug 4558205. OA Framewok Integration UT bug fix.
2052 -- Lot and serial numbers are not validated in server
2053 -- side for stand alone QWB. Adding revision for serial
2054 -- number validation.
2055 -- srhariha. Tue Sep 27 03:14:23 PDT 2005.
2056
2057 ELSIF (p_element_id = qa_ss_const.revision) THEN
2058 g_revision := p_value;
2059 --
2060 -- Bug 6126260
2061 -- Added the extra condition to assign the value of the
2062 -- component subinventory to the global variable which
2063 -- would later be used to validate the comp subinventory locator.
2064 -- bhsankar Thu Jan 4 20:58:23 PST 2007
2065 --
2066 ELSIF (p_element_id = qa_ss_const.comp_subinventory) THEN
2067 g_comp_subinventory := p_value;
2068
2069 END IF;
2070
2071 END copy_primitive_to_global;
2072
2073
2074
2075 FUNCTION validate_primitive (plan_id IN NUMBER, row_elements IN ElementsArray,
2076 row_record IN RowRecord, element_id IN NUMBER, value IN VARCHAR2)
2077 RETURN NUMBER IS
2078
2079 sql_statement VARCHAR2(1500);
2080 valid_element BOOLEAN;
2081
2082 BEGIN
2083
2084 IF (value IS NULL) THEN
2085 RETURN ok;
2086 END IF;
2087
2088 -- The following code was put to reduce element_id check.The existing code
2089 -- for element_id check is commented out after the new code.
2090 -- suramasw Thu Oct 24 05:14:54 PDT 2002.
2091
2092 IF qa_plan_element_api.values_exist(plan_id, element_id) THEN
2093 RETURN validate_values(plan_id, element_id, value);
2094 END IF;
2095
2096 /*
2097 IF element_id IN (
2098 qa_ss_const.disposition,
2099 qa_ss_const.disposition_action,
2100 qa_ss_const.disposition_source,
2101 qa_ss_const.disposition_status,
2102 qa_ss_const.nonconformance_source,
2103 qa_ss_const.nonconform_severity,
2104 qa_ss_const.nonconform_priority,
2105 qa_ss_const.nonconformance_type,
2106 qa_ss_const.nonconformance_status) THEN
2107
2108 RETURN validate_values(plan_id, element_id, value);
2109 END IF;
2110 */
2111
2112 valid_element := valid_against_sql(element_id, g_org_id, value);
2113
2114 IF valid_element THEN
2115
2116 -- Bug 4343758. OA Framework Integration project.
2117 -- If the primitive values are validated then it
2118 -- must be copied to package globals, which will
2119 -- be used to validate other dependent elements.
2120 -- Existing logic wrapped into a new procedure.
2121 -- srhariha. Thu May 26 02:38:04 PDT 2005.
2122
2123 copy_primitive_to_global(p_element_id => element_id,
2124 p_value => value);
2125
2126 RETURN ok;
2127
2128 ELSE
2129 RETURN value_not_in_sql_error;
2130 END IF;
2131
2132 EXCEPTION
2133 WHEN OTHERS THEN
2134 RETURN value_not_in_sql_error;
2135
2136 END validate_primitive;
2137
2138
2139 FUNCTION validate_sql (element_id IN NUMBER, value IN VARCHAR2, x_org_id IN
2140 NUMBER, x_user_id IN NUMBER)
2141 RETURN NUMBER IS
2142
2143 sql_string VARCHAR2(1500);
2144
2145 BEGIN
2146
2147 IF (value IS NULL) THEN
2148 RETURN ok;
2149 END IF;
2150
2151 sql_string := qa_plan_element_api.get_sql_validation_string(element_id);
2152
2153 --
2154 -- Bug 9773062
2155 -- For all elements which need bind variables, add them to following block
2156 -- so that the binds can be added to their original sql validation string.
2157 -- skolluku
2158 --
2159 --
2160 -- Bug 11659488
2161 -- For So_line_number, the LOV has to be pruned by the SO_Header_id
2162 --
2163 IF (element_id IN (qa_ss_const.rma_line_num, qa_ss_const.order_line)) THEN -- add more elements if needed.
2164 sql_string := qa_chars_api.remove_order_by_from_sql(sql_string);
2165 IF (element_id = qa_ss_const.rma_line_num AND g_rma_header_id IS NOT NULL) THEN
2166 sql_string := sql_string || ' AND SH.HEADER_ID = ' || g_rma_header_id;
2167 END IF;
2168
2169 IF (element_id = qa_ss_const.order_line AND g_sales_order_id IS NOT NULL) THEN
2170 sql_string := sql_string || ' AND OEHA.HEADER_ID IN (SELECT oe.header_id FROM mtl_sales_orders mso, '
2171 || ' oe_order_headers_all oe, oe_transaction_types_tl ot '
2172 || ' WHERE mso.segment1 = oe.order_number AND oe.order_type_id = ot.transaction_type_id '
2173 || ' AND mso.segment2 = ot.name AND mso.sales_order_id = '|| g_sales_order_id || ')';
2174 END IF;
2175 END IF;
2176
2177 sql_string := qa_chars_api.format_sql_for_validation (sql_string,
2178 x_org_id, x_user_id);
2179
2180 IF qa_plan_element_api.value_in_sql (sql_string, value) THEN
2181 RETURN ok;
2182
2183 ELSE
2184 RETURN sql_validation_error;
2185
2186 END IF;
2187
2188 EXCEPTION WHEN OTHERS THEN
2189 RETURN sql_validation_error;
2190
2191 END validate_sql;
2192
2193
2194 FUNCTION validate_spec_limits (row_record IN RowRecord, element_id IN NUMBER,
2195 value IN VARCHAR2)
2196 RETURN NUMBER IS
2197
2198 lower_limit VARCHAR2(150);
2199 upper_limit VARCHAR2(150);
2200 datatype NUMBER;
2201
2202 BEGIN
2203
2204 IF (value IS NULL) THEN
2205 RETURN ok;
2206 END IF;
2207
2208 -- gets the spec limits and converts them to canonical
2209 -- BUG 3303285
2210 -- ksoh Mon Dec 29 13:33:02 PST 2003
2211 -- call overloaded get_spec_limits that takes in plan_id
2212 -- it performs uom conversion
2213 qa_plan_element_api.get_spec_limits(row_record.plan_id, row_record.spec_id,
2214 element_id,
2215 lower_limit, upper_limit);
2216
2217 IF (lower_limit IS NULL) OR (upper_limit IS NULL) THEN
2218 RETURN ok;
2219 END IF;
2220
2221 datatype := qa_plan_element_api.get_element_datatype(element_id);
2222
2223 IF qltcompb.compare(value, 6, lower_limit, null, datatype) THEN
2224 -- if (value < lower_limit) then
2225 RETURN lower_limit_error;
2226 END IF;
2227
2228 IF qltcompb.compare(value, 5, upper_limit, null, datatype) THEN
2229 -- if (value > upper_limit) then
2230 RETURN upper_limit_error;
2231 END IF;
2232
2233 RETURN ok;
2234
2235 EXCEPTION
2236 WHEN OTHERS THEN
2237 RETURN spec_error;
2238
2239 END validate_spec_limits;
2240
2241
2242 FUNCTION validate_char (value IN VARCHAR2, result_holder IN OUT NOCOPY ResultRecord)
2243 RETURN NUMBER IS
2244
2245 BEGIN
2246
2247 result_holder.canonical_value := substr(value, 1, 150);
2248
2249 RETURN ok;
2250
2251 END validate_char;
2252
2253
2254 FUNCTION validate_number (value IN VARCHAR2, length IN NUMBER,
2255 precision IN NUMBER, result_holder IN OUT NOCOPY ResultRecord)
2256 RETURN NUMBER IS
2257
2258 BEGIN
2259
2260 -- anagarwal Fri Dec 12 12:04:39 PST 2003
2261 -- Bug 3303276
2262 -- Decimal precision of numbers was not being used. The new call
2263 -- uses the passed precision to round off the number according to
2264 -- the precision specified in the plan
2265 -- We use qltdate.number_to_cannon to ensure that there are no errors
2266 -- if the number is in format 1,2345 instead of 1.2345 (a German user
2267 -- perhaps).
2268
2269 --result_holder.canonical_value := qltdate.any_to_number(value);
2270 result_holder.canonical_value := qltdate.number_to_canon(
2271 round(qltdate.any_to_number(value),
2272 nvl(precision, 240)));
2273
2274 RETURN ok;
2275
2276
2277 EXCEPTION
2278 WHEN OTHERS THEN
2279 RAISE;
2280
2281 END validate_number;
2282
2283
2284 FUNCTION validate_date (value IN VARCHAR2, result_holder IN OUT NOCOPY ResultRecord)
2285 RETURN NUMBER IS
2286
2287 BEGIN
2288 -- convert it to canonical format
2289 result_holder.canonical_value := qltdate.any_to_canon(value);
2290 RETURN ok;
2291
2292 EXCEPTION
2293 WHEN OTHERS THEN
2294 RAISE;
2295
2296 END validate_date;
2297
2298
2299 -- rkaza. bug 3220767. 10/29/2003. Follwing function not used.
2300 -- When coming from ss, we have to do the tz conversion in the middle tier.
2301 -- because server side initializations required for tz conversion to work
2302 -- on server side would not be done by ss tech stack as in forms.
2303 FUNCTION validate_datetime (value IN VARCHAR2, result_holder IN OUT NOCOPY ResultRecord)
2304 RETURN NUMBER IS
2305
2306 -- Bug 4965371
2307 -- Variable to hold the date converted
2308 -- from the User format into DD-MON-RRRR HH24:MI:SS
2309 -- format
2310 -- nutngare Sun Feb 12 04:31:28 PST 2006
2311
2312 l_value varchar2(50);
2313
2314 BEGIN
2315
2316 -- Bug 4965371
2317 -- Convert the format of the argument value which would be '2005/12/21 17:09:36' to the
2318 -- format compatible to the fnd_date.displayDT_to_date function which needs the value to
2319 -- be in the format 'DD-MON-RRRR HH24:MI:SS'. So used qltdate.any_to_user_dt to convert
2320 -- the value to the format 'DD-MON-RRRR HH24:MI:SS' and then call the Fnd_date functions.
2321 -- ntungare Sun Feb 12 04:35:39 PST 2006
2322
2323 l_value := qltdate.any_to_user_dt(value);
2324
2325 -- convert the value to server tz and then to canonical.
2326 -- Bug 4965371
2327 -- Using the converted value
2328 -- ntungare Sun Feb 12 04:35:20 PST 2006
2329
2330 result_holder.canonical_value :=
2331 Fnd_date.date_to_canonical(fnd_date.displayDT_to_date(l_value, calendar_aware=> FND_DATE.calendar_aware_alt));
2332
2333 RETURN ok;
2334
2335 EXCEPTION
2336 WHEN OTHERS THEN
2337 -- Bug 3318462. This exception is raised when date coming
2338 -- from self service and mobile, since data is in server
2339 -- timezone from history plans and it is required to distinguish
2340 -- data from Forms.
2341 -- saugupta Fri, 06 Feb 2004 00:03:57 -0800 PDT
2342 IF SQLCODE = -1861 THEN
2343 RETURN -1861;
2344 ELSE
2345 RAISE;
2346 END IF;
2347
2348 END validate_datetime;
2349
2350
2351 FUNCTION validate_datatype (plan_id IN NUMBER, element_id IN NUMBER,
2352 value IN VARCHAR2, row_elements IN OUT NOCOPY ElementsArray,
2353 result_holder IN OUT NOCOPY ResultRecord)
2354 RETURN NUMBER IS
2355
2356 data_type NUMBER;
2357 len NUMBER;
2358 precision NUMBER;
2359 error_code NUMBER;
2360 val_len NUMBER;
2361 -- Bug 3318462. New variable to get actual datatype
2362 -- of date time elements to distinguish between
2363 -- softcoded and hardcoded eements
2364 actual_datatype NUMBER;
2365
2366 BEGIN
2367 -- bug 3178307. rkaza. 10/06/2003.
2368 -- Modifed the function for Timezone Support.
2369
2370 data_type := qa_chars_api.datatype(element_id);
2371
2372 len := qa_chars_api.display_length(element_id);
2373
2374 -- Bug 3318462. History child plans showing wrong
2375 -- client timezone. It is saving date time in client timezone
2376 -- for child plans due to this, difference is again added when
2377 -- viewing child plans
2378 -- saugupta Wed, 14 Jan 2004 04:39:30 -0800 PDT
2379 actual_datatype := qa_plan_element_api.get_actual_datatype(element_id);
2380
2381 --
2382 -- See Bug 2624112
2383 -- The decimal precision for a number type collection
2384 -- element is to be configured at plan level.
2385 --
2386 -- Validation would be appropriate when decimal precision is
2387 -- taken from plan definition rather than element setup
2388 --
2389 -- Before this change
2390 -- precision := qa_chars_api.decimal_precision(element_id);
2391 -- After this change
2392 -- precision := nvl(qa_plan_element_api.decimal_precision(plan_id, element_id),
2393 -- qa_chars_api.decimal_precision(element_id));
2394 --
2395 -- rkunchal Wed Oct 16 05:32:33 PDT 2002
2396 --
2397
2398 precision := nvl(qa_plan_element_api.decimal_precision(plan_id, element_id),
2399 qa_chars_api.decimal_precision(element_id));
2400
2401 IF (data_type = qa_ss_const.date_datatype) THEN
2402 error_code := validate_date(value, result_holder);
2403
2404 ELSIF (data_type = qa_ss_const.datetime_datatype) THEN
2405 val_len := length(value);
2406 if substr(value, val_len - 1, 2) = '.0' then
2407 -- all hardcoded datetimes in self service come here.
2408 -- When coming from Self service, a '.0' is appended to the value
2409 -- because of an implicit conversion from date to string.
2410 -- So chop it off.
2411 error_code := validate_date(substr(value, 1, val_len-2), result_holder);
2412 else
2413 -- softcoded datetime elements from ss and mobile comes here
2414 -- From ss, values are already in server tz and in canonical format
2415 -- values from Mobile are also in server timezone
2416 -- saugupta Fri, 06 Feb 2004 00:14:24 -0800 PDT
2417
2418 -- Bug 3318462. Also all forms datetime elements come here
2419 -- Forms calls validate_api and data for softcoded is coming
2420 -- from DISPLAYxx. So for History Plans softcoded date is getting saved in
2421 -- client timezone. To correct it, using get_actual_datatype() to check the
2422 -- real datatype of the element. If it is character than call validate_datetime
2423 -- else its hardcoded so calling validate_date.
2424 -- saugupta Wed, 14 Jan 2004 04:40:08 -0800 PDT
2425
2426 IF (actual_datatype = qa_ss_const.character_datatype) THEN
2427 error_code := validate_datetime(value, result_holder);
2428
2429 -- Bug 3318462. From ss and mobile softcoded datetime elements are
2430 -- in server timezone. Above call will throw and exception. Returned
2431 -- the error number from validate_datetime() and handled it in below
2432 -- statement to make sure that ss and mobile calls correct function.
2433 -- saugupta Fri, 06 Feb 2004 00:18:38 -0800 PDT
2434
2435 IF (error_code = -1861 ) THEN
2436 error_code := validate_date(value, result_holder);
2437 END IF;
2438 ELSE
2439 error_code := validate_date(value, result_holder);
2440 END IF;
2441 end if;
2442
2443 ELSIF (data_type = qa_ss_const.number_datatype) THEN
2444 error_code := validate_number(value, len, precision,
2445 result_holder);
2446 --
2447 -- Bug 3402251. In order to use the round-up values in
2448 -- further assign-a-value actions, the canonical value
2449 -- needs to be copied back to the row element, readjusted
2450 -- to client format.
2451 -- bso Mon Feb 9 21:42:20 PST 2004
2452 --
2453 row_elements(element_id).value := to_char(
2454 fnd_number.canonical_to_number(result_holder.canonical_value));
2455
2456 -- Bug 2427337. Added following elsif condition for longcomment datatype
2457 -- rponnusa Tue Jun 25 06:15:48 PDT 2002
2458
2459 ELSIF (data_type = qa_ss_const.comment_datatype) THEN
2460 error_code := validate_comment(value, result_holder);
2461
2462 ELSE
2463 error_code := validate_char(value, result_holder);
2464
2465 END IF;
2466
2467 RETURN ok;
2468
2469 EXCEPTION
2470 WHEN INVALID_NUMBER OR VALUE_ERROR THEN
2471 RETURN invalid_number_error;
2472
2473 WHEN INVALID_DATE OR INVALID_DATE_FORMAT THEN
2474 RETURN invalid_date_error;
2475
2476 WHEN OTHERS THEN
2477 RETURN unknown_error;
2478
2479 END validate_datatype;
2480
2481
2482 FUNCTION evaluate_trigger (condition_record IN ConditionRecord, plan_id IN NUMBER, element_id IN
2483 NUMBER, value IN VARCHAR2, spec_id IN NUMBER)
2484 RETURN BOOLEAN IS
2485
2486 low_value VARCHAR2(150);
2487 high_value VARCHAR2(150);
2488 datatype NUMBER;
2489
2490 BEGIN
2491
2492 IF condition_record.low_value_other IS NULL THEN
2493 -- BUG 3303285
2494 -- ksoh Mon Jan 5 12:55:13 PST 2004
2495 -- replaced get_spec_limits, which does not retrieve the
2496 -- correct low high value as it always retrieve reasonable limits
2497 --
2498 -- qa_plan_element_api.get_spec_limits(spec_id, element_id,
2499 -- low_value, high_value);
2500 qa_plan_element_api.get_low_high_values(plan_id, spec_id, element_id,
2501 condition_record.low_value_lookup, condition_record.high_value_lookup,
2502 low_value, high_value);
2503
2504 ELSE
2505 low_value := condition_record.low_value_other;
2506 high_value := condition_record.high_value_other;
2507
2508 END IF;
2509
2510 datatype := qa_plan_element_api.get_element_datatype(element_id);
2511
2512 IF qltcompb.compare(value, condition_record.operator, low_value,
2513 high_value, datatype) THEN
2514 RETURN TRUE;
2515 ELSE
2516 RETURN FALSE;
2517 END IF;
2518
2519 END evaluate_trigger;
2520
2521 --
2522 -- Bug 2976810
2523 -- this function modified to a procedure to give back the value of a token
2524 -- as well as the datatype of this value.
2525 -- ilawler Tue May 27 13:34:49 2003
2526 --
2527 PROCEDURE get_token_value (p_token_name IN VARCHAR2,
2528 p_plan_char_action_id IN NUMBER,
2529 p_row_elements IN ElementsArray,
2530 x_token_value OUT NOCOPY VARCHAR2,
2531 x_token_datatype OUT NOCOPY NUMBER)
2532 IS
2533
2534 element_id NUMBER;
2535 token_value VARCHAR2(2150);
2536
2537 --move the lookup of the datatype into this cursor
2538 /* CURSOR c1 (token VARCHAR2, pca_id NUMBER) IS
2539 SELECT qpcao.char_id, qpcv.datatype
2540 FROM qa_plan_char_action_outputs qpcao, qa_plan_chars_v qpcv
2541 WHERE plan_char_action_id = pca_id AND
2542 token_name = token AND
2543 qpcao.char_id = qpcv.char_id; */
2544
2545 -- Bug 4958778. SQL Repository Fix SQL ID: 15008783
2546 CURSOR c1 (token VARCHAR2, pca_id NUMBER) IS
2547 SELECT
2548 qpcao.char_id,
2549 qpcv.datatype
2550 FROM qa_plan_char_action_outputs qpcao,
2551 qa_chars qpcv
2552 WHERE plan_char_action_id = pca_id
2553 AND token_name = token
2554 AND qpcao.char_id = qpcv.char_id;
2555
2556
2557 BEGIN
2558 -- rkaza. 05/07/2003. Bug 2946779. Converting token name to upper case
2559 -- before comparing with token variable
2560
2561 OPEN c1 (upper(p_token_name), p_plan_char_action_id);
2562 FETCH c1 INTO element_id, x_token_datatype;
2563 CLOSE c1;
2564
2565 x_token_value := p_row_elements(element_id).value;
2566
2567 END get_token_value;
2568
2569
2570 --
2571 -- Bug 2976810
2572 -- this function performs the sql text/formula associated with an
2573 -- 'Assign a value to a collection element' plan action. This function has been
2574 -- modified to use dbms_sql and bind variables to remove our dependence on
2575 -- an exemption. This function was also expanded to do some of the data formatting
2576 -- done by import(qltdactb.do_assignment).
2577 -- ilawler Tue May 27 13:34:49 2003
2578 --
2579 FUNCTION get_assigned_value (plan_char_action_id IN NUMBER,
2580 message IN VARCHAR2,
2581 row_elements IN ElementsArray)
2582 RETURN VARCHAR2
2583 IS
2584 assigned_value VARCHAR2(150);
2585
2586 -- Bug 5150287. SHKALYAN 02-Mar-2006.
2587 -- Increased the column width of final_stmt from 500 to 2500.
2588 -- In 'Assign a value' action if we populate a comment datatype element
2589 -- directly with a value(without tokens) which is approximately 2000
2590 -- characters then this variable would not be able to hold the value.
2591 final_stmt VARCHAR2(2500);
2592
2593 len NUMBER;
2594 i NUMBER;
2595 k NUMBER := 1;
2596 ignore NUMBER;
2597 assigned_datatype NUMBER;
2598 assigned_precision NUMBER;
2599 curr_char VARCHAR2(30);
2600 token_name VARCHAR2(30);
2601 token_datatype NUMBER;
2602 bind_var_name VARCHAR2(100);
2603
2604 -- Bug 5150287. SHKALYAN 02-Mar-2006.
2605 -- Increased the column width of token_value from 150 to 2000.
2606 -- If the value of token_value which is going to be copied to
2607 -- the target element is more than 150 characters then ORA-06502
2608 -- would be raised. To prevent that column width has been increased.
2609 token_value VARCHAR2(2000) DEFAULT NULL;
2610
2611 TYPE tokenValTab IS TABLE OF token_value%TYPE INDEX BY BINARY_INTEGER;
2612 token_vals tokenValTab;
2613
2614 assignment_type VARCHAR2(1);
2615
2616 -- Bug 5150287. SHKALYAN 02-Mar-2006.
2617 -- Increased the column width of return_value_char from 1500 to
2618 -- 2000 for the same reason mentioned above for token_value.
2619 return_value_char VARCHAR2(2000);
2620
2621 return_value_num NUMBER;
2622 return_value_date DATE;
2623
2624 c1 NUMBER;
2625
2626 --besides fetching the assign type, get the datatype of the assign target
2627 /* CURSOR c2 (pca_id NUMBER) IS
2628 SELECT qpca.assign_type, qpcv.datatype, qpcv.decimal_precision
2629 FROM qa_plan_char_actions qpca, qa_plan_chars_v qpcv
2630 WHERE qpca.plan_char_action_id = pca_id AND
2631 qpca.assigned_char_id = qpcv.char_id; */
2632
2633 -- Bug 4958778. SQL Repository Fix SQL ID: 15008799
2634 -- There is also an existing bug in the original query,
2635 -- namely qpc.plan_id is not used as a condition.
2636 -- It is hereby fixed.
2637 -- bso Fri Feb 3 11:31:47 PST 2006
2638 CURSOR c2 (pca_id NUMBER) IS
2639 SELECT
2640 qpca.assign_type,
2641 qc.datatype,
2642 nvl(qpc.decimal_precision, qc.decimal_precision) decimal_precision
2643 FROM qa_chars qc,
2644 qa_plan_chars qpc,
2645 qa_plan_char_actions qpca,
2646 qa_plan_char_action_triggers qpcat
2647 WHERE
2648 qpca.plan_char_action_trigger_id = qpcat.plan_char_action_trigger_id
2649 AND qpca.plan_char_action_id = pca_id
2650 AND qpc.plan_id = qpcat.plan_id
2651 AND qpc.char_id = qpca.assigned_char_id
2652 AND qc.char_id = qpca.assigned_char_id;
2653
2654 BEGIN
2655
2656 i := 1;
2657 len := NVL(length (message), 0);
2658
2659 WHILE i <= len LOOP
2660 curr_char := substr(message, i, 1);
2661 IF curr_char <> '&' THEN
2662 final_stmt := final_stmt || curr_char;
2663 i := i + 1;
2664
2665 ELSE -- we're at an ampersand
2666
2667 i := i + 1; -- skip over ampersand
2668 token_name := '';
2669 curr_char := substr(message, i, 1);
2670
2671 WHILE (curr_char between '0' and '9')
2672 OR (curr_char between 'A' and 'Z')
2673 OR (curr_char between 'a' and 'z')
2674 LOOP
2675 token_name := token_name || curr_char;
2676 i := i + 1;
2677 curr_char := substr(message, i, 1);
2678 END LOOP;
2679
2680 -- at this point the token name is formed so get the value and datatype
2681 get_token_value (p_token_name => token_name,
2682 p_plan_char_action_id => plan_char_action_id,
2683 p_row_elements => row_elements,
2684 x_token_value => token_value,
2685 x_token_datatype => token_datatype);
2686
2687 --based on this datatype we add different text to our sql statement
2688 bind_var_name := ':' || k;
2689
2690 -- Bug 5150287. SHKALYAN 02-Mar-2006.
2691 -- Included comment datatype(y_datatype=4) in the following IF loop
2692 -- Before this fix if we try to assign a value to a comment
2693 -- datatype element the action would fire but the value would not
2694 -- be copied to the target element (or) would error out in SSQR.
2695 if token_datatype in (1,4) then
2696 bind_var_name := bind_var_name;
2697 elsif token_datatype = 2 then
2698 bind_var_name:= 'nvl(qltdate.canon_to_number(' || bind_var_name || '), 0)';
2699 elsif token_datatype = 3 then
2700 bind_var_name := 'qltdate.any_to_date(' || bind_var_name || ')';
2701
2702 -- Bug 3179845. Timezone Project. rponnusa Thu Oct 30 00:47:31 PST 2003
2703 elsif token_datatype = 6 then -- datetime
2704 bind_var_name := 'qltdate.any_to_datetime(' || bind_var_name || ')';
2705 end if;
2706
2707 --add the token value to the token value array and append the bind variable
2708 --reference string to the statement
2709 token_vals(k) := token_value;
2710 final_stmt := final_stmt || bind_var_name ;
2711
2712 k := k + 1;
2713
2714 END IF;
2715
2716 END LOOP;
2717
2718 -- anagarwa Wed Jan 7 16:27:11 PST 2004
2719 -- Bug 3340004 actions are not being fired in SSQR
2720 -- The reason was that template plans have an extra new line character
2721 -- at the end of the sql for date opened. This extran new line is now
2722 -- being removed along with comma and forward slash
2723 -- IMPORTANT NOTE: DO NOT REMOVE THE NEW LINE CHARACTER IN FOLLOWING
2724 -- RTRIM EXPRESSION. IT HAS BEEN PUT TO FIX BUG 3340004
2725 final_stmt := rtrim(final_stmt, ' ;/
2726 ');
2727
2728 OPEN c2 (plan_char_action_id);
2729 FETCH c2 INTO assignment_type, assigned_datatype, assigned_precision;
2730 CLOSE c2;
2731
2732 -- if it's a formula type assign, wrap the action text in a select from dual
2733 IF assignment_type = 'F' THEN
2734 final_stmt := 'SELECT ' || final_stmt || ' FROM DUAL';
2735 END IF;
2736
2737 c1 := dbms_sql.open_cursor;
2738 dbms_sql.parse(c1, final_stmt, dbms_sql.native);
2739
2740 --go through the token_vals array and do the bindings
2741 k := token_vals.FIRST;
2742 WHILE (k IS NOT NULL) LOOP
2743 dbms_sql.bind_variable(c1, ':' || to_char(k), token_vals(k));
2744 k := token_vals.NEXT(k);
2745 END LOOP;
2746
2747 --
2748 -- Bug 4635316
2749 -- Binding the value of the Global parameter Org Id set in the function
2750 -- validate_row
2751 -- ntungare Mon Oct 10 01:14:31 PDT 2005
2752 --
2753 IF INSTR(final_stmt, QA_SS_CONST.bindvar_param_org_id, 1)<> 0 THEN
2754 dbms_sql.bind_variable(c1, QA_SS_CONST.bindvar_param_org_id, g_org_id);
2755 END IF;
2756
2757 --
2758 -- Bug 4635316
2759 -- Binding the value of the Global parameter User Id set in the function
2760 -- validate_row
2761 -- ntungare Mon Oct 10 01:14:31 PDT 2005
2762 --
2763 IF INSTR(final_stmt, QA_SS_CONST.bindvar_param_user_id, 1) <> 0 THEN
2764 dbms_sql.bind_variable(c1, QA_SS_CONST.bindvar_param_user_id, g_user_id);
2765 END IF;
2766
2767 --set up the type of the output we expect
2768
2769 -- Bug 5150287. SHKALYAN 02-Mar-2006.
2770 -- Included comment datatype(assigned_datatype=4) in the following IF loop.
2771 -- Before this fix if we try to assign a value to a comment datatype
2772 -- element the action would fire but the value would not be copied to
2773 -- the target element in SSQR. Also increased the width of
2774 -- return_value_char from 1500 to 2000.
2775 IF assigned_datatype in (1,4) THEN
2776 dbms_sql.define_column(c1, 1, return_value_char, 2000);
2777 ELSIF assigned_datatype = 2 THEN
2778 dbms_sql.define_column(c1, 1, return_value_num);
2779 ELSIF assigned_datatype = 3 THEN
2780 -- Bug 3179845. Timezone Project. rponnusa Thu Oct 30 00:47:31 PST 2003
2781
2782 -- Assign value from Date element to Date element fail if
2783 -- col defined as char type. To fix this get the value as Date type
2784 -- dbms_sql.define_column(c1, 1, return_value_char, 1500);
2785 dbms_sql.define_column(c1, 1, return_value_date);
2786
2787 ELSIF assigned_datatype = 6 THEN -- datetime
2788 dbms_sql.define_column(c1, 1, return_value_date);
2789 END IF;
2790
2791 --execute the cursor and fetch the value into return_value_char
2792 ignore := dbms_sql.execute(c1);
2793
2794 IF dbms_sql.fetch_rows(c1)>0 THEN
2795
2796 -- Bug 5150287. SHKALYAN 02-Mar-2006.
2797 -- Included assigned_datatype=4 also in the following loop for the
2798 -- same reason mentioned few lines above.
2799 IF assigned_datatype in (1,4) THEN
2800
2801 dbms_sql.column_value(c1, 1, return_value_char);
2802
2803 ELSIF assigned_datatype = 2 THEN
2804
2805 dbms_sql.column_value(c1, 1, return_value_num);
2806 return_value_char := to_char(round(return_value_num, nvl(assigned_precision, 0)));
2807
2808 ELSIF assigned_datatype = 3 THEN
2809 -- Bug 3179845. Timezone Project. rponnusa Thu Oct 30 00:47:31 PST 2003
2810
2811 -- dbms_sql.column_value(c1, 1, return_value_char);
2812 dbms_sql.column_value(c1, 1, return_value_date);
2813 return_value_char := qltdate.date_to_canon(return_value_date);
2814
2815 ELSIF assigned_datatype = 6 THEN -- datetime
2816
2817 dbms_sql.column_value(c1, 1, return_value_date);
2818 return_value_char := qltdate.date_to_canon_dt(return_value_date);
2819
2820 END IF;
2821 ELSE
2822 --if we didn't get anything then just give back a null
2823 return_value_char := NULL;
2824 END IF;
2825 dbms_sql.close_cursor(c1);
2826
2827 RETURN return_value_char;
2828
2829 EXCEPTION WHEN OTHERS THEN
2830 RAISE;
2831
2832 END get_assigned_value;
2833
2834 -- Bug 3397484. Added row_record to the function required to make a call to
2835 -- validate_keyflex and validate_normalized.
2836 -- saugupta Wed, 28 Jan 2004 07:59:39 -0800 PDT
2837
2838 -- 12.1 QWB Usability Improvements
2839 -- Added 2 new parameters p_ssqr_operation
2840 -- and ordered_array
2841 FUNCTION perform_immediate_actions (action_id IN NUMBER,
2842 element_id IN NUMBER,
2843 row_record IN RowRecord,
2844 message IN VARCHAR2,
2845 plan_char_action_id IN NUMBER,
2846 row_elements IN OUT NOCOPY ElementsArray,
2847 return_results_array IN OUT NOCOPY ResultRecordArray,
2848 message_array IN OUT NOCOPY MessageArray,
2849 result_holder IN OUT NOCOPY ResultRecord,
2850 ordered_array IN OUT NOCOPY ElementInfoArray,
2851 p_ssqr_operation IN NUMBER DEFAULT NULL
2852 )
2853 RETURN NUMBER IS
2854
2855 target_element NUMBER;
2856
2857 -- Bug 5150287. SHKALYAN 02-Mar-2006.
2858 -- Increased the column width of assigned_value from 150 to 2000.
2859 -- If the value of variable assigned_value which is going to store the
2860 -- value to be assigned to the target element is more than 150 characters
2861 -- then ORA-06502 would be raised. To prevent that column width has been
2862 -- increased to the maximum supported by Quality.
2863 assigned_value VARCHAR2(2000);
2864 message_index NUMBER;
2865 assigned_element VARCHAR2(30);
2866
2867 -- Bug 3397484. Added the variables to make a call to validate_keyflex and validate_normalized.
2868 -- This is required for backward assignment.
2869 -- saugupta Wed, 28 Jan 2004 08:01:37 -0800 PDT.
2870 back_result_holder ResultRecord;
2871 error_code NUMBER;
2872
2873 -- Bug 3679762. Added the following cursor to validte whether the target column
2874 -- for "assign a value" action exist/enabled in collection plan.
2875 -- srhariha.Wed Jun 16 06:54:06 PDT 2004
2876
2877 cursor validate_target(p_plan_id number,p_char_id number) is
2878 select 1
2879 from qa_plan_chars
2880 where plan_id = p_plan_id
2881 and char_id = p_char_id
2882 and enabled_flag = 1;
2883
2884 l_target_exists number;
2885
2886 --
2887 -- Bug 4635316.
2888 -- The variable altered_message would hold the formula or the sql text used in the
2889 -- assign a value action and passed to this fucntion in the variable message. If
2890 -- the sql text has reference to parameter fields like org_id and user_id then
2891 -- they are replaced with the BindVars and the resultant string is stored in this
2892 -- variable altered_message
2893 -- ntungare Sun Oct 16 20:36:17 PDT 2005
2894 --
2895 altered_message VARCHAR2(2000);
2896
2897 BEGIN
2898
2899 -- We need to take both the row_elements and return_results_array
2900 -- because we allow both forward and backward assignment in the assign
2901 -- a value action.
2902 --
2903 -- If it is forward assignment then row_elements will have the
2904 -- correct value and will be validated as the validation proceeds.
2905 --
2906 -- If it is backward assignment then we must modify the
2907 -- return_results_array to indicate the change, but this value
2908 -- will NOT be validated.
2909
2910 IF (action_id = qa_ss_const.display_message_action) THEN
2911
2912 message_index := message_array.count;
2913 message_array(message_index).element_id := element_id;
2914 message_array(message_index).action_type :=
2915 qa_ss_const.display_message_action;
2916 message_array(message_index).message := message;
2917
2918 ELSIF (action_id = qa_ss_const.reject_input_action) THEN
2919
2920 message_index := message_array.count;
2921 message_array(message_index).element_id := element_id;
2922 message_array(message_index).action_type :=
2923 qa_ss_const.reject_input_action;
2924 message_array(message_index).message := message;
2925
2926 -- This can be used in self service, and if the action
2927 -- is fired, this will be consiidered an error. Therrfore,
2928 -- we should return reject_an_entry_error.
2929
2930 RETURN reject_an_entry_error;
2931
2932 ELSIF (action_id = qa_ss_const.assign_value_action) THEN
2933
2934 target_element := qa_plan_element_api.get_target_element(
2935 plan_char_action_id);
2936
2937
2938 -- Bug 3679762. Check whether target column of assign a value action
2939 -- exist/enabled in collection plan.If it doesnot exist/enabled return
2940 -- the corresponding error code.
2941 -- srhariha. Wed Jun 16 06:54:06 PDT 2004
2942
2943 l_target_exists:= -1;
2944
2945 open validate_target(row_record.plan_id,target_element);
2946 fetch validate_target into l_target_exists;
2947
2948 if (validate_target%NOTFOUND) then
2949 close validate_target;
2950 return missing_assign_column;
2951 end if;
2952
2953 close validate_target;
2954
2955 --
2956 -- Bug 4635316.
2957 -- The variable message would hold the formula or the sql text used in the
2958 -- assign a value action. If the sql text has reference to parameter fields
2959 -- like org_id and user_id then replace those references with the Bind Vars
2960 -- The replaced message string is stored in a variable altered_message, which
2961 -- is then used in the subsequent calls.
2962 -- ntungare Sun Oct 16 20:36:17 PDT 2005
2963 --
2964 altered_message := QLTTRAFB.REPLACE_TOKEN(X_STRING => message,
2965 X_OLD_TOKEN => QA_SS_CONST.global_param_org_id ,
2966 X_NEW_TOKEN => QA_SS_CONST.bindvar_param_org_id);
2967
2968 altered_message := QLTTRAFB.REPLACE_TOKEN(X_STRING => altered_message,
2969 X_OLD_TOKEN => QA_SS_CONST.global_param_user_id,
2970 X_NEW_TOKEN => QA_SS_CONST.bindvar_param_user_id);
2971
2972 assigned_value := get_assigned_value(plan_char_action_id, altered_message,
2973 row_elements);
2974
2975 -- Bug 3397484. Check for the item type keyflex or normalized and then call appropriate
2976 -- validate functions to get the ids.
2977 -- saugupta Wed, 28 Jan 2004 08:02:59 -0800 PDT
2978 IF qa_plan_element_api.keyflex(target_element) THEN
2979 error_code := validate_keyflex(row_elements, row_record,
2980 target_element, assigned_value, back_result_holder);
2981
2982 return_results_array(target_element).id := back_result_holder.id;
2983 row_elements(target_element).id := back_result_holder.id;
2984
2985 --12.1 QWB Usability Improvements
2986 -- Setting the validation flag to action not fired
2987 -- so that the actions initiated from value not entered trigger
2988 -- on one of the collection elements are cascaded
2989 --
2990 IF (p_ssqr_operation IS NOT NULL) THEN
2991 ordered_array(target_element).validation_flag := invalid_element;
2992 END IF;
2993
2994 ELSIF qa_plan_element_api.normalized(target_element) THEN
2995 error_code := validate_normalized(row_elements, row_record,
2996 target_element, assigned_value, back_result_holder);
2997
2998 return_results_array(target_element).id := back_result_holder.id;
2999 row_elements(target_element).id := back_result_holder.id;
3000
3001 --12.1 QWB Usability Improvements
3002 -- Setting the validation flag to action not fired
3003 -- so that the actions initiated from value not entered trigger
3004 -- on one of the collection elements are cascaded
3005 --
3006 IF (p_ssqr_operation IS NOT NULL) THEN
3007 ordered_array(target_element).validation_flag := invalid_element;
3008 END IF;
3009
3010 END IF;
3011
3012 return_results_array(target_element).canonical_value := assigned_value;
3013 row_elements(target_element).value := assigned_value;
3014
3015 --12.1 QWB Usability Improvements
3016 -- Setting the validation flag to action not fired
3017 -- so that the actions initiated from value not entered trigger
3018 -- on one of the collection elements are cascaded
3019 --
3020 IF (p_ssqr_operation IS NOT NULL) THEN
3021 ordered_array(target_element).validation_flag := invalid_element;
3022 END IF;
3023
3024 --ilawler - bug #3340004 - Mon Feb 16 18:40:12 2004
3025 --this covers the case of actions that do self-assignment.
3026 --update the result_holder element also to keep validate_row's logic
3027 --from overwriting the return_results_array with a blank value.
3028 IF (element_id = target_element) THEN
3029 result_holder.canonical_value := assigned_value;
3030 END IF;
3031
3032 message_index := message_array.count;
3033 message_array(message_index).element_id := element_id;
3034 message_array(message_index).action_type := qa_ss_const.assign_value_action;
3035 assigned_element := qa_chars_api.prompt(target_element);
3036
3037 -- bug 3178307. rkaza. 10/07/2003. Timezone Support.
3038 If qa_chars_api.datatype(target_element) = qa_ss_const.datetime_datatype then
3039 assigned_value :=
3040 fnd_date.date_to_displayDT(fnd_date.canonical_to_date(assigned_value), calendar_aware=> FND_DATE.calendar_aware_alt);
3041 End if;
3042
3043 -- anagarwa Wed Jan 28 16:39:34 PST 2004
3044 -- Bug bug 3404863 Commenting the hardcoded message
3045 -- Modify the action messages to Source: Target = Value
3046 -- Also we now escape @ chars in value string.
3047
3048 --ilawler - bug #3340004 - Mon Feb 16 18:53:29 2004
3049 --According to bso, the message should always be <target> = <value>
3050 /*
3051 message_array(message_index).message := assigned_value || ' Has Been Assigned To: ' || assigned_element || ' As Per The Assign A Value Action Of ' || trigger_element;
3052 IF (action_id <> qa_ss_const.assign_value_action) THEN
3053 startText := trigger_element || ': ' ;
3054 END IF;
3055
3056 message_array(message_index).message := startText || assigned_element || ' = ' || replace(assigned_value,'@','@@');
3057 */
3058 message_array(message_index).message := assigned_element || ' = ' || replace(assigned_value,'@','@@');
3059
3060 END IF;
3061
3062 RETURN ok;
3063
3064 END perform_immediate_actions;
3065
3066 -- 12.1 QWB Usability Improvements
3067 -- Added 2 new parameters p_ssqr_operation
3068 -- and ordered_array
3069 --
3070 FUNCTION fire_immediate_actions (plan_id IN NUMBER,
3071 spec_id IN NUMBER,
3072 element_id IN NUMBER,
3073 row_elements IN OUT NOCOPY ElementsArray,
3074 return_results_array IN OUT NOCOPY ResultRecordArray,
3075 message_array IN OUT NOCOPY MessageArray,
3076 result_holder IN OUT NOCOPY ResultRecord,
3077 ordered_array IN OUT NOCOPY ElementInfoArray,
3078 p_ssqr_operation IN NUMBER DEFAULT NULL
3079 )
3080 RETURN NUMBER IS
3081
3082 sequence_limit NUMBER;
3083 sequence_number NUMBER;
3084 trigger_id NUMBER;
3085 action_id NUMBER;
3086 plan_char_action_id NUMBER;
3087 message VARCHAR2(2000);
3088 target_element NUMBER;
3089 error_code NUMBER default ok;
3090 value VARCHAR2(2000);
3091 condition_record ConditionRecord;
3092 val_len number;
3093 datatype number;
3094
3095 --
3096 -- Bug 5003885
3097 -- Added the column plan_char_action_trigger_id to the order by
3098 -- clause so that all the actions under the trigger sequences
3099 -- on the same level are picked up in order
3100 -- ntungare Sun Feb 12 06:23:11 PST 2006
3101 --
3102
3103 CURSOR rule_cursor (p_id NUMBER, c_id NUMBER) IS
3104 SELECT plan_char_action_trigger_id, trigger_sequence, operator,
3105 low_value_other, high_value_other,
3106 low_value_lookup, high_value_lookup
3107 FROM qa_plan_char_action_triggers
3108 WHERE plan_id = p_id
3109 AND char_id = c_id
3110 ORDER BY trigger_sequence, plan_char_action_trigger_id;
3111
3112 CURSOR action_cursor (rule_id NUMBER) IS
3113 SELECT plan_char_action_id, action_id, message
3114 FROM qa_plan_char_actions
3115 WHERE plan_char_action_trigger_id = rule_id;
3116
3117 -- Bug 3397484. Added to make a call to changed function perform_immediate_actions
3118 -- see below the data in RowRecord.
3119 -- saugupta Wed, 28 Jan 2004 08:04:20 -0800 PDT
3120 row_record RowRecord;
3121
3122 BEGIN
3123
3124 -- Bug 3397484. setting values of row_record for passing to perform_immediate_actions.
3125 -- saugupta Wed, 28 Jan 2004 08:05:21 -0800 PDT
3126 row_record.plan_id := plan_id;
3127 row_record.spec_id := spec_id;
3128 row_record.org_id := NULL;
3129 row_record.user_id := NULL;
3130
3131
3132 value := row_elements(element_id).value;
3133
3134 -- rkaza. bug 3248836. 11/11/2003. tz bug.
3135 datatype := qa_chars_api.datatype(element_id);
3136
3137 IF (datatype = qa_ss_const.datetime_datatype) THEN
3138 val_len := length(value);
3139 if substr(value, val_len - 1, 2) = '.0' then
3140 -- Sometimes when coming from Self service, a '.0'
3141 -- is appended to the value
3142 -- because of an implicit conversion from date to string.
3143 -- So chop it off.
3144 value := substr(value, 1, val_len-2);
3145 end if;
3146 end if;
3147
3148 sequence_limit := 9999;
3149
3150 OPEN rule_cursor (plan_id, element_id);
3151
3152 LOOP
3153
3154 FETCH rule_cursor INTO trigger_id, sequence_number,
3155 condition_record.operator,
3156 condition_record.low_value_other,
3157 condition_record.high_value_other,
3158 condition_record.low_value_lookup,
3159 condition_record.high_value_lookup;
3160
3161 EXIT WHEN rule_cursor%NOTFOUND;
3162
3163 IF sequence_number > sequence_limit THEN
3164 EXIT;
3165
3166 ELSE
3167
3168 -- BUG 3303285
3169 -- ksoh Mon Dec 29 13:33:02 PST 2003
3170 -- pass in plan_id so that
3171 -- it calls get_low_high_values and performs uom conversion
3172 IF evaluate_trigger(condition_record, plan_id, element_id, value, spec_id)
3173 THEN
3174 OPEN action_cursor (trigger_id);
3175 LOOP
3176
3177 FETCH action_cursor INTO plan_char_action_id, action_id,
3178 message;
3179
3180 EXIT WHEN action_cursor%NOTFOUND;
3181
3182 error_code := perform_immediate_actions(
3183 action_id,
3184 element_id,
3185 row_record,
3186 message,
3187 plan_char_action_id,
3188 row_elements,
3189 return_results_array,
3190 message_array,
3191 result_holder,
3192 ordered_array,
3193 p_ssqr_operation);
3194
3195 IF error_code = reject_an_entry_error THEN
3196 RETURN reject_an_entry_error;
3197 END IF;
3198
3199 END LOOP;
3200
3201 CLOSE action_cursor;
3202 sequence_limit := sequence_number;
3203 END IF;
3204
3205 END IF;
3206
3207 END LOOP;
3208
3209 CLOSE rule_cursor;
3210
3211 RETURN error_code;
3212
3213 EXCEPTION WHEN OTHERS THEN
3214 RETURN immediate_action_error;
3215
3216 END fire_immediate_actions;
3217
3218 -- Bug 4519558. OA Framework integration project. UT bug fix.
3219 -- Transaction type element was erroring out for WIP transactions.
3220 -- "Transaction Type" will be treated as one of a kind.
3221 -- srhariha.Tue Aug 2 00:43:07 PDT 2005.
3222
3223 FUNCTION validate_transaction_type(value IN VARCHAR2,
3224 p_org_id IN NUMBER,
3225 p_user_id IN NUMBER)
3226 RETURN NUMBER IS
3227
3228
3229 BEGIN
3230
3231 IF (value IS NULL) THEN
3232 RETURN ok;
3233 END IF;
3234
3235 IF qa_plan_element_api.validate_transaction_type(g_transaction_number,p_org_id,
3236 p_user_id, value) THEN
3237 RETURN ok;
3238 ELSE
3239 RETURN value_not_in_sql_error;
3240 END IF;
3241
3242 EXCEPTION
3243 WHEN OTHERS THEN
3244 RETURN value_not_in_sql_error;
3245
3246 END validate_transaction_type;
3247
3248 --
3249 -- Bug 6749653
3250 -- 12.1 QWB Usability Enhancements
3251 -- New function to peform the Reject and Input
3252 -- online validation
3253 -- nutngare
3254 --
3255 FUNCTION validate_reject_an_input(plan_id IN NUMBER,
3256 element_id IN NUMBER,
3257 value IN VARCHAR2)
3258 RETURN NUMBER AS
3259 CURSOR rule_cursor (p_id NUMBER, c_id NUMBER) IS
3260 SELECT pcat.plan_char_action_trigger_id, pcat.trigger_sequence, pcat.operator,
3261 pcat.low_value_other, pcat.high_value_other,
3262 pcat.low_value_lookup, pcat.high_value_lookup,
3263 pca.plan_char_action_id, pca.action_id, pca.message
3264 FROM qa_plan_char_action_triggers pcat, qa_plan_char_actions pca
3265 WHERE plan_id = p_id
3266 AND char_id = c_id
3267 AND pca.plan_char_action_trigger_id = pcat.plan_char_action_trigger_id
3268 AND pca.action_id = 2
3269 ORDER BY trigger_sequence, plan_char_action_trigger_id;
3270
3271 sequence_number NUMBER;
3272 trigger_id NUMBER;
3273 condition_record ConditionRecord;
3274 action_id NUMBER;
3275 plan_char_action_id NUMBER;
3276 message VARCHAR2(2000);
3277 sequence_limit NUMBER;
3278 BEGIN
3279 sequence_limit := 9999;
3280
3281 OPEN rule_cursor (plan_id, element_id);
3282
3283 LOOP
3284 FETCH rule_cursor INTO trigger_id, sequence_number,
3285 condition_record.operator,
3286 condition_record.low_value_other,
3287 condition_record.high_value_other,
3288 condition_record.low_value_lookup,
3289 condition_record.high_value_lookup,
3290 plan_char_action_id,
3291 action_id,
3292 message;
3293
3294 EXIT WHEN rule_cursor%NOTFOUND;
3295
3296 IF sequence_number > sequence_limit THEN
3297 EXIT;
3298 ELSE
3299 IF evaluate_trigger(condition_record, plan_id, element_id, value, 0)
3300 THEN
3301 RETURN reject_an_entry_error;
3302 END IF;
3303 END IF;
3304 END LOOP;
3305
3306 RETURN ok;
3307 END validate_reject_an_input;
3308
3309 --
3310 -- 12.1 QWB Usablity Improvements Project
3311 -- Modified the API to add a new parameter
3312 -- org_id. This is needed to online validations
3313 -- through PPR
3314 -- ntungare
3315 --
3316 FUNCTION validate_element (
3317 row_elements IN OUT NOCOPY ElementsArray,
3318 row_record IN RowRecord,
3319 element_id IN NUMBER,
3320 org_id IN NUMBER,
3321 result_holder IN OUT NOCOPY ResultRecord)
3322 RETURN ErrorArray IS
3323
3324 error_list ErrorArray;
3325 error_code NUMBER;
3326
3327 -- Bug 2427337 variable size increased for long comment datatype
3328 -- rponnusa Tue Jun 25 06:15:48 PDT 2002
3329 element_value VARCHAR2(2100);
3330
3331 BEGIN
3332 -- 12.1 QWB Usablitity Improvements
3333 g_org_id := org_id;
3334 element_value := row_elements(element_id).value;
3335
3336 result_holder.actual_datatype :=
3337 qa_plan_element_api.get_actual_datatype (element_id);
3338
3339 error_list(1).error_code := validate_enabled (row_record.plan_id,
3340 element_id);
3341
3342
3343 -- We should not perform any mandatory check if the row is
3344 -- coming from background transaction. For Background
3345 -- transaction null is allowed even for mandatory elements.
3346
3347 error_list(2).error_code := ok;
3348
3349 --
3350 -- Bug 2617638.
3351 -- Added the id_derived conjunct. No need to call validate
3352 -- mandatory if ID is passed. It is always NOT NULL in this
3353 -- case, and will not fail validate_mandatory.
3354 -- bso Tue Oct 8 18:44:45 PDT 2002
3355 --
3356 IF NOT flag_is_set(row_elements(element_id).validation_flag,
3357 background_element)
3358 AND NOT flag_is_set(row_elements(element_id).validation_flag,
3359 valid_element)
3360 AND NOT flag_is_set(row_elements(element_id).validation_flag,
3361 id_derived)
3362 THEN
3363
3364 error_list(2).error_code := validate_mandatory (row_record, element_id,
3365 element_value);
3366 END IF;
3367
3368 error_list(3).error_code := validate_datatype(row_record.plan_id,
3369 element_id, element_value, row_elements, result_holder);
3370
3371 IF qa_plan_element_api.keyflex(element_id) THEN
3372 error_list(4).error_code := validate_keyflex(row_elements, row_record,
3373 element_id, element_value, result_holder);
3374
3375 ELSIF qa_plan_element_api.normalized(element_id) THEN
3376 error_list(4).error_code := validate_normalized(row_elements,
3377 row_record, element_id, element_value, result_holder);
3378
3379 ELSIF qa_plan_element_api.primitive(element_id) THEN
3380 error_list(4).error_code := validate_primitive(row_record.plan_id,
3381 row_elements, row_record, element_id, element_value);
3382
3383 -- Bug 4519558. OA Framework integration project. UT bug fix.
3384 -- Transaction type element was erroring out for WIP transactions.
3385 -- "Transaction Type" will be treated as one of a kind.
3386 -- srhariha.Tue Aug 2 00:43:07 PDT 2005.
3387
3388 ELSIF element_id = qa_ss_const.transaction_type THEN
3389 error_list(4).error_code := validate_transaction_type(element_value,
3390 g_org_id,row_record.user_id);
3391
3392 ELSIF qa_plan_element_api.values_exist(row_record.plan_id, element_id) THEN
3393 error_list(4).error_code := validate_values(row_record.plan_id,
3394 element_id, element_value);
3395
3396 -- Bug 7716875.pdube Mon Apr 13 03:25:19 PDT 2009
3397 -- Added condition based on validation_flag which will
3398 -- be true for elements with sql validation for forms and qwb
3399 -- ELSIF qa_plan_element_api.sql_validation_exists(element_id) THEN
3400 -- Bug 10431717
3401 -- Added the NVL condition to ensure that if the flag is NULL then
3402 -- the data is considered as invalid and the validation is performed
3403 --
3404 ELSIF qa_plan_element_api.sql_validation_exists(element_id)
3405 AND NOT NVL(row_elements(element_id).validation_flag,'invalid') = 'valid' THEN
3406 error_list(4).error_code := validate_sql(element_id, element_value,
3407 row_record.org_id, row_record.user_id);
3408
3409 ELSE -- For
3410 error_list(4).error_code := ok;
3411 END if;
3412
3413 error_list(5).error_code := validate_spec_limits(row_record, element_id,
3414 result_holder.canonical_value);
3415
3416 --
3417 -- Bug 6749653
3418 -- 12.1 QWB Usability Improvements
3419 -- Checking for Reject an input actions
3420 -- ntungare
3421 --
3422 error_list(6).error_code := validate_reject_an_input(row_record.plan_id, element_id,
3423 result_holder.canonical_value);
3424
3425 RETURN error_list;
3426
3427 END validate_element;
3428
3429 --
3430 -- 12.1 QWB Usability Improvements
3431 -- Added a new parameter p_ssqr_operation that would determine
3432 -- if the online actions should be fired or not. This is neede
3433 -- since in QWB the online actions would be fired though PPR
3434 -- and so need not be fired again at the time of validation
3435 --
3436 FUNCTION validate_row (
3437 plan_id IN NUMBER,
3438 spec_id IN NUMBER,
3439 org_id IN NUMBER,
3440 user_id IN NUMBER,
3441 transaction_number IN NUMBER,
3442 transaction_id IN NUMBER,
3443 return_results_array OUT NOCOPY ResultRecordArray,
3444 message_array OUT NOCOPY MessageArray,
3445 row_elements IN OUT NOCOPY ElementsArray,
3446 p_ssqr_operation IN NUMBER DEFAULT NULL)
3447 RETURN ErrorArray IS
3448
3449 row_record RowRecord;
3450 result_holder ResultRecord;
3451 error_list ErrorArray;
3452 row_error_list ErrorArray;
3453 ordered_array ElementInfoArray;
3454
3455 BEGIN
3456
3457 row_record.plan_id := plan_id;
3458 row_record.spec_id := spec_id;
3459 row_record.org_id := org_id;
3460 row_record.user_id := user_id;
3461
3462 g_org_id := org_id;
3463 g_transaction_number := transaction_number;
3464 g_transaction_id := transaction_id;
3465
3466 --
3467 -- Bug 4635316.
3468 -- Store the value of user_id in the global variable g_user_id so
3469 -- that it can be used in Function fire_immediate_actions.
3470 -- ntungare Wed Sep 28 06:03:11 PDT 2005.
3471 --
3472 g_user_id := user_id;
3473
3474 -- Bug 4558205. Lot/Serial Validation.
3475 -- Call init procedure for global variables.
3476 -- srhariha. Tue Sep 27 05:07:58 PDT 2005.
3477
3478 init_globals;
3479
3480 -- End Bug 4558205.
3481
3482 -- Bug 3397484 ksoh Tue Jan 27 13:54:38 PST 2004
3483 -- pass plan_id for ordering ordered_array by prompt_sequence
3484 ordered_array := populate_elements (row_elements, plan_id);
3485 determine_navigation_order (ordered_array);
3486
3487 FOR i IN 0..row_elements.count-1 LOOP
3488
3489 IF NOT nvl(ordered_array(i).treated, FALSE) THEN
3490
3491 -- We must not validate an element if it is already valid,
3492 -- for example context elements for transactions.
3493 --
3494 -- However, if this element is a keyflex or normalized
3495 -- then we have to go through validation to determine
3496 -- the corresponding id to put in qa_results.
3497
3498 -- Bug 3381173. Validation should be performed even if the
3499 -- element is a primitive one. Hence adding an OR condn below.
3500 -- This is also necessary because of the dependent elements.
3501 -- Eg.. the subinventory (primitive) validation should be
3502 -- performed before the locator (keyflex) validation.
3503 -- kabalakr Tue Jan 27 02:18:59 PST 2004.
3504
3505 -- Bug 4343758. OA Framework Integration project.
3506 -- If the primitive values are validated then it
3507 -- must be copied to package globals, which will
3508 -- be used to validate other dependent elements.
3509 -- Also removed primitive call from below OR list.
3510 -- srhariha. Thu May 26 02:38:04 PDT 2005.
3511
3512 IF flag_is_set(ordered_array(i).validation_flag,valid_element) AND
3513 qa_plan_element_api.primitive(ordered_array(i).id) THEN
3514
3515 copy_primitive_to_global(p_element_id => ordered_array(i).id,
3516 p_value => row_elements(ordered_array(i).id).value);
3517 END IF;
3518
3519
3520 IF NOT flag_is_set(ordered_array(i).validation_flag,
3521 valid_element)
3522 OR qa_plan_element_api.keyflex(ordered_array(i).id)
3523 OR qa_plan_element_api.normalized(ordered_array(i).id) THEN
3524 -- OR qa_plan_element_api.primitive(ordered_array(i).id) THEN
3525
3526 -- 12.1 QWB Usabiltiy Improvements
3527 -- Passing the Org Id parameter
3528 error_list := validate_element( row_elements, row_record,
3529 ordered_array(i).id, org_id, result_holder);
3530 ordered_array(i).treated := TRUE;
3531
3532 --
3533 -- Bug 5331420. Some primitive elements are not firing
3534 -- actions because they do not match the complex IF
3535 -- condition. Hence, moved the following block to
3536 -- out of the IF THEN ELSE. Actions should be fired
3537 -- for all elements as long as it doesn't have the
3538 -- action_fired flag set which will be checked here.
3539 -- bso Thu Jun 15 16:19:59 PDT 2006
3540 --
3541 -- IF no_errors(error_list) THEN
3542 --
3543 -- -- if the calling application took care of immediate
3544 -- -- actions then we must not do any processing
3545 -- -- related to firing immediate actions
3546 --
3547 -- --ilawler - bug #3340004 - Mon Feb 16 18:38:25 2004
3548 -- --add result_holder as a param to allow self-assignment
3549 -- IF NOT (flag_is_set(ordered_array(i).validation_flag,
3550 -- action_fired)) THEN
3551 -- error_list(6).error_code := fire_immediate_actions (
3552 -- plan_id, spec_id, ordered_array(i).id,
3553 -- row_elements, return_results_array, message_array,
3554 -- result_holder);
3555 -- END IF;
3556 --
3557 -- END IF;
3558
3559 ELSE
3560
3561 -- If validation is not performed on elements there are couple of
3562 -- things we must compute.
3563 -- validate_datatype is called because we want to compute
3564 -- the canonical values for each element.
3565 -- Another thing is to cmopute the actual datatype
3566
3567 error_list(1).error_code := validate_datatype(row_record.plan_id,
3568 ordered_array(i).id , row_elements(ordered_array(i).id).value,
3569 row_elements, result_holder);
3570
3571 result_holder.actual_datatype := qa_plan_element_api.get_actual_datatype(
3572 ordered_array(i).id);
3573
3574 END IF;
3575
3576 --
3577 -- Bug 5331420. See above. Moved code here.
3578 --
3579 IF no_errors(error_list) THEN
3580
3581 -- if the calling application took care of immediate
3582 -- actions then we must not do any processing
3583 -- related to firing immediate actions
3584
3585 --ilawler - bug #3340004 - Mon Feb 16 18:38:25 2004
3586 --add result_holder as a param to allow self-assignment
3587 -- 12.1 QWB Usabiltity Improvements
3588 -- Online actions are to fired only in case the
3589 -- Validate_row method has not been called from the QWB
3590 -- Application.
3591 --
3592 IF (NOT (flag_is_set(ordered_array(i).validation_flag,
3593 action_fired)) AND
3594 p_ssqr_operation IS NULL) THEN
3595 error_list(6).error_code := fire_immediate_actions (
3596 plan_id, spec_id, ordered_array(i).id,
3597 row_elements, return_results_array, message_array,
3598 result_holder, ordered_array);
3599 END IF;
3600 END IF;
3601
3602 END IF;
3603
3604 append_errors( ordered_array(i).id, error_list, row_error_list);
3605 return_results_array(ordered_array(i).id).element_id :=
3606 ordered_array(i).id;
3607 return_results_array(ordered_array(i).id).id := result_holder.id;
3608 return_results_array(ordered_array(i).id).actual_datatype :=
3609 result_holder.actual_datatype;
3610 return_results_array(ordered_array(i).id).canonical_value :=
3611 result_holder.canonical_value;
3612 result_holder.id := NULL;
3613 error_list.delete;
3614
3615 END LOOP;
3616
3617 RETURN row_error_list;
3618
3619 EXCEPTION WHEN OTHERS THEN
3620 -- dbms_output.put_line('An Error Occurred, Unable To Continue');
3621 -- dbms_output.put_line(to_char(sqlcode)||': '||sqlerrm);
3622 RAISE;
3623
3624 END validate_row;
3625
3626
3627 PROCEDURE init_message_map IS
3628 --
3629 -- A mapping between our internal error message and its AOL message name.
3630 --
3631 BEGIN
3632 g_message_map(not_enabled_error) := 'QA_API_NOT_ENABLED';
3633 g_message_map(no_values_error) := 'QA_API_NO_VALUES';
3634 g_message_map(mandatory_error) := 'QA_API_MANDATORY';
3635 g_message_map(not_revision_controlled_error) := 'QA_API_REVISION_CONTROLLED';
3636 g_message_map(mandatory_revision_error) := 'QA_API_MANDATORY_REVISION';
3637 g_message_map(no_values_error) := 'QA_API_NO_VALUES';
3638 g_message_map(keyflex_error) := 'QA_API_KEYFLEX';
3639 g_message_map(id_not_found_error) := 'QA_API_ID_NOT_FOUND';
3640 g_message_map(spec_limit_error) := 'QA_API_SPEC_LIMIT';
3641 g_message_map(immediate_action_error) := 'QA_API_IMMEDIATE_ACTION';
3642 g_message_map(lower_limit_error) := 'QA_API_LOWER_LIMIT';
3643 g_message_map(upper_limit_error) := 'QA_API_UPPER_LIMIT';
3644 g_message_map(value_not_in_sql_error) := 'QA_API_VALUE_NOT_IN_SQL';
3645 g_message_map(sql_validation_error) := 'QA_API_SQL_VALIDATION';
3646 g_message_map(date_conversion_error) := 'QA_API_INVALID_DATE';
3647 g_message_map(data_type_error) := 'QA_API_DATA_TYPE';
3648 g_message_map(number_conversion_error) := 'QA_API_INVALID_NUMBER';
3649 g_message_map(no_data_found_error) := 'QA_API_NO_DATA_FOUND';
3650 g_message_map(not_locator_controlled_error) := 'QA_API_NOT_LOCATOR_CONTROLLED';
3651 g_message_map(item_keyflex_error) := 'QA_API_ITEM_KEYFLEX';
3652 g_message_map(comp_item_keyflex_error) := 'QA_API_COMP_ITEM_KEYFLEX';
3653 g_message_map(locator_keyflex_error) := 'QA_API_LOCATOR_KEYFLEX';
3654 g_message_map(comp_locator_keyflex_error) := 'QA_API_COMP_LOCATOR_KEYFLEX';
3655 g_message_map(invalid_number_error) := 'QA_API_INVALID_NUMBER';
3656 g_message_map(invalid_date_error) := 'QA_API_INVALID_DATE';
3657 g_message_map(spec_error) := 'QA_API_SPEC';
3658 g_message_map(ok) := 'QA_API_NO_ERROR';
3659 g_message_map(unknown_error) := 'QA_API_UNKNOWN';
3660 g_message_map(reject_an_entry_error) := 'QA_API_REJECT_AN_ENTRY';
3661
3662 -- Added the following messages for Bill_Reference,Routing_Reference,To_locator
3663 -- Key FlexFields. Bug 2686970.suramasw Wed Nov 27 05:12:52 PST 2002.
3664
3665 g_message_map(bill_reference_keyflex_error) := 'QA_API_BILL_REFERENCE_KEYFLEX';
3666 g_message_map(rtg_reference_keyflex_error) := 'QA_API_RTG_REFERENCE_KEYFLEX';
3667 g_message_map(to_locator_keyflex_error) := 'QA_API_TO_LOCATOR_KEYFLEX';
3668
3669 -- Bug 3679762.Initialising the message array for the "missing assign a value target
3670 -- column" error message.
3671 -- srhariha.Wed Jun 16 06:54:06 PDT 2004
3672
3673 g_message_map(missing_assign_column) := 'QA_MISSING_ASSIGN_COLUMN';
3674
3675 END init_message_map;
3676
3677
3678 FUNCTION get_error_message(error_code IN NUMBER) RETURN VARCHAR2 IS
3679 --
3680 -- Return an error message in the user's language given an error code.
3681 --
3682 BEGIN
3683 RETURN fnd_message.get_string('QA', g_message_map(error_code));
3684 END get_error_message;
3685
3686 FUNCTION validate_comment (value IN VARCHAR2, result_holder IN OUT NOCOPY ResultRecord)
3687 RETURN NUMBER IS
3688 --
3689 -- This function is for long comment datatype. Long comment can hold
3690 -- max of 2000 characters. Introduced for bug 2427337
3691 -- rponnusa Tue Jun 25 06:15:48 PDT 2002
3692
3693 BEGIN
3694 result_holder.canonical_value := substr(value, 1, 2000);
3695
3696 RETURN ok;
3697 END validate_comment;
3698
3699
3700 --
3701 -- R12 Project MOAC 4637896
3702 --
3703 -- Moved several procedures from qltssreb to this package
3704 -- to centralize all validation routines. These are
3705 --
3706 -- parse_id
3707 -- parse_value
3708 -- result_to_array
3709 -- id_to_array
3710 -- set_validation_flag
3711 -- set_validation_flag_txn
3712 --
3713 -- bso Sat Oct 1 16:15:58 PDT 2005
3714 --
3715
3716
3717 FUNCTION parse_id(p_result IN VARCHAR2, n IN INTEGER,
3718 p IN INTEGER, q IN INTEGER) RETURN NUMBER IS
3719 BEGIN
3720 RETURN to_number(substr(p_result, p, q-p));
3721 END parse_id;
3722
3723
3724 FUNCTION parse_value(p_result IN VARCHAR2, n IN INTEGER,
3725 p IN OUT NOCOPY INTEGER) RETURN VARCHAR2 IS
3726
3727 -- anagarwal Fri Nov 14 14:11:12 PST 2003
3728 -- bug 3256981
3729 -- the problem was happening due to value being initialized to have
3730 -- character1 length. For comment1 to comment5, it can be as long as
3731 -- 2000 chars. So we need to have long enough field.
3732 l_value qa_results.comment1%TYPE;
3733 c VARCHAR2(10);
3734 separator CONSTANT VARCHAR2(1) := '@';
3735
3736 BEGIN
3737 --
3738 -- Loop until a single @ is found or p_result is exhausted.
3739 --
3740 p := p + 1; -- add 1 before substr to skip '='
3741 WHILE p <= n LOOP
3742 c := substr(p_result, p, 1);
3743 p := p + 1;
3744 IF (c = separator) THEN
3745 IF substr(p_result, p, 1) <> separator THEN
3746 --
3747 -- take a peak at the next character, if not another @,
3748 -- we have reached the end. Otherwise, skip this @
3749 --
3750 RETURN l_value;
3751 ELSE
3752 p := p + 1;
3753 END IF;
3754 END IF;
3755 l_value := l_value || c;
3756 END LOOP;
3757
3758 RETURN l_value;
3759 END parse_value;
3760
3761
3762 FUNCTION result_to_array(p_result IN VARCHAR2)
3763 RETURN qa_validation_api.ElementsArray IS
3764
3765 elements qa_validation_api.ElementsArray;
3766 n INTEGER;
3767 p INTEGER; -- starting string position
3768 q INTEGER; -- ending string position
3769 x_char_id NUMBER;
3770 --anagarwal Fri Nov 14 14:11:12 PST 2003
3771 -- bug 3256981
3772 -- the problem was happening due t value being initialized to have
3773 -- character1 length. For comment1 to comment5, it can be as long as
3774 -- 2000 chars. So we need to have long enough field.
3775 x_value qa_results.comment1%TYPE;
3776
3777 BEGIN
3778 n := length(p_result);
3779 p := 1;
3780 WHILE p < n LOOP
3781 q := instr(p_result, '=', p);
3782 --
3783 -- found the first = sign. To the left, must be char_id
3784 --
3785 x_char_id := parse_id(p_result, n, p, q);
3786 -- Bug 7716875.pdube Mon Apr 13 03:25:19 PDT 2009
3787 -- Added this statement to set the validation flag back to
3788 -- valid if the element has a validation string.
3789 -- this api is called from forms and qwb where the
3790 -- value of the element will be validated at UI.
3791 --
3792 -- Bug 10431717
3793 -- Reverted this fix since we would be validating the entered data
3794 -- again since the LOV values are not validated on cancel
3795 --
3796 --IF qa_validation_api.set_validation_flag_sql_valid(x_char_id) THEN
3797 -- elements(x_char_id).validation_flag := 'valid';
3798 --END IF;
3799 --
3800 -- To the right, must be the value
3801 --
3802 x_value := parse_value(p_result, n, q);
3803 elements(x_char_id).value := x_value;
3804 p := q;
3805 END LOOP;
3806
3807 RETURN elements;
3808 END result_to_array;
3809
3810
3811 -- I am over riding this function for the ability to pass ids.
3812 -- This will resolve the validation issue for work order like elements
3813 -- names are not unique only ids are.
3814 --
3815 -- ORASHID 15-August-2001
3816 --
3817 -- R12 Project MOAC 4637896
3818 -- Renaming this function from result_to_array to
3819 -- id_to_array to fix a confusion. Uptake the
3820 -- parameter and local variable naming to Apps
3821 -- standard convention.
3822 -- bso Tue Sep 27 17:51:10 PDT 2005
3823 --
3824 FUNCTION id_to_array(
3825 p_result IN VARCHAR2,
3826 x_elements IN OUT NOCOPY qa_validation_api.ElementsArray)
3827 RETURN qa_validation_api.ElementsArray IS
3828
3829 n INTEGER;
3830 p INTEGER; -- starting string position
3831 q INTEGER; -- ending string position
3832 l_char_id NUMBER;
3833 l_value qa_results.character1%TYPE;
3834
3835 BEGIN
3836
3837 IF p_result IS NULL THEN
3838 RETURN x_elements;
3839 END IF;
3840
3841 n := length(p_result);
3842 p := 1;
3843 WHILE p < n LOOP
3844 q := instr(p_result, '=', p);
3845 --
3846 -- found the first = sign. To the left, must be char_id
3847 --
3848 l_char_id := parse_id(p_result, n, p, q);
3849 --
3850 -- To the right, must be the value
3851 --
3852 l_value := parse_value(p_result, n, q);
3853 x_elements(l_char_id).id := l_value;
3854 -- Bug 7716875.pdube Mon Apr 13 03:25:19 PDT 2009
3855 -- Added this statement to set the validation flag back to
3856 -- valid if the element has a validation string.
3857 -- this api is called from forms and qwb where the
3858 -- value of the element will be validated at UI.
3859 IF qa_validation_api.set_validation_flag_sql_valid(l_char_id) THEN
3860 x_elements(l_char_id).validation_flag := 'valid';
3861 END IF;
3862
3863 x_elements(l_char_id).validation_flag :=
3864 nvl(x_elements(l_char_id).validation_flag, 'invalid') ||
3865 qa_validation_api.id_derived;
3866 p := q;
3867 END LOOP;
3868
3869 RETURN x_elements;
3870 END id_to_array;
3871
3872
3873 PROCEDURE set_validation_flag(
3874 x_elements IN OUT NOCOPY qa_validation_api.ElementsArray) IS
3875 i INTEGER;
3876 BEGIN
3877 i := x_elements.FIRST;
3878 WHILE i <= x_elements.LAST LOOP
3879 x_elements(i).validation_flag :=
3880 x_elements(i).validation_flag ||
3881 qa_validation_api.action_fired;
3882
3883 IF i = qa_ss_const.transaction_type THEN
3884 x_elements(i).validation_flag :=
3885 x_elements(i).validation_flag ||
3886 qa_validation_api.valid_element;
3887 END IF;
3888
3889 i := x_elements.NEXT(i);
3890 END LOOP;
3891 END set_validation_flag;
3892
3893
3894 --
3895 -- The previous version of the following routine was
3896 -- incorrectly implemented. It is hereby redone.
3897 -- See version 120.4 of qltssreb.plb or before for the
3898 -- old version. Also renamed from set_validation_flag
3899 -- to set_validation_flag_txn.
3900 --
3901 -- This procedure is needed to set context elements to
3902 -- have background_element flag so that it will pass
3903 -- mandatory-ness validation even though the value is
3904 -- null. Background values will be posted later in a
3905 -- separate step, hence mandatory check is not needed.
3906 --
3907 -- Caller chould supply p_plan_id + p_transaction_number
3908 -- or simply p_plan_transaction_id which will be more
3909 -- accurate.
3910 --
3911 -- bso Sat Oct 1 15:05:35 PDT 2005
3912 --
3913
3914 PROCEDURE set_validation_flag_txn(
3915 x_elements IN OUT NOCOPY qa_validation_api.ElementsArray,
3916 p_plan_id NUMBER,
3917 p_transaction_number NUMBER,
3918 p_plan_transaction_id NUMBER) IS
3919
3920 CURSOR context IS
3921 SELECT collection_trigger_id
3922 FROM qa_txn_collection_triggers
3923 WHERE transaction_number = p_transaction_number AND
3924 enabled_flag = 1;
3925
3926 CURSOR bg1 IS
3927 SELECT 1
3928 FROM qa_plan_transactions
3929 WHERE plan_id = p_plan_id AND
3930 transaction_number = p_transaction_number AND
3931 enabled_flag = 1 AND
3932 background_collection_flag = 1;
3933
3934 CURSOR bg2 IS
3935 SELECT 1
3936 FROM qa_plan_transactions
3937 WHERE plan_transaction_id = p_plan_transaction_id AND
3938 enabled_flag = 1 AND
3939 background_collection_flag = 1;
3940
3941 i BINARY_INTEGER;
3942 l_background NUMBER;
3943
3944 BEGIN
3945 --
3946 -- Step 1. Set all context elements to be valid.
3947 --
3948 FOR c IN context LOOP
3949 IF x_elements.EXISTS(c.collection_trigger_id) THEN
3950 x_elements(c.collection_trigger_id).validation_flag :=
3951 x_elements(c.collection_trigger_id).validation_flag ||
3952 qa_validation_api.valid_element;
3953 END IF;
3954 END LOOP;
3955
3956 --
3957 -- Step 2. Set additional valid elements.
3958 --
3959 IF x_elements.EXISTS(qa_ss_const.lot_number) THEN
3960 x_elements(qa_ss_const.lot_number).validation_flag :=
3961 x_elements(qa_ss_const.lot_number).validation_flag ||
3962 qa_validation_api.valid_element;
3963 END IF;
3964
3965 IF x_elements.EXISTS(qa_ss_const.serial_number) THEN
3966 x_elements(qa_ss_const.serial_number).validation_flag :=
3967 x_elements(qa_ss_const.serial_number).validation_flag ||
3968 qa_validation_api.valid_element;
3969 END IF;
3970
3971 IF x_elements.EXISTS(qa_ss_const.transaction_type) THEN
3972 x_elements(qa_ss_const.transaction_type).validation_flag :=
3973 x_elements(qa_ss_const.transaction_type).validation_flag ||
3974 qa_validation_api.valid_element;
3975 END IF;
3976
3977 --
3978 -- Step 3. If it is a background plan, set all elements
3979 -- to have the background_element flag. Currently this
3980 -- is only an approximation because we should have used
3981 -- plan_transaction_id to identify the particular txn.
3982 -- But this was not available in the current architecture,
3983 -- so using a conservative approach to look for all
3984 -- plan_id + transaction_number combination and if any
3985 -- is background, then assume it is a background plan.
3986 -- The correct fix is that the caller must supply the
3987 -- p_plan_transaction_id param, then this function will
3988 -- work correctly.
3989 --
3990
3991 IF p_plan_transaction_id IS NULL THEN
3992 OPEN bg1;
3993 FETCH bg1 INTO l_background;
3994 CLOSE bg1;
3995 ELSE
3996 OPEN bg2;
3997 FETCH bg2 INTO l_background;
3998 CLOSE bg2;
3999 END IF;
4000
4001 IF l_background IS NOT NULL THEN
4002 i := x_elements.FIRST;
4003 WHILE i <= x_elements.LAST LOOP
4004 x_elements(i).validation_flag :=
4005 x_elements(i).validation_flag ||
4006 qa_validation_api.background_element;
4007 i := x_elements.NEXT(i);
4008 END LOOP;
4009 END IF;
4010
4011 END set_validation_flag_txn;
4012
4013 -- End R12 Project MOAC 4637896
4014
4015 -- Bug 7716875.pdube Mon Apr 13 03:25:19 PDT 2009
4016 -- This function will return true if there is already a sql validation
4017 -- attached to the element.We consider that the UI will validate the
4018 -- elements correctly and they need not to be validated again, hence
4019 -- using this value, shall set the validation_flag to valid
4020 FUNCTION set_validation_flag_sql_valid(
4021 p_char_id IN NUMBER) RETURN BOOLEAN IS
4022
4023 CURSOR sql_valid(x_char_id NUMBER) IS
4024 SELECT 1
4025 FROM qa_chars
4026 WHERE char_id = x_char_id AND
4027 sql_validation_string is not null;
4028 p_sql_validation_flag BOOLEAN;
4029 temp NUMBER := 0; -- Flag number 1 for true and 0 for false
4030
4031 BEGIN
4032 IF p_char_id is not null then
4033 OPEN sql_valid(p_char_id);
4034 FETCH sql_valid INTO temp;
4035 CLOSE sql_valid;
4036 END IF;
4037
4038 IF temp = 1 THEN
4039 RETURN TRUE;
4040 ELSE
4041 RETURN FALSE;
4042 END IF;
4043 END set_validation_flag_sql_valid;
4044
4045 -- 12.1 QWB Usability Improvements
4046 -- Procedure to De-reference the values for the HC elements
4047 -- that depended on Non Quality tables for their values
4048 PROCEDURE build_deref_string(p_plan_id IN NUMBER,
4049 p_collection_id IN NUMBER,
4050 p_occurrence IN NUMBER,
4051 p_charid_string OUT NOCOPY VARCHAR2,
4052 p_values_string OUT NOCOPY VARCHAR2)
4053 AS
4054
4055 Type hardcoded_char_tab_typ IS TABLE OF NUMBER INDEX BY binary_integer;
4056 hardcoded_char_tab hardcoded_char_tab_typ;
4057
4058 cols_str VARCHAR2(32767);
4059 char_ids_str VARCHAR2(32767);
4060
4061 plan_name VARCHAR2(100);
4062
4063 result_str VARCHAR2(32767);
4064
4065 char_name VARCHAR(100);
4066
4067 BEGIN
4068 --Get the list of HardCoded elements in the
4069 --Collection plan
4070 SELECT qpc.char_id bulk collect
4071 INTO hardcoded_char_tab
4072 FROM qa_plan_chars qpc,
4073 qa_chars qc
4074 WHERE qpc.plan_id = p_plan_id
4075 AND qpc.char_id = qc.char_id
4076 AND qc.hardcoded_column IS NOT NULL
4077 AND fk_table_name IS NOT NULL;
4078
4079 --loop through the list of HardCoded elements
4080 FOR cntr IN 1 .. hardcoded_char_tab.COUNT
4081 LOOP
4082 -- Select the column name for the Hardcoded
4083 -- element based on the element id
4084 Select upper(translate(name,' ''*{}','_____')) into char_name
4085 from qa_chars
4086 where char_id = hardcoded_char_tab(cntr);
4087
4088 --
4089 -- bug 7559568
4090 -- Added replace function to double encode the delimiter ,
4091 -- if the data contains the delimiter.
4092 -- ntungare
4093 --
4094 cols_str := cols_str || 'REPLACE(NVL(to_char('||char_name||'), ''NULL''),'','','',,'') ||'',''||';
4095 char_ids_str := char_ids_str ||
4096 qa_ak_mapping_api.get_vo_attribute_name(hardcoded_char_tab(cntr), p_plan_id)||
4097 ',';
4098 END LOOP;
4099
4100 if hardcoded_char_tab.count <> 0 then
4101 -- Get the plan name to form the Dynamic Plan View Name
4102 SELECT deref_view_name
4103 INTO plan_name
4104 FROM qa_plans
4105 WHERE plan_id = p_plan_id;
4106
4107 cols_str := RTRIM(cols_str, '||'',''||');
4108 char_ids_str := RTRIM(char_ids_str, ',');
4109
4110 begin
4111 EXECUTE IMMEDIATE 'Select ''' || char_ids_str || ''',' || cols_str || ' from ' || plan_name ||
4112 ' where collection_id = :collection_id and
4113 occurrence = :occurrence'
4114 INTO p_charid_string,
4115 p_values_string
4116 USING p_collection_id,
4117 p_occurrence;
4118 EXCEPTION when others
4119 then null;
4120 end;
4121 end if;
4122
4123 END build_deref_string;
4124
4125 -- 12.1 QWB Usability Improvements
4126 -- API to replace the Tokens in the error messages
4127 -- with the element prompts
4128 -- ntungare
4129 FUNCTION replace_message_tokens(p_error_message IN VARCHAR2)
4130 RETURN VARCHAR2 AS
4131
4132 token_count NUMBER;
4133 element_prompt VARCHAR2(200);
4134 replaced_message VARCHAR2(2000);
4135 token_postn NUMBER;
4136 BEGIN
4137 SELECT LENGTH(p_error_message) - LENGTH(REPLACE(p_error_message,'&',''))
4138 INTO token_count FROM DUAL;
4139
4140 IF token_count <> 0 THEN
4141 SELECT INSTR(p_error_message,':',1) INTO token_postn FROM DUAL;
4142
4143 SELECT SUBSTR(p_error_message,1,token_postn-1),
4144 SUBSTR(p_error_message,token_postn+1)
4145 INTO element_prompt, replaced_message
4146 FROM DUAL;
4147
4148 SELECT REPLACE(replaced_message,'&'||'CHAR_PROMPT', element_prompt)
4149 INTO replaced_message FROM DUAL;
4150 ELSE
4151 RETURN p_error_message;
4152 END IF;
4153
4154 RETURN replaced_message;
4155 END replace_message_tokens;
4156
4157 -- 12.1 QWB Usability Improvements
4158 -- Method to do the online validations
4159 -- This method would also make a call to the API
4160 -- process_dependent_elements to do the dependent
4161 -- elelemts processing
4162 --
4163 PROCEDURE perform_ssqr_validation (p_plan_id IN VARCHAR2,
4164 p_org_id IN VARCHAR2,
4165 p_spec_id IN VARCHAR2,
4166 p_user_id IN VARCHAR2 DEFAULT NULL,
4167 p_element_id IN VARCHAR2,
4168 p_input_value IN VARCHAR2,
4169 result_string IN VARCHAR2,
4170 id_string IN VARCHAR2,
4171 normalized_attr OUT NOCOPY VARCHAR2,
4172 normalized_id_val OUT NOCOPY VARCHAR2,
4173 message OUT NOCOPY VARCHAR2,
4174 dependent_elements OUT NOCOPY VARCHAR2,
4175 disable_enable_flag_list OUT NOCOPY VARCHAR2,
4176 disabled_dep_elem_vo_attr_lst OUT NOCOPY VARCHAR2)
4177 AS
4178 row_record QA_VALIDATION_API.RowRecord;
4179 result_record QA_VALIDATION_API.ResultRecord;
4180 row_elements QA_VALIDATION_API.ElementsArray;
4181 error_array QA_VALIDATION_API.ErrorArray;
4182 errors_list QA_VALIDATION_API.ErrorArray;
4183 cntr NUMBER;
4184 i NUMBER :=1 ;
4185 message_str VARCHAR2(4000);
4186
4187 l_id_string VARCHAR2(4000);
4188 -- Bug 9382356
4189 -- Modified the length to 32767 so that it can hold more than 1 Comments type elements.
4190 -- Also, added new variable l_input_value to truncate a string to 2000 characters as the
4191 -- limit in row_elements.value is 2000 characters.
4192 -- skolluku
4193 l_result_string VARCHAR2(32767);
4194 l_input_value VARCHAR2(2000);
4195
4196 dep_elements_list VARCHAR2(4000);
4197 dep_flag_list VARCHAR2(4000);
4198 dep_elements_status VARCHAR2(4000);
4199
4200 elements qa_validation_api.ElementsArray;
4201
4202 dependent_elements_arr QA_PARENT_CHILD_PKG.ChildPlanArray;
4203 dep_elements_status_arr QA_PARENT_CHILD_PKG.ChildPlanArray;
4204
4205 disabled_dep_elem_vo_attr VARCHAR2(4000);
4206 disabled_dep_elem_id_attr VARCHAR2(4000);
4207 BEGIN
4208 -- populate the record structures
4209 /*
4210 if result_string is not NULL THEN
4211 elements := qa_validation_api.result_to_array(result_string);
4212 elements := qa_validation_api.id_to_array(id_string, elements);
4213 end if;
4214 */
4215
4216 row_elements(p_element_id).id := p_element_id;
4217 /*
4218 If (elements.COUNT <> 0 AND elements(p_element_id).value IS NOT NULL) THEN
4219 row_elements(p_element_id).value := elements(p_element_id).value;
4220 ELSE
4221 row_elements(p_element_id).value := p_input_value;
4222 END If;
4223 */
4224 -- Bug 9382356. Truncate the value to 2000 and use it instead of p_input_value.
4225 l_input_value := substr(p_input_value,1,2000);
4226 --
4227 -- bug 12375005
4228 -- The input value has the @s doubly encoded. This is done
4229 -- while building the result string. While this is correct for the
4230 -- result string which again would be decoded when its converted
4231 -- into an array, it is not proper for the direct value. So replace
4232 -- the double encoded @s with a sigle one
4233 --
4234 -- row_elements(p_element_id).value := l_input_value;
4235 row_elements(p_element_id).value := replace(l_input_value, '@@','@');
4236
4237 -- Bug 9382356. Use l_input_value instead of p_input_value.
4238 l_result_string := result_string || '@' || p_element_id || '=' || l_input_value;
4239
4240 IF (qa_chars_api.datatype(p_element_id) IN (6,3) AND
4241 p_input_value is NOT NULL) THEN
4242 BEGIN
4243 row_elements(p_element_id).value := QLTDATE.any_to_canon(UPPER(p_input_value));
4244 EXCEPTION WHEN OTHERS THEN
4245 errors_list(1).error_code := invalid_date_error;
4246 errors_list(1).element_id := p_element_id;
4247
4248 QA_SS_RESULTS.get_error_messages(errors_list, p_plan_id,message_str);
4249 message := replace_message_tokens(message_str);
4250 RETURN;
4251 END;
4252 END IF;
4253
4254 row_record.plan_id := p_plan_id;
4255 row_record.org_id := p_org_id;
4256 row_record.spec_id := p_spec_id;
4257 row_record.user_id := p_user_id;
4258
4259 result_record.element_id := p_element_id;
4260
4261 -- call the validate_element api to perform
4262 -- the element validation
4263 error_array := QA_VALIDATION_API.validate_element(
4264 row_elements => row_elements,
4265 row_record => row_record,
4266 element_id => p_element_id,
4267 org_id => p_org_id,
4268 result_holder => result_record);
4269
4270 cntr := error_array.first;
4271
4272 -- build the error list array
4273 while cntr <= error_array.last
4274 loop
4275 if error_array(cntr).error_code <> QA_VALIDATION_API.OK THEN
4276 errors_list(i).element_id := p_element_id;
4277 errors_list(i).error_code := error_array(cntr).error_code;
4278 i := i+1;
4279 END If;
4280 cntr := error_array.next(cntr);
4281 end loop;
4282
4283 -- build the error message string
4284 -- bug 6980226
4285 -- If the element is a HC element then we need to clear
4286 -- the Id value and also disable the dependent elements
4287 -- This is done in the ELSE part
4288 -- ntungare
4289 --
4290 If (QA_VALIDATION_API.no_errors(error_array) = FALSE AND
4291 ((qa_plan_element_api.keyflex(p_element_id) OR
4292 qa_plan_element_api.normalized(p_element_id)) = FALSE)) THEN
4293
4294 QA_SS_RESULTS.get_error_messages(errors_list, p_plan_id, message_str);
4295 message := replace_message_tokens(message_str);
4296
4297 ELSE
4298 -- bug 6980226
4299 -- In case the element is a HC element then the error message
4300 -- needs to be captured if there is any. The dependent elements
4301 -- processing needs to be done in case of an invalid value as well
4302 -- ntungare
4303 --
4304 IF QA_VALIDATION_API.no_errors(error_array) = FALSE THEN
4305 QA_SS_RESULTS.get_error_messages(errors_list, p_plan_id, message_str);
4306 message := replace_message_tokens(message_str);
4307 END IF;
4308
4309 -- Set the normalized value for HC element
4310 IF ((qa_plan_element_api.keyflex(p_element_id) OR
4311 qa_plan_element_api.normalized(p_element_id)) = TRUE) THEN
4312 normalized_id_val := result_record.id;
4313 -- Set the normalized element VO attribute
4314 normalized_attr := qa_chars_api.hardcoded_column(p_element_id);
4315
4316 IF normalized_id_val is NOT NULL THEN
4317 l_id_string := id_string || '@'|| p_element_id || '=' || normalized_id_val;
4318 ELSE
4319 normalized_id_val := 'NULL';
4320 END IF;
4321
4322 l_id_string := LTRIM(l_id_string, '@');
4323 END IF;
4324
4325 -- Process dependent elements
4326 QA_PLAN_ELEMENT_API.process_dependent_elements(
4327 l_result_string,
4328 l_id_string,
4329 p_org_id,
4330 p_plan_id,
4331 p_element_id,
4332 dep_elements_list,
4333 dep_flag_list);
4334
4335 dependent_elements:= dep_elements_list;
4336 disable_enable_flag_list := dep_flag_list;
4337
4338 -- If any dependent element has been disabled then its
4339 -- value needs to be cleared.
4340 --
4341 IF (dependent_elements IS NOT NULL AND
4342 INSTR(disable_enable_flag_list,'D',1,1) <> 0) THEN
4343 -- If the above condition evaluates to true then it means
4344 -- that there are dependent elements that are disabled
4345
4346 -- Representing the enabled and disabled flags as 1 and 2
4347 -- respectively. This is needed since the parse_list API
4348 -- that converts the comma separated strings into arrays
4349 -- works only with number elements
4350 SELECT TRANSLATE(disable_enable_flag_list,'ED','12')
4351 INTO dep_elements_status
4352 FROM DUAL;
4353
4354 QA_PARENT_CHILD_PKG.parse_list(dependent_elements , dependent_elements_arr);
4355 QA_PARENT_CHILD_PKG.parse_list(dep_elements_status, dep_elements_status_arr);
4356
4357 -- Loop though the dependent elements
4358 FOR dep_elem_ctr in 1..dependent_elements_arr.COUNT
4359 LOOP
4360 -- Check if any of them is disabled
4361 IF (dep_elements_status_arr(dep_elem_ctr) = 2) THEN
4362
4363 disabled_dep_elem_vo_attr :=
4364 qa_ak_mapping_api.get_vo_attribute_name(dependent_elements_arr(dep_elem_ctr),
4365 p_plan_id);
4366
4367 IF (disabled_dep_elem_vo_attr IS NOT NULL) THEN
4368 disabled_dep_elem_vo_attr_lst := disabled_dep_elem_vo_attr_lst || ',' ||
4369 disabled_dep_elem_vo_attr;
4370 END IF;
4371
4372 -- Getting the HC id column
4373 disabled_dep_elem_id_attr :=
4374 qa_chars_api.hardcoded_column(dependent_elements_arr(dep_elem_ctr));
4375
4376 IF (disabled_dep_elem_id_attr IS NOT NULL AND
4377 disabled_dep_elem_id_attr <> disabled_dep_elem_vo_attr) THEN
4378 disabled_dep_elem_vo_attr_lst := disabled_dep_elem_vo_attr_lst || ',' ||
4379 disabled_dep_elem_id_attr;
4380 END IF;
4381
4382 disabled_dep_elem_id_attr := NULL;
4383 disabled_dep_elem_vo_attr := NULL;
4384 END IF;
4385 END LOOP;
4386
4387 IF (disabled_dep_elem_vo_attr_lst IS NOT NULL) THEN
4388 disabled_dep_elem_vo_attr_lst := LTRIM(disabled_dep_elem_vo_attr_lst, ',');
4389 END IF;
4390 END IF;
4391 END IF;
4392 END perform_ssqr_validation;
4393
4394
4395 -- 12.1 QWB Usability Improvements
4396 -- method to get the sql string for ResultExportVO
4397 FUNCTION get_export_vo_sql (p_plan_id in NUMBER) Return VARCHAR2 is
4398
4399 CURSOR plan_chars IS
4400 select upper(translate(qc.name,' ''*{}','_____')) name,
4401 qpc.char_id char_id,
4402 qc.datatype
4403 from qa_chars qc,
4404 qa_plan_chars qpc
4405 WHERE qc.char_id = qpc.char_id
4406 AND qpc.plan_id = p_plan_id
4407 ORDER BY qpc.prompt_sequence;
4408
4409 l_sql_stmt VARCHAR2(4000);
4410 l_view_sql VARCHAR2(32767);
4411
4412 l_view_name VARCHAR2(100) := NULL;
4413
4414 l_apps_schema VARCHAR(30) := 'APPS';
4415
4416 CURSOR get_exp_view(p_view_name IN VARCHAR2) IS
4417 SELECT view_name from all_views
4418 WHERE view_name = p_view_name
4419 AND owner = l_apps_schema;
4420
4421 --
4422 -- bug 12596623
4423 --
4424 l_dummy BOOLEAN;
4425 l_fnd CONSTANT VARCHAR2(3) := 'FND';
4426 l_status VARCHAR2(1);
4427 l_industry VARCHAR2(10);
4428 l_schema VARCHAR2(30);
4429
4430 BEGIN
4431 l_sql_stmt := 'select ''N'' as "HideShowStatus" , ';
4432 for rec in plan_chars
4433 loop
4434 l_sql_stmt := l_sql_stmt || rec.name ||', ';
4435 end loop;
4436
4437 l_sql_stmt := l_sql_stmt || 'CREATED_BY, COLLECTION_ID, LAST_UPDATE_DATE, PLAN_ID, OCCURRENCE FROM ';
4438
4439 OPEN get_exp_view('QA_'||p_plan_id||'_EXP_V');
4440 FETCH get_exp_view INTO l_view_name;
4441 CLOSE get_exp_view;
4442
4443 IF l_view_name IS NOT NULL THEN
4444 l_sql_stmt := l_sql_stmt || l_view_name ;
4445 ELSE
4446 --
4447 -- bug 12596623
4448 -- Use the exploded view SQL for export VO instead of using the plan view directly
4449 --
4450 l_view_sql := 'CREATE OR REPLACE FORCE VIEW QA_'||p_plan_id||'_EXP_V AS '||QLTVCREB.get_export_view_sql(p_plan_id);
4451
4452 l_dummy := fnd_installation.get_app_info(l_fnd, l_status, l_industry, l_schema);
4453
4454 ad_ddl.do_ddl(l_schema, 'QA', ad_ddl.create_view, l_view_sql, 'QA_'|| p_plan_id || '_EXP_V');
4455 l_sql_stmt := l_sql_stmt || 'QA_'||p_plan_id||'_EXP_V' ;
4456 END IF;
4457
4458 return l_sql_stmt;
4459
4460 END get_export_vo_sql;
4461
4462
4463
4464 -- 12.1 QWB Usability Improvements
4465 -- Procedure to fire the online actions
4466 -- on elements that have triggers defined
4467 -- for the value not entered conditition
4468 --
4469 FUNCTION processNotEnteredActions (p_plan_id IN NUMBER,
4470 p_spec_id IN NUMBER,
4471 p_ssqr_operation IN NUMBER DEFAULT NULL,
4472 p_row_elements IN OUT NOCOPY ElementsArray,
4473 p_return_results_array IN OUT NOCOPY ResultRecordArray,
4474 message_array OUT NOCOPY MessageArray)
4475 RETURN ErrorArray IS
4476 charctr NUMBER;
4477 ordered_array ElementInfoArray;
4478 ordered_array2 ElementInfoArray;
4479 error_list ErrorArray;
4480 result_holder ResultRecord;
4481
4482 row_error_list ErrorArray;
4483
4484 TYPE action_elements_tab_Typ IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
4485 action_elements_tab action_elements_tab_Typ ;
4486
4487 Cursor cur is
4488 SELECT distinct char_id
4489 FROM qa_plan_char_action_triggers qpt, qa_plan_char_actions qpa
4490 WHERE plan_id = p_plan_id AND
4491 qpt.plan_char_action_trigger_id = qpa.plan_char_action_trigger_id AND
4492 operator = 8;
4493 BEGIN
4494 ordered_array := populate_elements (p_row_elements, p_plan_id);
4495
4496 for c in cur
4497 loop
4498 action_elements_tab(c.char_id) := c.char_id;
4499 end loop;
4500
4501 For cntr in 0..ordered_array.COUNT-1
4502 Loop
4503 -- If the element is in the actions tab then it means
4504 -- the actions for it have not been fired since this tab
4505 -- is specific to elements having online actions defined on
4506 -- operator
4507 IF (action_elements_tab.EXISTS((ordered_array(cntr).id)) AND
4508 p_row_elements(ordered_array(cntr).id).id IS NULL AND
4509 p_row_elements(ordered_array(cntr).id).value IS NULL) THEN
4510
4511 ordered_array(cntr).validation_flag := invalid_element;
4512 ELSE
4513 ordered_array(cntr).validation_flag := action_fired;
4514 END If;
4515 ordered_array2(ordered_array(cntr).id) := ordered_array(cntr);
4516 End Loop;
4517
4518 charctr := p_row_elements.first;
4519
4520 while charctr <= p_row_elements.last
4521 loop
4522 result_holder.element_id := charctr;
4523
4524 -- In case the call is from the self-service application p_ssqr_operation=1
4525 -- then the results_record_arry needs to be populated. This is because in other
4526 -- cases the result array is populated by the validate_row api in qltrsiub
4527 -- which is not called for standalone ssqr operations
4528 --
4529 IF (p_ssqr_operation = 1) THEN
4530 -- Assinging the element Id
4531 p_return_results_array(ordered_array2(charctr).id).element_id :=
4532 ordered_array2(charctr).id;
4533
4534 -- Assinging the element Normalized Id
4535 p_return_results_array(ordered_array2(charctr).id).id :=
4536 p_row_elements(ordered_array2(charctr).id).id;
4537
4538 -- Assinging the Actual data Type
4539 p_return_results_array(ordered_array2(charctr).id).actual_datatype :=
4540 qa_plan_element_api.get_actual_datatype(ordered_array2(charctr).id);
4541
4542 -- Assinging the Deferenced value
4543 p_return_results_array(ordered_array2(charctr).id).canonical_value :=
4544 p_row_elements(ordered_array2(charctr).id).value;
4545
4546 END IF;
4547
4548
4549 if p_return_results_array(ordered_array2(charctr).id).id IS NOT NULL THEN
4550 -- Set the id value
4551 result_holder.id := p_return_results_array(ordered_array2(charctr).id).id;
4552 ELSE
4553 -- Set the canonical value
4554 result_holder.canonical_value := p_return_results_array(ordered_array2(charctr).id).canonical_value;
4555 END If;
4556
4557 result_holder.actual_datatype := qa_plan_element_api.get_actual_datatype(charctr);
4558
4559 IF (NOT (flag_is_set(ordered_array2(charctr).validation_flag,action_fired))) THEN
4560 error_list(6).error_code := fire_immediate_actions (
4561 p_plan_id,
4562 p_spec_id,
4563 ordered_array2(charctr).id,
4564 p_row_elements,
4565 p_return_results_array,
4566 message_array,
4567 result_holder,
4568 ordered_array2,
4569 p_ssqr_operation);
4570 END IF;
4571 append_errors( ordered_array2(charctr).id, error_list, row_error_list);
4572
4573 result_holder.id := NULL;
4574 error_list.delete;
4575
4576 charctr := p_row_elements.next(charctr);
4577 end loop;
4578 RETURN row_error_list;
4579 EXCEPTION WHEN OTHERS THEN
4580 raise;
4581 END processNotEnteredActions;
4582
4583 BEGIN
4584
4585 populate_dependency_matrix;
4586 init_message_map;
4587
4588 END qa_validation_api;