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