DBA Data[Home] [Help]

PACKAGE BODY: APPS.QA_SPECS_PUB

Source


1 PACKAGE BODY qa_specs_pub AS
2 /* $Header: qltpspcb.plb 120.3 2011/05/19 12:23:20 ntungare ship $ */
3 
4 
5 --
6 -- Safe globals.
7 --
8 
9 TYPE qa_specs_table IS TABLE OF qa_specs%ROWTYPE INDEX BY BINARY_INTEGER;
10 g_qa_specs_array   qa_specs_table;
11 
12 g_pkg_name         CONSTANT VARCHAR2(30):= 'qa_specs_pub';
13 g_user_name_cache  fnd_user.user_name%TYPE := NULL;
14 g_user_id_cache    NUMBER;
15 
16 --
17 -- General utility functions
18 --
19 
20 FUNCTION get_user_id(p_name VARCHAR2) RETURN NUMBER IS
21 --
22 -- Decode user name from fnd_user table.
23 --
24     id NUMBER;
25 
26     CURSOR user_cursor IS
27         SELECT user_id
28         FROM fnd_user
29         WHERE user_name = p_name;
30 BEGIN
31 
32 --
33 -- Code is duplicated in qltpspcb.plb.  Any modification here
34 -- should be propagated to that file.
35 --
36 
37     IF p_name IS NULL THEN
38         RETURN nvl(fnd_global.user_id, -1);
39     END IF;
40 
41     --
42     -- It is very common for the same user to call the
43     -- APIs successively.
44     --
45     IF g_user_name_cache = p_name THEN
46         RETURN g_user_id_cache;
47     END IF;
48 
49     OPEN user_cursor;
50     FETCH user_cursor INTO id;
51     IF user_cursor%NOTFOUND THEN
52         CLOSE user_cursor;
53         RETURN -1;
54     END IF;
55     CLOSE user_cursor;
56 
57     g_user_name_cache := p_name;
58     g_user_id_cache := id;
59 
60     RETURN id;
61 END get_user_id;
62 
63 --
64 -- Global caching mechanism.  A global array is used to kept
65 -- all fetched qa_specs.  If the same spec data is required in
66 -- a future call, the cached data will be used.
67 --
68 
69 FUNCTION exists_qa_specs(spec_id IN NUMBER)
70     RETURN BOOLEAN IS
71 
72 BEGIN
73 
74     RETURN g_qa_specs_array.EXISTS(spec_id);
75 
76 END exists_qa_specs;
77 
78 
79 PROCEDURE fetch_qa_specs(spec_id IN NUMBER) IS
80 --
81 -- Retrieve a specification header and cached.
82 --
83     CURSOR c1 (p_id NUMBER) IS
84         SELECT *
85         FROM qa_specs
86         WHERE spec_id = p_id;
87 
88 BEGIN
89     IF NOT exists_qa_specs(spec_id) THEN
90         OPEN c1(spec_id);
91         FETCH c1 INTO g_qa_specs_array(spec_id);
92         CLOSE c1;
93     END IF;
94 END fetch_qa_specs;
95 
96 
97 PROCEDURE fetch_qa_specs(p_spec_name IN VARCHAR2, x_spec_id OUT NOCOPY NUMBER) IS
98 --
99 -- Retrieve a specification header and cached.  Similar to
100 -- the previous function but query by spec name instead of id.
101 --
102     CURSOR c1 IS
103         SELECT *
104         FROM qa_specs
105         WHERE spec_name = p_spec_name;
106 
107     temp qa_specs%ROWTYPE;
108 
109 BEGIN
110     OPEN c1;
111     FETCH c1 INTO temp;
112     IF c1%NOTFOUND THEN
113         CLOSE c1;
114         RETURN;
115     END IF;
116 
117     x_spec_id := temp.spec_id;
118     g_qa_specs_array(x_spec_id) := temp;
119     CLOSE c1;
120 END fetch_qa_specs;
121 
122 
123 FUNCTION item_id(spec_id IN NUMBER)
124     RETURN NUMBER IS
125 
126 BEGIN
127 
128     fetch_qa_specs(spec_id);
129     IF NOT exists_qa_specs(spec_id) THEN
130         RETURN NULL;
131     END IF;
132     RETURN g_qa_specs_array(spec_id).item_id;
133 
134 END item_id;
135 
136 
137 FUNCTION organization_id(spec_id IN NUMBER)
138     RETURN NUMBER IS
139 
140 BEGIN
141 
142     fetch_qa_specs(spec_id);
143     IF NOT exists_qa_specs(spec_id) THEN
144         RETURN NULL;
145     END IF;
146     RETURN g_qa_specs_array(spec_id).organization_id;
147 
148 END organization_id;
149 
150 
151 FUNCTION spec_name(spec_id IN NUMBER)
152     RETURN VARCHAR2 IS
153 
154 BEGIN
155 
156     fetch_qa_specs(spec_id);
157     IF NOT exists_qa_specs(spec_id) THEN
158         RETURN NULL;
159     END IF;
160     RETURN g_qa_specs_array(spec_id).spec_name;
161 
162 END spec_name;
163 
164 
165 FUNCTION category_set_id(spec_id IN NUMBER)
166     RETURN NUMBER IS
167 
168 BEGIN
169 
170     fetch_qa_specs(spec_id);
171     IF NOT exists_qa_specs(spec_id) THEN
172         RETURN NULL;
173     END IF;
174     RETURN g_qa_specs_array(spec_id).category_set_id;
175 
176 END category_set_id;
177 
178 
179 FUNCTION category_id(spec_id IN NUMBER)
180     RETURN NUMBER IS
181 
182 BEGIN
183 
184     fetch_qa_specs(spec_id);
185     IF NOT exists_qa_specs(spec_id) THEN
186         RETURN NULL;
187     END IF;
188     RETURN g_qa_specs_array(spec_id).category_id;
189 
190 END category_id;
191 
192 
193 FUNCTION item_revision(spec_id IN NUMBER)
194     RETURN VARCHAR2 IS
195 
196 BEGIN
197 
198     fetch_qa_specs(spec_id);
199     IF NOT exists_qa_specs(spec_id) THEN
200         RETURN NULL;
201     END IF;
202     RETURN g_qa_specs_array(spec_id).item_revision;
203 
204 END item_revision;
205 
206 
207 FUNCTION vendor_id(spec_id IN NUMBER)
208     RETURN NUMBER IS
209 
210 BEGIN
211 
212     fetch_qa_specs(spec_id);
213     IF NOT exists_qa_specs(spec_id) THEN
214         RETURN NULL;
215     END IF;
216     RETURN g_qa_specs_array(spec_id).vendor_id;
217 
218 END vendor_id;
219 
220 
221 FUNCTION customer_id(spec_id IN NUMBER)
222     RETURN NUMBER IS
223 
224 BEGIN
225 
226     fetch_qa_specs(spec_id);
227     IF NOT exists_qa_specs(spec_id) THEN
228         RETURN NULL;
229     END IF;
230     RETURN g_qa_specs_array(spec_id).customer_id;
231 
232 END customer_id;
233 
234 
235 FUNCTION char_id(spec_id IN NUMBER)
236     RETURN NUMBER IS
237 
238 BEGIN
239 
240     fetch_qa_specs(spec_id);
241     IF NOT exists_qa_specs(spec_id) THEN
242         RETURN NULL;
243     END IF;
244     RETURN g_qa_specs_array(spec_id).char_id;
245 
246 END char_id;
247 
248 
249 FUNCTION spec_element_value(spec_id IN NUMBER)
250     RETURN VARCHAR2  IS
251 
252 BEGIN
253 
254     fetch_qa_specs(spec_id);
255     IF NOT exists_qa_specs(spec_id) THEN
256         RETURN NULL;
257     END IF;
258     RETURN g_qa_specs_array(spec_id).spec_element_value;
259 
260 END spec_element_value;
261 
262 
263 FUNCTION get_context_element_id(p_element_name IN VARCHAR2)
264     RETURN NUMBER IS
265 
266     CURSOR c IS
267         SELECT char_id
268         FROM   qa_chars
269         WHERE  char_context_flag = 1 AND
270                enabled_flag = 1 AND
271                name = p_element_name;
272 
273     l_char_id NUMBER;
274 
275 BEGIN
276 
277     OPEN c;
278     FETCH c INTO l_char_id;
279     IF c%NOTFOUND THEN
280         CLOSE c;
281         fnd_message.set_name('QA', 'QA_API_INVALID_ELEMENT');
282         fnd_msg_pub.add();
283         RAISE fnd_api.g_exc_error;
284     END IF;
285 
286     CLOSE c;
287     RETURN l_char_id;
288 
289 END get_context_element_id;
290 
291 --
292 -- The child specs inherit all the spec elements of the master.
293 --
294 -- rkunchal
295 --
296 
297 PROCEDURE check_for_spec_element(p_spec_id IN NUMBER) IS
298 
299     CURSOR c IS
300         SELECT 1
301         FROM qa_spec_chars qsc, qa_specs qs
302         WHERE qs.spec_id = p_spec_id
303         AND qs.common_spec_id = qsc.spec_id;
304 
305     l_dummy     NUMBER;
306     l_found     BOOLEAN;
307 
308 BEGIN
309 
310     OPEN c;
311     FETCH c INTO l_dummy;
312     l_found := c%FOUND;
313     CLOSE c;
314 
315     IF NOT l_found THEN
316         fnd_message.set_name('QA', 'QA_API_SPEC_MUST_HAVE_CHARS');
317         fnd_msg_pub.add();
318         RAISE fnd_api.g_exc_error;
319     END IF;
320 
321 END check_for_spec_element;
322 
323 
324 FUNCTION get_revision_flag(p_item_id IN NUMBER, p_org_id IN NUMBER)
325     RETURN NUMBER IS
326 
327     CURSOR c IS
328         SELECT revision_qty_control_code
329         from mtl_system_items
330         where inventory_item_id = p_item_id
331         and organization_id = p_org_id;
332 
333     l_revision_flag NUMBER;
334 
335 BEGIN
336 
337     OPEN c;
338     FETCH c INTO l_revision_flag;
339     CLOSE c;
340 
341     RETURN l_revision_flag;
342 
343 END get_revision_flag;
344 
345 
346 FUNCTION process_item_and_revision(p_item_name IN VARCHAR2, p_item_revision
347     IN VARCHAR2, p_org_id IN NUMBER) RETURN NUMBER IS
348 
349     l_item_id   NUMBER;
350     l_revision_flag NUMBER;
351 
352 BEGIN
353 
354     l_item_id := qa_flex_util.get_item_id(p_org_id, p_item_name);
355 
356     IF (l_item_id IS NULL) THEN
357         fnd_message.set_name('QA', 'QA_API_INVALID_ITEM_NAME');
358         fnd_msg_pub.add();
359         RAISE fnd_api.g_exc_error;
360     ELSE
361         l_revision_flag := get_revision_flag(l_item_id, p_org_id);
362         IF (l_revision_flag = 1) THEN
363 
364             IF (p_item_revision IS NOT NULL)  THEN
365                 fnd_message.set_name('QA', 'QA_API_REVISION_CONTROLLED');
366                 fnd_msg_pub.add();
367                 RAISE fnd_api.g_exc_error;
368             END IF;
369 
370         ELSIF (l_revision_flag = 2) and (p_item_revision IS NULL)  THEN
371             fnd_message.set_name('QA', 'QA_API_MANDATORY_REVISION');
372             fnd_msg_pub.add();
373             RAISE fnd_api.g_exc_error;
374 
375         ELSE
376             IF NOT qa_plan_element_api.validate_revision(p_org_id,
377                 l_item_id, p_item_revision) THEN
378                 fnd_message.set_name('QA', 'QA_API_INVALID_REVISION');
379                 fnd_msg_pub.add();
380                 RAISE fnd_api.g_exc_error;
381             END IF;
382         END IF;
383     END IF;
384 
385     RETURN l_item_id;
386 
387 END;
388 
389 
390 PROCEDURE validate_datatype(p_value IN VARCHAR2, p_datatype NUMBER) IS
391 
392     temp_number Number;
393     temp_date Date;
394 
395 BEGIN
396 
397     IF p_value IS NULL THEN
398         RETURN;
399     END IF;
400 
401     IF p_datatype = qa_ss_const.number_datatype THEN
402         BEGIN
403             temp_number := to_number(p_value);
404         EXCEPTION WHEN OTHERS THEN
405             fnd_message.set_name('QA', 'QA_INVALID_NUMBER');
406             fnd_msg_pub.add();
407             RAISE fnd_api.g_exc_error;
408         END;
409 
410     ELSIF p_datatype = qa_ss_const.date_datatype THEN
411         BEGIN
412             temp_date := qltdate.any_to_date(p_value);
413         EXCEPTION WHEN OTHERS THEN
414             fnd_message.set_name('QA', 'QA_INVALID_DATE');
415             fnd_msg_pub.add();
416             RAISE fnd_api.g_exc_error;
417         END;
418     END IF;
419 
420 END validate_datatype;
421 
422 
423 FUNCTION combination_exists(
424     p_category_set_id           IN NUMBER,
425     p_category_id               IN NUMBER,
426     p_item_id                   IN NUMBER,
427     p_item_revision             IN VARCHAR2,
428     p_org_id                    IN NUMBER,
429     p_vendor_id                 IN NUMBER,
430     p_customer_id               IN NUMBER,
431     p_char_id                   IN NUMBER,
432     p_sub_type_element_value    IN VARCHAR2,
433     x_spec_name                 OUT NOCOPY VARCHAR2)
434     RETURN BOOLEAN IS
435 
436     l_spec_name varchar2(30);
437 
438     CURSOR c IS
439         SELECT spec_name
440         FROM qa_specs
441         WHERE category_set_id = p_category_set_id
442             AND category_id = p_category_id
443             AND item_id = p_item_id
444             AND item_revision = nvl(p_item_revision, 'NONE')
445             AND organization_id = p_org_id
446             AND vendor_id = p_vendor_id
447             AND customer_id = p_customer_id
448             AND char_id = p_char_id
449             AND spec_element_value = p_sub_type_element_value;
450 
451     result BOOLEAN;
452     dummy  VARCHAR2(30);
453 
454 BEGIN
455 
456     OPEN c;
457     FETCH c INTO x_spec_name;
458     result := c%FOUND;
459     CLOSE c;
460 
461     RETURN result;
462 
463 END combination_exists;
464 
465 
466 FUNCTION get_category_set_id(
467     p_category_set_name IN VARCHAR2,
468     x_structure_id OUT NOCOPY NUMBER,
469     x_validate_flag OUT NOCOPY mtl_category_sets.validate_flag%TYPE)
470     RETURN NUMBER IS
471 
472     CURSOR c IS
473         SELECT category_set_id, structure_id, validate_flag
474         FROM mtl_category_sets
475         WHERE category_set_name = p_category_set_name;
476 
477     l_category_set_id NUMBER;
478 
479 BEGIN
480 
481     OPEN c;
482     FETCH c INTO l_category_set_id, x_structure_id, x_validate_flag;
483     CLOSE c;
484 
485     IF (l_category_set_id IS NULL) THEN
486         fnd_message.set_name('QA', 'QA_API_INVALID_CATEGORY_SET');
487         fnd_msg_pub.add();
488         RAISE fnd_api.g_exc_error;
489     END IF;
490 
491     RETURN l_category_set_id;
492 
493 END get_category_set_id;
494 
495 
496 FUNCTION get_category_id(
497     p_category_name IN VARCHAR2,
498     p_category_set_id IN NUMBER,
499     p_org_id IN NUMBER,
500     p_structure_id IN NUMBER,
501     p_validate_flag mtl_category_sets.validate_flag%TYPE)
502     RETURN NUMBER IS
503 
504     -- Bug 2532177. Removed the Default value for l_category_id variable.
505     l_category_id NUMBER;
506     l_where_clause VARCHAR2(500);
507 
508 BEGIN
509 
510     IF p_validate_flag = 'Y' THEN
511         l_where_clause :=
512             '(nvl(disable_date, sysdate+1) > sysdate) AND category_id IN
513              (SELECT category_id
514               FROM mtl_category_set_valid_cats vc
515               WHERE vc.category_set_id = ' || p_category_set_id || ')';
516     ELSE
517         l_where_clause := '(nvl(disable_date, sysdate+1) > sysdate)';
518     END IF;
519 
520     IF FND_FLEX_KEYVAL.validate_segs(
521         operation => 'CHECK_COMBINATION',
522         key_flex_code => 'MCAT',
523         appl_short_name => 'INV',
524         structure_number => p_structure_id,
525         concat_segments => p_category_name,
526         data_set => p_structure_id,
527         where_clause => l_where_clause) THEN
528 
529         l_category_id := FND_FLEX_KEYVAL.combination_id;
530     END IF;
531 
532     IF (l_category_id IS NULL) THEN
533         fnd_message.set_name('QA', 'QA_API_INVALID_CATEGORY');
534         fnd_msg_pub.add();
535         RAISE fnd_api.g_exc_error;
536     END IF;
537 
538     RETURN l_category_id;
539 
540 END get_category_id;
541 
542 
543 FUNCTION get_spec_id(p_spec_name IN VARCHAR2, p_org_code IN VARCHAR2)
544     RETURN NUMBER IS
545 
546     l_spec_id NUMBER;
547     l_org_id  NUMBER;
548 
549     CURSOR c IS
550         SELECT spec_id
551         FROM qa_specs
552         WHERE spec_name = p_spec_name AND organization_id = l_org_id;
553 
554 BEGIN
555 
556     l_org_id := qa_plans_api.get_org_id(p_org_code);
557 
558     OPEN c;
559     FETCH c INTO l_spec_id;
560 
561     IF c%NOTFOUND THEN
562         CLOSE c;
563         fnd_message.set_name('QA', 'QA_API_SPEC_NAME_NOT_FOUND');
564         fnd_msg_pub.add();
565         RAISE fnd_api.g_exc_error;
566     END IF;
567 
568     CLOSE c;
569 
570     RETURN l_spec_id;
571 
572 END get_spec_id;
573 
574 
575 FUNCTION spec_exists(p_name IN VARCHAR2)
576     RETURN BOOLEAN IS
577 
578     CURSOR c IS
579         SELECT 1
580         FROM  qa_specs
581         WHERE spec_name = p_name;
582 
583     result BOOLEAN;
584     dummy NUMBER;
585 
586 BEGIN
587 
588     OPEN c;
589     FETCH c INTO dummy;
590     result := c%FOUND;
591     CLOSE c;
592 
593     RETURN result;
594 
595 END spec_exists;
596 
597 
598 FUNCTION spec_element_exists(p_spec_id IN VARCHAR2, p_char_id IN NUMBER)
599     RETURN BOOLEAN IS
600 
601     CURSOR c IS
602         SELECT 1
603         FROM  qa_spec_chars
604         WHERE spec_id = p_spec_id AND char_id = p_char_id;
605 
606     result BOOLEAN;
607     dummy NUMBER;
608 
609 BEGIN
610 
611     OPEN c;
612     FETCH c INTO dummy;
613     result := c%FOUND;
614     CLOSE c;
615 
616     RETURN result;
617 
618 END spec_element_exists;
619 
620 
621 FUNCTION convert_flag(p_flag IN VARCHAR2)
622     RETURN NUMBER IS
623 
624 BEGIN
625 
626     IF p_flag = fnd_api.g_true THEN
627         RETURN 1;
628     END IF;
629 
630     RETURN 2;
631 
632 END convert_flag;
633 
634 
635 --
636 -- Global Specifications Enhancements
637 -- Introduced the following internal functions
638 -- Both are overloaded for ease of use
639 --
640 -- Extremely useful to change the API to support
641 -- Global Specifications Enhancements
642 --
643 -- rkunchal
644 --
645 -- is_child_spec returns true if the passed spec is a child spec.
646 -- child_spec_exists returns true if the passed spec is being
647 --   referenced by at least one more spec.
648 --
649 
650 FUNCTION is_child_spec(p_spec_id IN NUMBER) RETURN BOOLEAN IS
651 
652   CURSOR c IS
653      SELECT 1
654      FROM   qa_specs
655      WHERE  spec_id = p_spec_id
656      AND    spec_id <> common_spec_id;
657 
658   result BOOLEAN;
659   dummy  NUMBER;
660 
661 BEGIN
662 
663   OPEN c;
664   FETCH c INTO dummy;
665   result := c%FOUND;
666   CLOSE c;
667 
668   RETURN result;
669 
670 END is_child_spec;
671 
672 FUNCTION is_child_spec(p_spec_name IN VARCHAR2) RETURN BOOLEAN IS
673 
674   CURSOR c IS
675      SELECT 1
676      FROM   qa_specs
677      WHERE  spec_name = p_spec_name
678      AND    spec_id <> common_spec_id;
679 
680   result BOOLEAN;
681   dummy  NUMBER;
682 
683 BEGIN
684 
685   OPEN c;
686   FETCH c INTO dummy;
687   result := c%FOUND;
688   CLOSE c;
689 
690   RETURN result;
691 
692 END is_child_spec;
693 
694 FUNCTION child_spec_exists(p_spec_id IN NUMBER) RETURN BOOLEAN IS
695 
696   CURSOR c IS
697      SELECT 1
698      FROM   qa_specs
699      WHERE  common_spec_id = p_spec_id
700      AND    spec_id <> common_spec_id;
701 
702   result BOOLEAN;
703   dummy  NUMBER;
704 
705 BEGIN
706 
707   OPEN c;
708   FETCH c INTO dummy;
709   result := c%FOUND;
710   CLOSE c;
711 
712   RETURN result;
713 
714 END child_spec_exists;
715 
716 FUNCTION child_spec_exists(p_spec_name IN VARCHAR2) RETURN BOOLEAN IS
717 
718   CURSOR c IS
719      SELECT 1
720      FROM   qa_specs qs1, qa_specs qs2
721      WHERE  qs1.spec_name = p_spec_name
722      AND    qs1.spec_id = qs2.common_spec_id
723      AND    qs2.spec_id <> qs2.common_spec_id;
724 
725   result BOOLEAN;
726   dummy  NUMBER;
727 
728 BEGIN
729 
730   OPEN c;
731   FETCH c INTO dummy;
732   result := c%FOUND;
733   CLOSE c;
734 
735   RETURN result;
736 
737 END child_spec_exists;
738 
739 --
740 --
741 --  Start of Public APIs
742 --
743 
744 --
745 -- Add a new argument to pass common_spec_id also.
746 -- This API can be used to create a referencing spec (child spec) also.
747 -- Additional validation for a referencing spec is, to check if
748 -- the referenced spec is a master or not.
749 --
750 
751 PROCEDURE create_specification(
752     p_api_version               IN  NUMBER,
753     p_init_msg_list             IN  VARCHAR2  := fnd_api.g_false,
754     p_validation_level          IN  NUMBER    := fnd_api.G_VALID_LEVEL_FULL,
755     p_user_name                 IN  VARCHAR2  := NULL,
756     p_spec_name                 IN  VARCHAR2,
757     p_organization_code         IN  VARCHAR2,
758     p_reference_spec            IN  VARCHAR2  := NULL,
759     p_effective_from            IN  DATE      := SYSDATE,
760     p_effective_to              IN  DATE      := NULL,
761     p_assignment_type           IN  NUMBER    := qa_specs_pub.g_spec_type_item,
762     p_category_set_name         IN  VARCHAR2  := NULL,
763     p_category_name             IN  VARCHAR2  := NULL,
764     p_item_name                 IN  VARCHAR2  := NULL,
765     p_item_revision             IN  VARCHAR2  := NULL,
766     p_supplier_name             IN  VARCHAR2  := NULL,
767     p_customer_name             IN  VARCHAR2  := NULL,
768     p_sub_type_element          IN  VARCHAR2  := NULL,
769     p_sub_type_element_value    IN  VARCHAR2  := NULL,
770     x_spec_id                   OUT NOCOPY NUMBER,
771     x_msg_count                 OUT NOCOPY NUMBER,
772     x_msg_data                  OUT NOCOPY VARCHAR2,
773     x_return_status             OUT NOCOPY VARCHAR2,
774     -- Bug 7430441.FP for Bug 6877858.
775     -- Added the attribute parameters in order to populate the DFF
776     -- fields too into the qa_specs table
777     -- pdube Wed Sep 24 03:17:03 PDT 2008
778     p_attribute_category        IN VARCHAR2 := NULL,
779     p_attribute1                IN VARCHAR2 := NULL,
780     p_attribute2                IN VARCHAR2 := NULL,
781     p_attribute3                IN VARCHAR2 := NULL,
782     p_attribute4                IN VARCHAR2 := NULL,
783     p_attribute5                IN VARCHAR2 := NULL,
784     p_attribute6                IN VARCHAR2 := NULL,
785     p_attribute7                IN VARCHAR2 := NULL,
786     p_attribute8                IN VARCHAR2 := NULL,
787     p_attribute9                IN VARCHAR2 := NULL,
788     p_attribute10               IN VARCHAR2 := NULL,
789     p_attribute11               IN VARCHAR2 := NULL,
790     p_attribute12               IN VARCHAR2 := NULL,
791     p_attribute13               IN VARCHAR2 := NULL,
792     p_attribute14               IN VARCHAR2 := NULL,
793     p_attribute15               IN VARCHAR2 := NULL,
794     --
795     -- bug 12538300
796     -- Added 2 new attributes to set the supplier and customer
797     -- uniquely using the ids, in case there are duplicate names
798     --
799     p_supplier_id               IN NUMBER   := NULL,
800     p_customer_id               IN NUMBER   := NULL) IS
801 
802     l_api_name          CONSTANT VARCHAR2(30)   := 'create_specification_pub';
803     l_api_version       CONSTANT NUMBER         := 1.0;
804 
805     l_user_id                   NUMBER;
806     l_org_id                    NUMBER := -1;
807     l_category_set_id           NUMBER := -1;
808     l_category_id               NUMBER := -1;
809     l_structure_id              NUMBER;
810     l_validate_flag             mtl_category_sets.validate_flag%TYPE;
811     l_item_id                   NUMBER := -1;
812     l_vendor_id                 NUMBER := -1;
813     l_customer_id               NUMBER := -1;
814     l_char_id                   NUMBER := -1;
815     l_sub_type_value            qa_specs.spec_element_value%TYPE;
816     l_existing_spec_name        VARCHAR2(30);
817     l_datatype                  NUMBER;
818 
819     l_reference_spec_id            NUMBER;
820 
821     --BUG 3500244
822     --we do NOT support ERES in APIs as documented in QA FDA HLD
823     --so this should behave as though ERES profile is No
824     --which means spec_status of 40 which is No Approval Reqd
825     --should be used for spec creation since it is a NON-Null Column
826     l_spec_status                  NUMBER := 40;
827 
828 
829     CURSOR c IS
830       SELECT spec_id
831       FROM   qa_specs
832       WHERE  spec_name = p_reference_spec;
833 
834 
835     -- bug 12538300
836     l_validate_vendor             NUMBER := 0;
837     l_validate_customer           NUMBER := 0;
838 
839 BEGIN
840 
841     -- Standard Start of API savepoint
842 
843     SAVEPOINT create_specification_pub;
844 
845     -- Standard call to check for call compatibility.
846     IF NOT fnd_api.compatible_api_call (
847         l_api_version,
848         p_api_version,
849         l_api_name,
850         g_pkg_name) THEN
851         RAISE fnd_api.g_exc_unexpected_error;
852     END IF;
853 
854     -- Initialize message list if p_init_msg_list is set to TRUE.
855     IF fnd_api.to_boolean(p_init_msg_list) THEN
856         fnd_msg_pub.initialize;
857     END IF;
858 
859 
860     --  Initialize API return status to success
861     x_return_status := fnd_api.g_ret_sts_success;
862 
863     l_user_id := get_user_id(p_user_name);
864     IF l_user_id = -1 THEN
865         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
866         fnd_msg_pub.add();
867         raise fnd_api.g_exc_error;
868     END IF;
869 
870     -- Algorithm
871     --
872     --
873     -- 0. Check for duplicate name
874     --
875     -- 0.5 If the reference_spec is passed, verify if that spec exists and is not a
876     --     referencing any other spec.
877     --
878     -- 1. convert org code to org id
879     --
880     -- 2. validate the effective FROM and TO dates
881     --
882     -- 3.
883     --    if assignment type is supplier then
884     --        validate vendor and generate id
885     --    else if assignment type is customer then
886     --        validate customer and generate id
887     --    end if;
888     --
889     -- 4.
890     --    if item is given then
891     --        validate item and generate id
892     --        validate revision if provided
893     --    else if category set name is given then
894     --        validate category set name and generate id
895     --    else
896     --        generate an error
897     --    end if;
898     --
899     -- 5. if there is spec sub type provided (element) then
900     --    convert it into id
901     --
902     -- 6. Check for existing combination.
903     --
904     -- 7. generate spec id
905     --
906     -- 8. insert the row
907 
908     IF (spec_exists(p_spec_name)) THEN
909         fnd_message.set_name('QA', 'QA_API_DUPLICATE_SPEC_NAME');
910         fnd_msg_pub.add();
911         RAISE fnd_api.g_exc_error;
912     END IF;
913 
914     -- See if the spec exists with p_common_spec_name
915     IF p_reference_spec IS NOT NULL AND NOT spec_exists(p_reference_spec) THEN
916         fnd_message.set_name('QA', 'QA_SPEC_NOT_EXISTS');
917         fnd_message.set_token('ENTITY1', p_reference_spec);
918         fnd_msg_pub.add();
919         RAISE fnd_api.g_exc_error;
920     END IF;
921 
922     -- Force not to reference a child spec if common_spec_name is passed
923     IF p_reference_spec IS NOT NULL AND is_child_spec(p_reference_spec) THEN
924         fnd_message.set_name('QA', 'QA_CANNOT_REFER_CHILD_SPEC');
925         fnd_msg_pub.add();
926         RAISE fnd_api.g_exc_error;
927     END IF;
928 
929     l_org_id := qa_plans_api.get_org_id(p_organization_code);
930 
931     IF (l_org_id IS NULL) THEN
932         fnd_message.set_name('QA', 'QA_API_INVALID_ORG_CODE');
933         fnd_msg_pub.add();
934         RAISE fnd_api.g_exc_error;
935     END IF;
936 
937     IF (p_effective_to IS NOT NULL) THEN
938         IF (p_effective_to < p_effective_from) THEN
939             fnd_message.set_name('QA', 'QA_EFFECTIVE_DATE_RANGE');
940             fnd_msg_pub.add();
941             RAISE fnd_api.g_exc_error;
942         END IF;
943     END IF;
944 
945     IF (p_assignment_type = g_spec_type_item) THEN
946         NULL; -- nothing special needs to be done for item spec.
947 
948     ELSIF (p_assignment_type = g_spec_type_supplier) THEN
949         --
950         -- bug 12538300
951         -- If the supplier id is passed then it should take precedence
952         --
953         IF (p_supplier_id IS NULL) THEN
954            l_vendor_id := qa_plan_element_api.get_supplier_id(p_supplier_name);
955         ELSE
956            -- Validate vendor
957 	   SELECT count(*) into l_validate_vendor
958              FROM po_vendors
959            WHERE vendor_id = p_supplier_id
960 	     AND nvl(end_date_active, sysdate + 1) > sysdate;
961 
962 	   IF l_validate_vendor = 0 THEN
963               l_vendor_id := NULL;
964            ELSE
965  	      l_vendor_id := p_supplier_id;
966 	   END IF;
967 	END IF;
968 
969         IF (l_vendor_id IS NULL) THEN
970             fnd_message.set_name('QA', 'QA_API_INVALID_VENDOR_NAME');
971             fnd_msg_pub.add();
972             RAISE fnd_api.g_exc_error;
973         END IF;
974 
975     ELSIF (p_assignment_type = g_spec_type_customer) THEN
976         --
977         -- bug 12538300
978         -- If the customer id is passed then it should take precedence
979         --
980         IF (p_customer_id IS NULL) THEN
981            l_customer_id := qa_plan_element_api.get_customer_id(p_customer_name);
982         ELSE
983            -- Validate customer
984 	   SELECT count(*) into l_validate_customer
985              FROM qa_customers_lov_v
986            WHERE customer_id = p_customer_id
987 	     AND status = 'A'
988 	     AND nvl(customer_prospect_code, 'CUSTOMER') = 'CUSTOMER';
989 
990 	   IF l_validate_customer = 0 THEN
991               l_customer_id := NULL;
992            ELSE
993  	      l_customer_id := p_customer_id;
994 	   END IF;
995 
996         END IF;
997 
998         IF (l_customer_id IS NULL) THEN
999             fnd_message.set_name('QA', 'QA_API_INVALID_CUSTOMER_NAME');
1000             fnd_msg_pub.add();
1001             RAISE fnd_api.g_exc_error;
1002         END IF;
1003 
1004     ELSE
1005         fnd_message.set_name('QA', 'QA_API_INVALID_ASSIGNMENT_TYPE');
1006         fnd_msg_pub.add();
1007         RAISE fnd_api.g_exc_error;
1008     END IF;
1009 
1010     IF (p_item_name IS NOT NULL) THEN
1011         l_item_id := process_item_and_revision(p_item_name, p_item_revision,
1012             l_org_id);
1013     ELSE
1014         l_category_set_id := get_category_set_id(
1015             p_category_set_name, l_structure_id, l_validate_flag);
1016         l_category_id := get_category_id(p_category_name,
1017             l_category_set_id, l_org_id, l_structure_id, l_validate_flag);
1018     END IF;
1019 
1020     IF (p_sub_type_element IS NOT NULL) THEN
1021         l_sub_type_value := p_sub_type_element_value;
1022         l_char_id := qa_chars_api.get_element_id(p_sub_type_element);
1023  /* Fix for bug 3216242 - Check to ensure sub_type_element is a valid collection element.Hence, l_char_id should be not NULL for valid case.Added the following IF-ELSE condition.
1024  */
1025         IF (l_char_id IS NOT NULL) THEN
1026             l_datatype := qa_chars_api.datatype(l_char_id);
1027             validate_datatype(l_sub_type_value, l_datatype);
1028         ELSE
1029            fnd_message.set_name('QA', 'QA_API_INVALID_ELEMENT');
1030            fnd_msg_pub.add();
1031            RAISE fnd_api.g_exc_error;
1032         END IF;
1033     ELSE
1034         l_char_id := -1;
1035         l_sub_type_value := '-1';
1036     END IF;
1037 
1038     IF (combination_exists(l_category_set_id, l_category_id, l_item_id,
1039         p_item_revision, l_org_id, l_vendor_id, l_customer_id, l_char_id,
1040         l_sub_type_value, l_existing_spec_name)) THEN
1041 
1042         fnd_message.set_name('QA', 'QA_SPEC_COMBINATION_EXISTS');
1043         fnd_message.set_token('ENTITY1', l_existing_spec_name);
1044         fnd_msg_pub.add();
1045         RAISE fnd_api.g_exc_error;
1046     END IF;
1047 
1048     SELECT qa_specs_s.nextval INTO x_spec_id FROM DUAL;
1049 
1050     IF p_reference_spec IS NOT NULL THEN
1051        OPEN c;
1052        FETCH c INTO l_reference_spec_id;
1053        CLOSE c;
1054     ELSE
1055        l_reference_spec_id := x_spec_id;
1056     END IF;
1057 
1058     INSERT INTO qa_specs(
1059         spec_id,
1060         last_update_date,
1061         last_updated_by,
1062         creation_date,
1063         created_by,
1064         last_update_login,
1065         spec_name,
1066         organization_id,
1067         effective_from,
1068         effective_to,
1069         common_spec_id,
1070         assignment_type,
1071         category_set_id,
1072         category_id,
1073         item_id,
1074         item_revision,
1075         vendor_id,
1076         customer_id,
1077         hide_plan_chars_flag,
1078         char_id,
1079         spec_element_value,
1080 	spec_status,       --Bug 3500244
1081         attribute_category, -- Bug 7430441
1082         attribute1,
1083         attribute2,
1084         attribute3,
1085         attribute4,
1086         attribute5,
1087         attribute6,
1088         attribute7,
1089         attribute8,
1090         attribute9,
1091         attribute10,
1092         attribute11,
1093         attribute12,
1094         attribute13,
1095         attribute14,
1096         attribute15 )
1097     VALUES(
1098         x_spec_id,
1099         sysdate,
1100         l_user_id,
1101         sysdate,
1102         l_user_id,
1103         l_user_id,
1104         p_spec_name,
1105         l_org_id,
1106         p_effective_from,
1107         p_effective_to,
1108         l_reference_spec_id,
1109         p_assignment_type,
1110         l_category_set_id,
1111         l_category_id,
1112         l_item_id,
1113         nvl(p_item_revision, 'NONE'),
1114         l_vendor_id,
1115         l_customer_id,
1116         1,
1117         l_char_id,
1118         l_sub_type_value,
1119 	l_spec_status,  --Bug 3500244
1120         p_attribute_category , -- Bug 7430441
1121         p_attribute1 ,
1122         p_attribute2 ,
1123         p_attribute3 ,
1124         p_attribute4 ,
1125         p_attribute5 ,
1126         p_attribute6 ,
1127         p_attribute7 ,
1128         p_attribute8 ,
1129         p_attribute9 ,
1130         p_attribute10,
1131         p_attribute11,
1132         p_attribute12,
1133         p_attribute13,
1134         p_attribute14,
1135         p_attribute15 );
1136 
1137 EXCEPTION
1138 
1139     WHEN fnd_api.g_exc_error THEN
1140         ROLLBACK TO create_specification_pub;
1141         x_return_status := fnd_api.g_ret_sts_error;
1142         fnd_msg_pub.count_and_get(
1143             p_count => x_msg_count,
1144             p_data  => x_msg_data
1145         );
1146 
1147      WHEN fnd_api.g_exc_unexpected_error THEN
1148         ROLLBACK TO create_specification_pub;
1149         x_return_status := fnd_api.g_ret_sts_unexp_error;
1150         fnd_msg_pub.count_and_get(
1151             p_count => x_msg_count,
1152             p_data  => x_msg_data
1153         );
1154 
1155      WHEN OTHERS THEN
1156         -- dbms_output.put_line(SQLCODE || SQLERRM);
1157         ROLLBACK TO create_specification_pub;
1158         x_return_status := fnd_api.g_ret_sts_unexp_error;
1159         IF fnd_msg_pub.Check_Msg_Level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1160             fnd_msg_pub.Add_Exc_Msg(g_pkg_name, l_api_name);
1161         END IF;
1162         fnd_msg_pub.count_and_get(
1163             p_count => x_msg_count,
1164             p_data  => x_msg_data
1165         );
1166 
1167 END create_specification;
1168 
1169 --
1170 -- Adding spec elements is not allowed for child specs
1171 -- We would throw the same error if attempted.
1172 --
1173 -- rkunchal
1174 --
1175 
1176 PROCEDURE add_spec_element(
1177     p_api_version               IN      NUMBER,
1178     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1179     p_validation_level          IN      NUMBER   := fnd_api.G_VALID_LEVEL_FULL,
1180     p_user_name                 IN      VARCHAR2 := NULL,
1181     p_spec_name                 IN      VARCHAR2,
1182     p_organization_code         IN      VARCHAR2,
1183     p_element_name              IN      VARCHAR2,
1184     p_uom_code                  IN      VARCHAR2 := NULL,
1185     p_enabled_flag              IN      VARCHAR2 := fnd_api.g_true,
1186     p_target_value              IN      VARCHAR2 := NULL,
1187     p_upper_spec_limit          IN      VARCHAR2 := NULL,
1188     p_lower_spec_limit          IN      VARCHAR2 := NULL,
1189     p_upper_reasonable_limit    IN      VARCHAR2 := NULL,
1190     p_lower_reasonable_limit    IN      VARCHAR2 := NULL,
1191     p_upper_user_defined_limit  IN      VARCHAR2 := NULL,
1192     p_lower_user_defined_limit  IN      VARCHAR2 := NULL,
1193     x_msg_count                 OUT     NOCOPY NUMBER,
1194     x_msg_data                  OUT     NOCOPY VARCHAR2,
1195     x_return_status             OUT     NOCOPY VARCHAR2,
1196     -- 7430441.FP for Bug 7046198
1197     -- Added the attribute parameters in order to populate the DFF
1198     -- fields too into the qa_spec_chars table
1199     -- pdube Wed Sep 24 03:17:03 PDT 2008
1200     p_attribute_category        IN VARCHAR2 := NULL,
1201     p_attribute1                IN VARCHAR2 := NULL,
1202     p_attribute2                IN VARCHAR2 := NULL,
1203     p_attribute3                IN VARCHAR2 := NULL,
1204     p_attribute4                IN VARCHAR2 := NULL,
1205     p_attribute5                IN VARCHAR2 := NULL,
1206     p_attribute6                IN VARCHAR2 := NULL,
1207     p_attribute7                IN VARCHAR2 := NULL,
1208     p_attribute8                IN VARCHAR2 := NULL,
1209     p_attribute9                IN VARCHAR2 := NULL,
1210     p_attribute10               IN VARCHAR2 := NULL,
1211     p_attribute11               IN VARCHAR2 := NULL,
1212     p_attribute12               IN VARCHAR2 := NULL,
1213     p_attribute13               IN VARCHAR2 := NULL,
1214     p_attribute14               IN VARCHAR2 := NULL,
1215     p_attribute15               IN VARCHAR2 := NULL ) IS
1216 
1217 
1218     l_api_name                  CONSTANT VARCHAR2(30)   := 'add_spec_element';
1219     l_api_version               CONSTANT NUMBER         := 1.0;
1220 
1221     l_user_id      NUMBER;
1222     l_enabled_flag NUMBER;
1223     l_char_id      NUMBER;
1224     l_spec_id      NUMBER;
1225     l_datatype     NUMBER;
1226 
1227 BEGIN
1228 
1229     -- Standard Start of API savepoint
1230 
1231     SAVEPOINT add_spec_element;
1232 
1233     -- Standard call to check for call compatibility.
1234     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version,
1235         l_api_name, g_pkg_name) THEN
1236         RAISE fnd_api.g_exc_unexpected_error;
1237     END IF;
1238 
1239     -- Initialize message list if p_init_msg_list is set to TRUE.
1240     IF fnd_api.to_boolean(p_init_msg_list) THEN
1241         fnd_msg_pub.initialize;
1242     END IF;
1243 
1244     --  Initialize API return status to success
1245     x_return_status := fnd_api.g_ret_sts_success;
1246 
1247     l_user_id := get_user_id(p_user_name);
1248     IF l_user_id = -1 THEN
1249         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1250         fnd_msg_pub.add();
1251         raise fnd_api.g_exc_error;
1252     END IF;
1253 
1254     l_char_id := get_context_element_id(p_element_name);
1255     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1256 
1257     -- See if the spec is a child and throw exception appropriately
1258     IF is_child_spec(l_spec_id) THEN
1259         fnd_message.set_name('QA', 'QA_SPEC_ELEM_TO_CHILD');
1260         fnd_msg_pub.add();
1261         raise fnd_api.g_exc_error;
1262     END IF;
1263 
1264     IF (spec_element_exists(l_spec_id, l_char_id)) THEN
1265         fnd_message.set_name ('QA', 'QA_API_DUPLICATE_SPEC_ELEMENT');
1266         fnd_msg_pub.add();
1267         RAISE fnd_api.g_exc_error;
1268     END IF;
1269 
1270     l_datatype := qa_chars_api.datatype(l_char_id);
1271 
1272     validate_datatype(p_target_value, l_datatype);
1273     validate_datatype(p_upper_spec_limit, l_datatype);
1274     validate_datatype(p_lower_spec_limit, l_datatype);
1275     validate_datatype(p_upper_reasonable_limit, l_datatype);
1276     validate_datatype(p_lower_reasonable_limit, l_datatype);
1277     validate_datatype(p_upper_user_defined_limit, l_datatype);
1278     validate_datatype(p_lower_user_defined_limit, l_datatype);
1279 
1280     IF qltcompb.compare(p_upper_spec_limit, 6, p_lower_spec_limit, null,
1281         l_datatype) THEN
1282         fnd_message.set_name('QA', 'QA_LSL_GREATER_THAN_USL');
1283         fnd_msg_pub.add();
1284         RAISE fnd_api.g_exc_error;
1285     END IF;
1286 
1287     IF qltcompb.compare(p_upper_reasonable_limit, 6, p_lower_reasonable_limit,
1288         null, l_datatype) THEN
1289         fnd_message.set_name('QA', 'QA_LRL_GREATER_THAN_URL');
1290         fnd_msg_pub.add();
1291         RAISE fnd_api.g_exc_error;
1292     END IF;
1293 
1294     IF qltcompb.compare(p_upper_user_defined_limit, 6,
1295         p_lower_user_defined_limit, null, l_datatype) THEN
1296         fnd_message.set_name('QA', 'QA_LUL_GREATER_THAN_UUL');
1297         fnd_msg_pub.add();
1298         RAISE fnd_api.g_exc_error;
1299     END IF;
1300 
1301     l_enabled_flag := convert_flag(p_enabled_flag);
1302 
1303     -- The values getting inserted in to qa_spec_chars in the following insert
1304     -- statement were reversed.Changed the order of parameters for
1305     -- upper_reasonable_limit,lower_reasonable_limit,upper_user_defined_limit,
1306     -- lower_user_defined_limit.
1307     -- Bug 2715786.suramasw Wed Dec 18 23:08:20 PST 2002.
1308 
1309     INSERT INTO qa_spec_chars(
1310         spec_id,
1311         char_id,
1312         last_update_date,
1313         last_updated_by,
1314         creation_date,
1315         created_by,
1316         last_update_login,
1317         enabled_flag,
1318         target_value,
1319         upper_spec_limit,
1320         lower_spec_limit,
1321         upper_reasonable_limit,
1322         lower_reasonable_limit,
1323         upper_user_defined_limit,
1324         lower_user_defined_limit,
1325         uom_code,
1326         attribute_category, -- Bug 7430441
1327         attribute1,
1328         attribute2,
1329         attribute3,
1330         attribute4,
1331         attribute5,
1332         attribute6,
1333         attribute7,
1334         attribute8,
1335         attribute9,
1336         attribute10,
1337         attribute11,
1338         attribute12,
1339         attribute13,
1340         attribute14,
1341         attribute15 )
1342     VALUES(
1343         l_spec_id,
1344         l_char_id,
1345         sysdate,
1346         l_user_id,
1347         sysdate,
1348         l_user_id,
1349         l_user_id,
1350         l_enabled_flag,
1351         p_target_value,
1352         p_upper_spec_limit,
1353         p_lower_spec_limit,
1354         p_upper_reasonable_limit,
1355         p_lower_reasonable_limit,
1356         p_upper_user_defined_limit,
1357         p_lower_user_defined_limit,
1358         p_uom_code,
1359         p_attribute_category , -- Bug 7430441
1360         p_attribute1 ,
1361         p_attribute2 ,
1362         p_attribute3 ,
1363         p_attribute4 ,
1364         p_attribute5 ,
1365         p_attribute6 ,
1366         p_attribute7 ,
1367         p_attribute8 ,
1368         p_attribute9 ,
1369         p_attribute10,
1370         p_attribute11,
1371         p_attribute12,
1372         p_attribute13,
1373         p_attribute14,
1374         p_attribute15 );
1375 
1376 EXCEPTION
1377 
1378     WHEN fnd_api.g_exc_error THEN
1379         ROLLBACK TO add_spec_element;
1380         x_return_status := fnd_api.g_ret_sts_error;
1381         fnd_msg_pub.count_and_get(
1382             p_count => x_msg_count,
1383             p_data  => x_msg_data
1384         );
1385 
1386      WHEN fnd_api.g_exc_unexpected_error THEN
1387         ROLLBACK TO add_spec_element;
1388         x_return_status := fnd_api.g_ret_sts_unexp_error;
1389         fnd_msg_pub.count_and_get(
1390             p_count => x_msg_count,
1391             p_data  => x_msg_data
1392         );
1393 
1394      WHEN OTHERS THEN
1395         ROLLBACK TO add_spec_element;
1396         x_return_status := fnd_api.g_ret_sts_unexp_error;
1397         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1398             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1399         END IF;
1400         fnd_msg_pub.count_and_get(
1401             p_count => x_msg_count,
1402             p_data  => x_msg_data
1403         );
1404 
1405 END add_spec_element;
1406 
1407 
1408 PROCEDURE complete_spec_processing(
1409     p_api_version               IN      NUMBER,
1410     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1411     p_user_name                 IN      VARCHAR2 := NULL,
1412     p_spec_name                 IN      VARCHAR2,
1413     p_organization_code         IN      VARCHAR2,
1414     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1415     x_msg_count                 OUT     NOCOPY NUMBER,
1416     x_msg_data                  OUT     NOCOPY VARCHAR2,
1417     x_return_status             OUT     NOCOPY VARCHAR2) IS
1418 
1419     l_api_name          CONSTANT VARCHAR2(30):= 'complete_spec_definition';
1420     l_api_version       CONSTANT NUMBER      := 1.0;
1421 
1422     l_user_id   NUMBER;
1423     l_spec_id   NUMBER;
1424 
1425 BEGIN
1426 
1427     -- Standard Start of API savepoint
1428 
1429     SAVEPOINT complete_spec_definition;
1430 
1431     -- Standard call to check for call compatibility.
1432     IF NOT fnd_api.compatible_api_call(
1433         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1434         RAISE fnd_api.g_exc_unexpected_error;
1435     END IF;
1436 
1437     -- Initialize message list if p_init_msg_list is set to TRUE.
1438     IF fnd_api.to_boolean(p_init_msg_list) THEN
1439         fnd_msg_pub.initialize;
1440     END IF;
1441 
1442     --  Initialize API return status to success
1443     x_return_status := fnd_api.g_ret_sts_success;
1444 
1445     l_user_id := get_user_id(p_user_name);
1446     IF l_user_id = -1 THEN
1447         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1448         fnd_msg_pub.add();
1449         raise fnd_api.g_exc_error;
1450     END IF;
1451 
1452     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1453     check_for_spec_element(l_spec_id);
1454 
1455     IF fnd_api.to_boolean(p_commit) THEN
1456         COMMIT;
1457     END IF;
1458 
1459 EXCEPTION
1460 
1461     WHEN fnd_api.g_exc_error THEN
1462         ROLLBACK TO complete_spec_definition;
1463         x_return_status := fnd_api.g_ret_sts_error;
1464         fnd_msg_pub.count_and_get(
1465             p_count => x_msg_count,
1466             p_data  => x_msg_data
1467         );
1468 
1469      WHEN fnd_api.g_exc_unexpected_error THEN
1470         ROLLBACK TO complete_spec_definition;
1471         x_return_status := fnd_api.g_ret_sts_unexp_error;
1472         fnd_msg_pub.count_and_get(
1473             p_count => x_msg_count,
1474             p_data  => x_msg_data
1475         );
1476 
1477      WHEN OTHERS THEN
1478         ROLLBACK TO complete_spec_definition;
1479         x_return_status := fnd_api.g_ret_sts_unexp_error;
1480         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1481             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1482         END IF;
1483         fnd_msg_pub.count_and_get(
1484             p_count => x_msg_count,
1485             p_data  => x_msg_data
1486         );
1487 
1488 END complete_spec_processing;
1489 
1490 
1491 PROCEDURE delete_spec_private(p_spec_id IN NUMBER) IS
1492 --
1493 -- The real work of deleting a specification and all its
1494 -- spec elements.  Do not commit.
1495 --
1496 BEGIN
1497 
1498     DELETE
1499     FROM qa_spec_chars
1500     WHERE spec_id = p_spec_id;
1501 
1502     DELETE
1503     FROM qa_specs
1504     WHERE spec_id = p_spec_id;
1505 
1506 END delete_spec_private;
1507 
1508 PROCEDURE delete_spec_element_private(
1509     p_spec_id IN NUMBER,
1510     p_element_id IN NUMBER) IS
1511 
1512 BEGIN
1513 
1514     DELETE
1515     FROM qa_spec_chars
1516     WHERE spec_id = p_spec_id
1517     AND char_id = p_element_id;
1518 
1519 END delete_spec_element_private;
1520 
1521 
1522 --
1523 -- Should not allow deletion if there exists
1524 -- at least one child spec. Use child_spec_exists
1525 -- rkunchal
1526 --
1527 
1528 PROCEDURE delete_specification(
1529     p_api_version               IN      NUMBER,
1530     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1531     p_user_name                 IN      VARCHAR2 := NULL,
1532     p_spec_name                 IN      VARCHAR2,
1533     p_organization_code         IN      VARCHAR2,
1534     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1535     x_msg_count                 OUT     NOCOPY NUMBER,
1536     x_msg_data                  OUT     NOCOPY VARCHAR2,
1537     x_return_status             OUT     NOCOPY VARCHAR2) IS
1538 
1539     l_api_name                  CONSTANT VARCHAR2(30):= 'delete_specification';
1540     l_api_version               CONSTANT NUMBER      := 1.0;
1541 
1542     l_user_id      NUMBER;
1543     l_spec_id      NUMBER;
1544     l_org_id       NUMBER;
1545 
1546 BEGIN
1547 
1548     -- Standard Start of API savepoint
1549 
1550     SAVEPOINT   delete_specification;
1551 
1552     -- Standard call to check for call compatibility.
1553     IF NOT fnd_api.compatible_api_call(
1554         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1555         RAISE fnd_api.g_exc_unexpected_error;
1556     END IF;
1557 
1558     -- Initialize message list if p_init_msg_list is set to TRUE.
1559     IF fnd_api.to_boolean(p_init_msg_list) THEN
1560         fnd_msg_pub.initialize;
1561     END IF;
1562 
1563     --  Initialize API return status to success
1564     x_return_status := fnd_api.g_ret_sts_success;
1565 
1566     l_user_id := get_user_id(p_user_name);
1567     IF l_user_id = -1 THEN
1568         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1569         fnd_msg_pub.add();
1570         raise fnd_api.g_exc_error;
1571     END IF;
1572 
1573     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1574 
1575     -- Perfect place to check for child specs
1576     IF child_spec_exists(l_spec_id) THEN
1577         fnd_message.set_name('QA', 'QA_CHILD_SPECS_EXIST');
1578         fnd_msg_pub.add();
1579         raise fnd_api.g_exc_error;
1580     END IF;
1581 
1582     delete_spec_private(l_spec_id);
1583 
1584     IF fnd_api.to_boolean(p_commit) THEN
1585         COMMIT;
1586     END IF;
1587 
1588 EXCEPTION
1589 
1590     WHEN fnd_api.g_exc_error THEN
1591         ROLLBACK TO delete_specification;
1592         x_return_status := fnd_api.g_ret_sts_error;
1593         fnd_msg_pub.count_and_get(
1594             p_count => x_msg_count,
1595             p_data  => x_msg_data
1596         );
1597 
1598      WHEN fnd_api.g_exc_unexpected_error THEN
1599         ROLLBACK TO delete_specification;
1600         x_return_status := fnd_api.g_ret_sts_unexp_error;
1601         fnd_msg_pub.count_and_get(
1602             p_count => x_msg_count,
1603             p_data  => x_msg_data
1604         );
1605 
1606      WHEN OTHERS THEN
1607         ROLLBACK TO delete_specification;
1608         x_return_status := fnd_api.g_ret_sts_unexp_error;
1609         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1610             fnd_msg_pub.Add_Exc_Msg(g_pkg_name, l_api_name);
1611         END IF;
1612         fnd_msg_pub.count_and_get(
1613             p_count => x_msg_count,
1614             p_data  => x_msg_data
1615         );
1616 
1617 END delete_specification;
1618 
1619 --
1620 -- Though this will not effectively do anything for child specs,
1621 -- we want to give an impression to caller that this operation
1622 -- on a child spec is not functionally valid and is discouraged.
1623 --
1624 -- rkunchal
1625 --
1626 
1627 PROCEDURE delete_spec_element(
1628     p_api_version               IN      NUMBER,
1629     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1630     p_user_name                 IN      VARCHAR2 := NULL,
1631     p_spec_name                 IN      VARCHAR2,
1632     p_organization_code         IN      VARCHAR2,
1633     p_element_name              IN      VARCHAR2,
1634     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1635     x_msg_count                 OUT     NOCOPY NUMBER,
1636     x_msg_data                  OUT     NOCOPY VARCHAR2,
1637     x_return_status             OUT     NOCOPY VARCHAR2) IS
1638 
1639     l_api_name                  CONSTANT VARCHAR2(30):= 'delete_spec_element';
1640     l_api_version               CONSTANT NUMBER      := 1.0;
1641 
1642     l_user_id   NUMBER;
1643     l_spec_id   NUMBER;
1644     l_char_id   NUMBER;
1645     l_org_id    NUMBER;
1646 
1647 BEGIN
1648 
1649     -- Standard Start of API savepoint
1650 
1651     SAVEPOINT delete_spec_element;
1652 
1653     -- Standard call to check for call compatibility.
1654     IF NOT fnd_api.compatible_api_call(
1655         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1656         RAISE fnd_api.g_exc_unexpected_error;
1657     END IF;
1658 
1659     -- Initialize message list if p_init_msg_list is set to TRUE.
1660     IF fnd_api.to_boolean(p_init_msg_list) THEN
1661         fnd_msg_pub.initialize;
1662     END IF;
1663 
1664     --  Initialize API return status to success
1665     x_return_status := fnd_api.g_ret_sts_success;
1666 
1667     l_user_id := get_user_id(p_user_name);
1668     IF l_user_id = -1 THEN
1669         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1670         fnd_msg_pub.add();
1671         raise fnd_api.g_exc_error;
1672     END IF;
1673 
1674     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1675 
1676     -- We must be checking here if the spec is a child
1677     IF is_child_spec(l_spec_id) THEN
1678         fnd_message.set_name('QA', 'QA_DELETE_SPEC_ELEM_ON_CHILD');
1679         fnd_msg_pub.add();
1680         raise fnd_api.g_exc_error;
1681     END IF;
1682 
1683     l_char_id := get_context_element_id(p_element_name);
1684 
1685     delete_spec_element_private(l_spec_id, l_char_id);
1686 
1687     IF fnd_api.to_boolean(p_commit) THEN
1688         COMMIT;
1689     END IF;
1690 
1691 EXCEPTION
1692 
1693     WHEN fnd_api.g_exc_error THEN
1694         ROLLBACK TO delete_spec_element;
1695         x_return_status := fnd_api.g_ret_sts_error;
1696         fnd_msg_pub.count_and_get(
1697             p_count => x_msg_count,
1698             p_data  => x_msg_data
1699         );
1700 
1701      WHEN fnd_api.g_exc_unexpected_error THEN
1702         ROLLBACK TO delete_spec_element;
1703         x_return_status := fnd_api.g_ret_sts_unexp_error;
1704         fnd_msg_pub.count_and_get(
1705             p_count => x_msg_count,
1706             p_data  => x_msg_data
1707         );
1708 
1709      WHEN OTHERS THEN
1710         ROLLBACK TO delete_spec_element;
1711         x_return_status := fnd_api.g_ret_sts_unexp_error;
1712         IF fnd_msg_pub.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1713             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1714         END IF;
1715         fnd_msg_pub.count_and_get(
1716             p_count => x_msg_count,
1717             p_data  => x_msg_data
1718         );
1719 
1720 END delete_spec_element;
1721 
1722 --
1723 -- We should not copy Spec Elements if the spec being copied is a child.
1724 -- The new, copied spec still references the same master spec.
1725 -- Copying child is seemless and caller will not see any message.
1726 --
1727 -- rkunchal
1728 --
1729 
1730 PROCEDURE copy_specification(
1731     p_api_version               IN      NUMBER,
1732     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1733     p_user_name                 IN      VARCHAR2 := NULL,
1734     p_spec_name                 IN      VARCHAR2,
1735     p_organization_code         IN      VARCHAR2,
1736     p_to_spec_name              IN      VARCHAR2,
1737     p_to_organization_code      IN      VARCHAR2,
1738     p_to_item_name              IN      VARCHAR2,
1739     p_to_item_revision          IN      VARCHAR2 := NULL,
1740     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1741     x_spec_id                   OUT     NOCOPY NUMBER,
1742     x_msg_count                 OUT     NOCOPY NUMBER,
1743     x_msg_data                  OUT     NOCOPY VARCHAR2,
1744     x_return_status             OUT     NOCOPY VARCHAR2) IS
1745 
1746     l_api_name                  CONSTANT VARCHAR2(30):= 'copy_specification';
1747     l_api_version               CONSTANT NUMBER      := 1.0;
1748 
1749     l_user_id                   NUMBER;
1750     l_spec_id                   NUMBER;
1751     l_org_id                    NUMBER;
1752     l_spec_name                 NUMBER;
1753     l_to_org_id                 NUMBER;
1754     l_category_set_id           NUMBER;
1755     l_category_id               NUMBER;
1756     l_to_item_id                NUMBER;
1757     l_to_item_revision          NUMBER;
1758     l_vendor_id                 NUMBER;
1759     l_customer_id               NUMBER;
1760     l_char_id                   NUMBER;
1761     l_spec_element_value        VARCHAR2(150);
1762     l_existing_spec_name        VARCHAR2(30);
1763 
1764     --BUG 3500244
1765     --we do NOT support ERES in APIs as documented in QA FDA HLD
1766     --so this should behave as though ERES profile is No
1767     --which means spec_status of 40 which is No Approval Reqd
1768     --should be used for spec creation since it is a NON-Null Column
1769 
1770     l_spec_status               NUMBER := 40;
1771 
1772 BEGIN
1773 
1774     -- Standard Start of API savepoint
1775 
1776     SAVEPOINT copy_specification;
1777 
1778     -- Standard call to check for call compatibility.
1779     IF NOT fnd_api.compatible_api_call(
1780         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1781         RAISE fnd_api.g_exc_unexpected_error;
1782     END IF;
1783 
1784     -- Initialize message list if p_init_msg_list is set to TRUE.
1785     IF fnd_api.to_boolean(p_init_msg_list) THEN
1786         fnd_msg_pub.initialize;
1787     END IF;
1788 
1789     --  Initialize API return status to success
1790     x_return_status := fnd_api.g_ret_sts_success;
1791 
1792     l_user_id := get_user_id(p_user_name);
1793     IF l_user_id = -1 THEN
1794         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1795         fnd_msg_pub.add();
1796         raise fnd_api.g_exc_error;
1797     END IF;
1798 
1799     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1800     l_org_id := organization_id(l_spec_id);
1801 
1802     l_to_org_id := qa_plans_api.get_org_id(p_to_organization_code);
1803     IF (l_to_org_id IS NULL) THEN
1804         fnd_message.set_name('QA', 'QA_API_INVALID_ORG_CODE');
1805         fnd_msg_pub.add();
1806         RAISE fnd_api.g_exc_error;
1807     END IF;
1808 
1809     IF (spec_exists(p_to_spec_name)) THEN
1810         fnd_message.set_name('QA', 'QA_API_DUPLICATE_SPEC_NAME');
1811         fnd_msg_pub.add();
1812         RAISE fnd_api.g_exc_error;
1813     END IF;
1814 
1815     l_to_item_id := process_item_and_revision(p_to_item_name,
1816         p_to_item_revision, l_org_id);
1817 
1818     l_category_set_id           := category_set_id(l_spec_id);
1819     l_category_id               := category_id(l_spec_id);
1820     l_vendor_id                 := vendor_id(l_spec_id);
1821     l_customer_id               := customer_id(l_spec_id);
1822     l_char_id                   := char_id(l_spec_id);
1823     l_spec_element_value        := spec_element_value(l_spec_id);
1824 
1825     IF (combination_exists(l_category_set_id, l_category_id, l_to_item_id,
1826         p_to_item_revision, l_org_id, l_vendor_id, l_customer_id, l_char_id,
1827         l_spec_element_value, l_existing_spec_name)) THEN
1828 
1829         fnd_message.set_name('QA', 'QA_SPEC_COMBINATION_EXISTS');
1830         fnd_message.set_token('ENTITY1', l_existing_spec_name);
1831         fnd_msg_pub.add();
1832         RAISE fnd_api.g_exc_error;
1833     END IF;
1834 
1835     SELECT qa_specs_s.nextval INTO x_spec_id FROM DUAL;
1836 
1837     INSERT INTO qa_specs(
1838         spec_id,
1839         last_update_date,
1840         last_updated_by,
1841         creation_date,
1842         created_by,
1843         last_update_login,
1844         spec_name,
1845         organization_id,
1846         effective_from,
1847         effective_to,
1848         common_spec_id,
1849         assignment_type,
1850         category_set_id,
1851         category_id,
1852         item_id,
1853         item_revision,
1854         vendor_id,
1855         customer_id,
1856         hide_plan_chars_flag,
1857         char_id,
1858         spec_element_value,
1859         spec_status ) --Bug 3500244
1860     SELECT
1861         x_spec_id,
1862         sysdate,
1863         l_user_id,
1864         sysdate,
1865         l_user_id,
1866         l_user_id,
1867         p_to_spec_name,
1868         l_to_org_id,
1869         effective_from,
1870         effective_to,
1871         common_spec_id,
1872         assignment_type,
1873         category_set_id,
1874         category_id,
1875         l_to_item_id,
1876         nvl(p_to_item_revision, 'NONE'),
1877         vendor_id,
1878         customer_id,
1879         hide_plan_chars_flag,
1880         char_id,
1881         spec_element_value,
1882         40                 --Bug 3500244 see note below
1883     FROM qa_specs
1884     WHERE spec_id = l_spec_id;
1885 
1886     --Bug 3500244
1887     --In above Select we have not used the variable l_spec_status
1888     --But purposely used the literal 40 so it is very clear for readability
1889     --that we are not selecting from database, but it is kind of a constant
1890 
1891 
1892     -- Prevent this insertion if the spec being copied is a child spec
1893     IF NOT is_child_spec(l_spec_id) THEN
1894       INSERT INTO qa_spec_chars(
1895         spec_id,
1896         char_id,
1897         last_update_date,
1898         last_updated_by,
1899         creation_date,
1900         created_by,
1901         last_update_login,
1902         enabled_flag,
1903         target_value,
1904         upper_spec_limit,
1905         lower_spec_limit,
1906         upper_reasonable_limit,
1907         lower_reasonable_limit,
1908         upper_user_defined_limit,
1909         lower_user_defined_limit)
1910       SELECT
1911         x_spec_id,
1912         char_id,
1913         sysdate,
1914         l_user_id,
1915         sysdate,
1916         l_user_id,
1917         l_user_id,
1918         enabled_flag,
1919         target_value,
1920         upper_spec_limit,
1921         lower_spec_limit,
1922         upper_user_defined_limit,
1923         lower_user_defined_limit,
1924         upper_reasonable_limit,
1925         lower_reasonable_limit
1926       FROM qa_spec_chars
1927       WHERE spec_id = l_spec_id;
1928     END IF;
1929 
1930     --
1931     -- Bug 5231952.  After copying, we should copy attachments.
1932     --
1933     qa_specs_pkg.copy_attachment(
1934         p_from_spec_id => l_spec_id,
1935         p_to_spec_id => x_spec_id);
1936 
1937     IF fnd_api.to_boolean(p_commit) THEN
1938         COMMIT;
1939     END IF;
1940 
1941 EXCEPTION
1942 
1943     WHEN fnd_api.g_exc_error THEN
1944         ROLLBACK TO copy_specification;
1945         x_return_status := fnd_api.g_ret_sts_error;
1946         fnd_msg_pub.count_and_get(
1947             p_count => x_msg_count,
1948             p_data  => x_msg_data
1949         );
1950 
1951      WHEN fnd_api.g_exc_unexpected_error THEN
1952         ROLLBACK TO copy_specification;
1953         x_return_status := fnd_api.g_ret_sts_unexp_error;
1954         fnd_msg_pub.count_and_get(
1955             p_count => x_msg_count,
1956             p_data  => x_msg_data
1957         );
1958 
1959      WHEN OTHERS THEN
1960         ROLLBACK TO copy_specification;
1961         x_return_status := fnd_api.g_ret_sts_unexp_error;
1962         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1963             fnd_msg_pub.Add_Exc_Msg(g_pkg_name, l_api_name);
1964         END IF;
1965         fnd_msg_pub.count_and_get(
1966             p_count => x_msg_count,
1967             p_data  => x_msg_data
1968         );
1969 
1970 END copy_specification;
1971 
1972 
1973 END qa_specs_pub;
1974