DBA Data[Home] [Help]

PACKAGE BODY: APPS.QA_SPECS_PUB

Source


1 PACKAGE BODY qa_specs_pub AS
2 /* $Header: qltpspcb.plb 120.1.12010000.2 2008/09/24 11:29:02 pdube 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 ) IS
794 
795     l_api_name          CONSTANT VARCHAR2(30)   := 'create_specification_pub';
796     l_api_version       CONSTANT NUMBER         := 1.0;
797 
798     l_user_id                   NUMBER;
799     l_org_id                    NUMBER := -1;
800     l_category_set_id           NUMBER := -1;
801     l_category_id               NUMBER := -1;
802     l_structure_id              NUMBER;
803     l_validate_flag             mtl_category_sets.validate_flag%TYPE;
804     l_item_id                   NUMBER := -1;
805     l_vendor_id                 NUMBER := -1;
806     l_customer_id               NUMBER := -1;
807     l_char_id                   NUMBER := -1;
808     l_sub_type_value            qa_specs.spec_element_value%TYPE;
809     l_existing_spec_name        VARCHAR2(30);
810     l_datatype                  NUMBER;
811 
812     l_reference_spec_id            NUMBER;
813 
814     --BUG 3500244
815     --we do NOT support ERES in APIs as documented in QA FDA HLD
816     --so this should behave as though ERES profile is No
817     --which means spec_status of 40 which is No Approval Reqd
818     --should be used for spec creation since it is a NON-Null Column
819     l_spec_status                  NUMBER := 40;
820 
821 
822     CURSOR c IS
823       SELECT spec_id
824       FROM   qa_specs
825       WHERE  spec_name = p_reference_spec;
826 
827 BEGIN
828 
829     -- Standard Start of API savepoint
830 
831     SAVEPOINT create_specification_pub;
832 
833     -- Standard call to check for call compatibility.
834     IF NOT fnd_api.compatible_api_call (
835         l_api_version,
836         p_api_version,
837         l_api_name,
838         g_pkg_name) THEN
839         RAISE fnd_api.g_exc_unexpected_error;
840     END IF;
841 
842     -- Initialize message list if p_init_msg_list is set to TRUE.
843     IF fnd_api.to_boolean(p_init_msg_list) THEN
844         fnd_msg_pub.initialize;
845     END IF;
846 
847 
848     --  Initialize API return status to success
849     x_return_status := fnd_api.g_ret_sts_success;
850 
851     l_user_id := get_user_id(p_user_name);
852     IF l_user_id = -1 THEN
853         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
854         fnd_msg_pub.add();
855         raise fnd_api.g_exc_error;
856     END IF;
857 
858     -- Algorithm
859     --
860     --
861     -- 0. Check for duplicate name
862     --
863     -- 0.5 If the reference_spec is passed, verify if that spec exists and is not a
864     --     referencing any other spec.
865     --
866     -- 1. convert org code to org id
867     --
868     -- 2. validate the effective FROM and TO dates
869     --
870     -- 3.
871     --    if assignment type is supplier then
872     --        validate vendor and generate id
873     --    else if assignment type is customer then
874     --        validate customer and generate id
875     --    end if;
876     --
877     -- 4.
878     --    if item is given then
879     --        validate item and generate id
880     --        validate revision if provided
881     --    else if category set name is given then
882     --        validate category set name and generate id
883     --    else
884     --        generate an error
885     --    end if;
886     --
887     -- 5. if there is spec sub type provided (element) then
888     --    convert it into id
889     --
890     -- 6. Check for existing combination.
891     --
892     -- 7. generate spec id
893     --
894     -- 8. insert the row
895 
896     IF (spec_exists(p_spec_name)) THEN
897         fnd_message.set_name('QA', 'QA_API_DUPLICATE_SPEC_NAME');
898         fnd_msg_pub.add();
899         RAISE fnd_api.g_exc_error;
900     END IF;
901 
902     -- See if the spec exists with p_common_spec_name
903     IF p_reference_spec IS NOT NULL AND NOT spec_exists(p_reference_spec) THEN
904         fnd_message.set_name('QA', 'QA_SPEC_NOT_EXISTS');
905         fnd_message.set_token('ENTITY1', p_reference_spec);
906         fnd_msg_pub.add();
907         RAISE fnd_api.g_exc_error;
908     END IF;
909 
910     -- Force not to reference a child spec if common_spec_name is passed
911     IF p_reference_spec IS NOT NULL AND is_child_spec(p_reference_spec) THEN
912         fnd_message.set_name('QA', 'QA_CANNOT_REFER_CHILD_SPEC');
913         fnd_msg_pub.add();
914         RAISE fnd_api.g_exc_error;
915     END IF;
916 
917     l_org_id := qa_plans_api.get_org_id(p_organization_code);
918 
919     IF (l_org_id IS NULL) THEN
920         fnd_message.set_name('QA', 'QA_API_INVALID_ORG_CODE');
921         fnd_msg_pub.add();
922         RAISE fnd_api.g_exc_error;
923     END IF;
924 
925     IF (p_effective_to IS NOT NULL) THEN
926         IF (p_effective_to < p_effective_from) THEN
927             fnd_message.set_name('QA', 'QA_EFFECTIVE_DATE_RANGE');
928             fnd_msg_pub.add();
929             RAISE fnd_api.g_exc_error;
930         END IF;
931     END IF;
932 
933     IF (p_assignment_type = g_spec_type_item) THEN
934         NULL; -- nothing special needs to be done for item spec.
935 
936     ELSIF (p_assignment_type = g_spec_type_supplier) THEN
937         l_vendor_id := qa_plan_element_api.get_supplier_id(p_supplier_name);
938         IF (l_vendor_id IS NULL) THEN
939             fnd_message.set_name('QA', 'QA_API_INVALID_VENDOR_NAME');
940             fnd_msg_pub.add();
941             RAISE fnd_api.g_exc_error;
942         END IF;
943 
944     ELSIF (p_assignment_type = g_spec_type_customer) THEN
945         l_customer_id := qa_plan_element_api.get_customer_id(p_customer_name);
946         IF (l_customer_id IS NULL) THEN
947             fnd_message.set_name('QA', 'QA_API_INVALID_CUSTOMER_NAME');
948             fnd_msg_pub.add();
949             RAISE fnd_api.g_exc_error;
950         END IF;
951 
952     ELSE
953         fnd_message.set_name('QA', 'QA_API_INVALID_ASSIGNMENT_TYPE');
954         fnd_msg_pub.add();
955         RAISE fnd_api.g_exc_error;
956     END IF;
957 
958     IF (p_item_name IS NOT NULL) THEN
959         l_item_id := process_item_and_revision(p_item_name, p_item_revision,
960             l_org_id);
961     ELSE
962         l_category_set_id := get_category_set_id(
963             p_category_set_name, l_structure_id, l_validate_flag);
964         l_category_id := get_category_id(p_category_name,
965             l_category_set_id, l_org_id, l_structure_id, l_validate_flag);
966     END IF;
967 
968     IF (p_sub_type_element IS NOT NULL) THEN
969         l_sub_type_value := p_sub_type_element_value;
970         l_char_id := qa_chars_api.get_element_id(p_sub_type_element);
971  /* 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.
972  */
973         IF (l_char_id IS NOT NULL) THEN
974             l_datatype := qa_chars_api.datatype(l_char_id);
975             validate_datatype(l_sub_type_value, l_datatype);
976         ELSE
977            fnd_message.set_name('QA', 'QA_API_INVALID_ELEMENT');
978            fnd_msg_pub.add();
979            RAISE fnd_api.g_exc_error;
980         END IF;
981     ELSE
982         l_char_id := -1;
983         l_sub_type_value := '-1';
984     END IF;
985 
986     IF (combination_exists(l_category_set_id, l_category_id, l_item_id,
987         p_item_revision, l_org_id, l_vendor_id, l_customer_id, l_char_id,
988         l_sub_type_value, l_existing_spec_name)) THEN
989 
990         fnd_message.set_name('QA', 'QA_SPEC_COMBINATION_EXISTS');
991         fnd_message.set_token('ENTITY1', l_existing_spec_name);
992         fnd_msg_pub.add();
993         RAISE fnd_api.g_exc_error;
994     END IF;
995 
996     SELECT qa_specs_s.nextval INTO x_spec_id FROM DUAL;
997 
998     IF p_reference_spec IS NOT NULL THEN
999        OPEN c;
1000        FETCH c INTO l_reference_spec_id;
1001        CLOSE c;
1002     ELSE
1003        l_reference_spec_id := x_spec_id;
1004     END IF;
1005 
1006     INSERT INTO qa_specs(
1007         spec_id,
1008         last_update_date,
1009         last_updated_by,
1010         creation_date,
1011         created_by,
1012         last_update_login,
1013         spec_name,
1014         organization_id,
1015         effective_from,
1016         effective_to,
1017         common_spec_id,
1018         assignment_type,
1019         category_set_id,
1020         category_id,
1021         item_id,
1022         item_revision,
1023         vendor_id,
1024         customer_id,
1025         hide_plan_chars_flag,
1026         char_id,
1027         spec_element_value,
1028 	spec_status,       --Bug 3500244
1029         attribute_category, -- Bug 7430441
1030         attribute1,
1031         attribute2,
1032         attribute3,
1033         attribute4,
1034         attribute5,
1035         attribute6,
1036         attribute7,
1037         attribute8,
1038         attribute9,
1039         attribute10,
1040         attribute11,
1041         attribute12,
1042         attribute13,
1043         attribute14,
1044         attribute15 )
1045     VALUES(
1046         x_spec_id,
1047         sysdate,
1048         l_user_id,
1049         sysdate,
1050         l_user_id,
1051         l_user_id,
1052         p_spec_name,
1053         l_org_id,
1054         p_effective_from,
1055         p_effective_to,
1056         l_reference_spec_id,
1057         p_assignment_type,
1058         l_category_set_id,
1059         l_category_id,
1060         l_item_id,
1061         nvl(p_item_revision, 'NONE'),
1062         l_vendor_id,
1063         l_customer_id,
1064         1,
1065         l_char_id,
1066         l_sub_type_value,
1067 	l_spec_status,  --Bug 3500244
1068         p_attribute_category , -- Bug 7430441
1069         p_attribute1 ,
1070         p_attribute2 ,
1071         p_attribute3 ,
1072         p_attribute4 ,
1073         p_attribute5 ,
1074         p_attribute6 ,
1075         p_attribute7 ,
1076         p_attribute8 ,
1077         p_attribute9 ,
1078         p_attribute10,
1079         p_attribute11,
1080         p_attribute12,
1081         p_attribute13,
1082         p_attribute14,
1083         p_attribute15 );
1084 
1085 EXCEPTION
1086 
1087     WHEN fnd_api.g_exc_error THEN
1088         ROLLBACK TO create_specification_pub;
1089         x_return_status := fnd_api.g_ret_sts_error;
1090         fnd_msg_pub.count_and_get(
1091             p_count => x_msg_count,
1092             p_data  => x_msg_data
1093         );
1094 
1095      WHEN fnd_api.g_exc_unexpected_error THEN
1096         ROLLBACK TO create_specification_pub;
1097         x_return_status := fnd_api.g_ret_sts_unexp_error;
1098         fnd_msg_pub.count_and_get(
1099             p_count => x_msg_count,
1100             p_data  => x_msg_data
1101         );
1102 
1103      WHEN OTHERS THEN
1104         -- dbms_output.put_line(SQLCODE || SQLERRM);
1105         ROLLBACK TO create_specification_pub;
1106         x_return_status := fnd_api.g_ret_sts_unexp_error;
1107         IF fnd_msg_pub.Check_Msg_Level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1108             fnd_msg_pub.Add_Exc_Msg(g_pkg_name, l_api_name);
1109         END IF;
1110         fnd_msg_pub.count_and_get(
1111             p_count => x_msg_count,
1112             p_data  => x_msg_data
1113         );
1114 
1115 END create_specification;
1116 
1117 --
1118 -- Adding spec elements is not allowed for child specs
1119 -- We would throw the same error if attempted.
1120 --
1121 -- rkunchal
1122 --
1123 
1124 PROCEDURE add_spec_element(
1125     p_api_version               IN      NUMBER,
1126     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1127     p_validation_level          IN      NUMBER   := fnd_api.G_VALID_LEVEL_FULL,
1128     p_user_name                 IN      VARCHAR2 := NULL,
1129     p_spec_name                 IN      VARCHAR2,
1130     p_organization_code         IN      VARCHAR2,
1131     p_element_name              IN      VARCHAR2,
1132     p_uom_code                  IN      VARCHAR2 := NULL,
1133     p_enabled_flag              IN      VARCHAR2 := fnd_api.g_true,
1134     p_target_value              IN      VARCHAR2 := NULL,
1135     p_upper_spec_limit          IN      VARCHAR2 := NULL,
1136     p_lower_spec_limit          IN      VARCHAR2 := NULL,
1137     p_upper_reasonable_limit    IN      VARCHAR2 := NULL,
1138     p_lower_reasonable_limit    IN      VARCHAR2 := NULL,
1139     p_upper_user_defined_limit  IN      VARCHAR2 := NULL,
1140     p_lower_user_defined_limit  IN      VARCHAR2 := NULL,
1141     x_msg_count                 OUT     NOCOPY NUMBER,
1142     x_msg_data                  OUT     NOCOPY VARCHAR2,
1143     x_return_status             OUT     NOCOPY VARCHAR2,
1144     -- 7430441.FP for Bug 7046198
1145     -- Added the attribute parameters in order to populate the DFF
1146     -- fields too into the qa_spec_chars table
1147     -- pdube Wed Sep 24 03:17:03 PDT 2008
1148     p_attribute_category        IN VARCHAR2 := NULL,
1149     p_attribute1                IN VARCHAR2 := NULL,
1150     p_attribute2                IN VARCHAR2 := NULL,
1151     p_attribute3                IN VARCHAR2 := NULL,
1152     p_attribute4                IN VARCHAR2 := NULL,
1153     p_attribute5                IN VARCHAR2 := NULL,
1154     p_attribute6                IN VARCHAR2 := NULL,
1155     p_attribute7                IN VARCHAR2 := NULL,
1156     p_attribute8                IN VARCHAR2 := NULL,
1157     p_attribute9                IN VARCHAR2 := NULL,
1158     p_attribute10               IN VARCHAR2 := NULL,
1159     p_attribute11               IN VARCHAR2 := NULL,
1160     p_attribute12               IN VARCHAR2 := NULL,
1161     p_attribute13               IN VARCHAR2 := NULL,
1162     p_attribute14               IN VARCHAR2 := NULL,
1163     p_attribute15               IN VARCHAR2 := NULL ) IS
1164 
1165 
1166     l_api_name                  CONSTANT VARCHAR2(30)   := 'add_spec_element';
1167     l_api_version               CONSTANT NUMBER         := 1.0;
1168 
1169     l_user_id      NUMBER;
1170     l_enabled_flag NUMBER;
1171     l_char_id      NUMBER;
1172     l_spec_id      NUMBER;
1173     l_datatype     NUMBER;
1174 
1175 BEGIN
1176 
1177     -- Standard Start of API savepoint
1178 
1179     SAVEPOINT add_spec_element;
1180 
1181     -- Standard call to check for call compatibility.
1182     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version,
1183         l_api_name, g_pkg_name) THEN
1184         RAISE fnd_api.g_exc_unexpected_error;
1185     END IF;
1186 
1187     -- Initialize message list if p_init_msg_list is set to TRUE.
1188     IF fnd_api.to_boolean(p_init_msg_list) THEN
1189         fnd_msg_pub.initialize;
1190     END IF;
1191 
1192     --  Initialize API return status to success
1193     x_return_status := fnd_api.g_ret_sts_success;
1194 
1195     l_user_id := get_user_id(p_user_name);
1196     IF l_user_id = -1 THEN
1197         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1198         fnd_msg_pub.add();
1199         raise fnd_api.g_exc_error;
1200     END IF;
1201 
1202     l_char_id := get_context_element_id(p_element_name);
1203     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1204 
1205     -- See if the spec is a child and throw exception appropriately
1206     IF is_child_spec(l_spec_id) THEN
1207         fnd_message.set_name('QA', 'QA_SPEC_ELEM_TO_CHILD');
1208         fnd_msg_pub.add();
1209         raise fnd_api.g_exc_error;
1210     END IF;
1211 
1212     IF (spec_element_exists(l_spec_id, l_char_id)) THEN
1213         fnd_message.set_name ('QA', 'QA_API_DUPLICATE_SPEC_ELEMENT');
1214         fnd_msg_pub.add();
1215         RAISE fnd_api.g_exc_error;
1216     END IF;
1217 
1218     l_datatype := qa_chars_api.datatype(l_char_id);
1219 
1220     validate_datatype(p_target_value, l_datatype);
1221     validate_datatype(p_upper_spec_limit, l_datatype);
1222     validate_datatype(p_lower_spec_limit, l_datatype);
1223     validate_datatype(p_upper_reasonable_limit, l_datatype);
1224     validate_datatype(p_lower_reasonable_limit, l_datatype);
1225     validate_datatype(p_upper_user_defined_limit, l_datatype);
1226     validate_datatype(p_lower_user_defined_limit, l_datatype);
1227 
1228     IF qltcompb.compare(p_upper_spec_limit, 6, p_lower_spec_limit, null,
1229         l_datatype) THEN
1230         fnd_message.set_name('QA', 'QA_LSL_GREATER_THAN_USL');
1231         fnd_msg_pub.add();
1232         RAISE fnd_api.g_exc_error;
1233     END IF;
1234 
1235     IF qltcompb.compare(p_upper_reasonable_limit, 6, p_lower_reasonable_limit,
1236         null, l_datatype) THEN
1237         fnd_message.set_name('QA', 'QA_LRL_GREATER_THAN_URL');
1238         fnd_msg_pub.add();
1239         RAISE fnd_api.g_exc_error;
1240     END IF;
1241 
1242     IF qltcompb.compare(p_upper_user_defined_limit, 6,
1243         p_lower_user_defined_limit, null, l_datatype) THEN
1244         fnd_message.set_name('QA', 'QA_LUL_GREATER_THAN_UUL');
1245         fnd_msg_pub.add();
1246         RAISE fnd_api.g_exc_error;
1247     END IF;
1248 
1249     l_enabled_flag := convert_flag(p_enabled_flag);
1250 
1251     -- The values getting inserted in to qa_spec_chars in the following insert
1252     -- statement were reversed.Changed the order of parameters for
1253     -- upper_reasonable_limit,lower_reasonable_limit,upper_user_defined_limit,
1254     -- lower_user_defined_limit.
1255     -- Bug 2715786.suramasw Wed Dec 18 23:08:20 PST 2002.
1256 
1257     INSERT INTO qa_spec_chars(
1258         spec_id,
1259         char_id,
1260         last_update_date,
1261         last_updated_by,
1262         creation_date,
1263         created_by,
1264         last_update_login,
1265         enabled_flag,
1266         target_value,
1267         upper_spec_limit,
1268         lower_spec_limit,
1269         upper_reasonable_limit,
1270         lower_reasonable_limit,
1271         upper_user_defined_limit,
1272         lower_user_defined_limit,
1273         uom_code,
1274         attribute_category, -- Bug 7430441
1275         attribute1,
1276         attribute2,
1277         attribute3,
1278         attribute4,
1279         attribute5,
1280         attribute6,
1281         attribute7,
1282         attribute8,
1283         attribute9,
1284         attribute10,
1285         attribute11,
1286         attribute12,
1287         attribute13,
1288         attribute14,
1289         attribute15 )
1290     VALUES(
1291         l_spec_id,
1292         l_char_id,
1293         sysdate,
1294         l_user_id,
1295         sysdate,
1296         l_user_id,
1297         l_user_id,
1298         l_enabled_flag,
1299         p_target_value,
1300         p_upper_spec_limit,
1301         p_lower_spec_limit,
1302         p_upper_reasonable_limit,
1303         p_lower_reasonable_limit,
1304         p_upper_user_defined_limit,
1305         p_lower_user_defined_limit,
1306         p_uom_code,
1307         p_attribute_category , -- Bug 7430441
1308         p_attribute1 ,
1309         p_attribute2 ,
1310         p_attribute3 ,
1311         p_attribute4 ,
1312         p_attribute5 ,
1313         p_attribute6 ,
1314         p_attribute7 ,
1315         p_attribute8 ,
1316         p_attribute9 ,
1317         p_attribute10,
1318         p_attribute11,
1319         p_attribute12,
1320         p_attribute13,
1321         p_attribute14,
1322         p_attribute15 );
1323 
1324 EXCEPTION
1325 
1326     WHEN fnd_api.g_exc_error THEN
1327         ROLLBACK TO add_spec_element;
1328         x_return_status := fnd_api.g_ret_sts_error;
1329         fnd_msg_pub.count_and_get(
1330             p_count => x_msg_count,
1331             p_data  => x_msg_data
1332         );
1333 
1334      WHEN fnd_api.g_exc_unexpected_error THEN
1335         ROLLBACK TO add_spec_element;
1336         x_return_status := fnd_api.g_ret_sts_unexp_error;
1337         fnd_msg_pub.count_and_get(
1338             p_count => x_msg_count,
1339             p_data  => x_msg_data
1340         );
1341 
1342      WHEN OTHERS THEN
1343         ROLLBACK TO add_spec_element;
1344         x_return_status := fnd_api.g_ret_sts_unexp_error;
1345         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1346             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1347         END IF;
1348         fnd_msg_pub.count_and_get(
1349             p_count => x_msg_count,
1350             p_data  => x_msg_data
1351         );
1352 
1353 END add_spec_element;
1354 
1355 
1356 PROCEDURE complete_spec_processing(
1357     p_api_version               IN      NUMBER,
1358     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1359     p_user_name                 IN      VARCHAR2 := NULL,
1360     p_spec_name                 IN      VARCHAR2,
1361     p_organization_code         IN      VARCHAR2,
1362     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1363     x_msg_count                 OUT     NOCOPY NUMBER,
1364     x_msg_data                  OUT     NOCOPY VARCHAR2,
1365     x_return_status             OUT     NOCOPY VARCHAR2) IS
1366 
1367     l_api_name          CONSTANT VARCHAR2(30):= 'complete_spec_definition';
1368     l_api_version       CONSTANT NUMBER      := 1.0;
1369 
1370     l_user_id   NUMBER;
1371     l_spec_id   NUMBER;
1372 
1373 BEGIN
1374 
1375     -- Standard Start of API savepoint
1376 
1377     SAVEPOINT complete_spec_definition;
1378 
1379     -- Standard call to check for call compatibility.
1380     IF NOT fnd_api.compatible_api_call(
1381         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1382         RAISE fnd_api.g_exc_unexpected_error;
1383     END IF;
1384 
1385     -- Initialize message list if p_init_msg_list is set to TRUE.
1386     IF fnd_api.to_boolean(p_init_msg_list) THEN
1387         fnd_msg_pub.initialize;
1388     END IF;
1389 
1390     --  Initialize API return status to success
1391     x_return_status := fnd_api.g_ret_sts_success;
1392 
1393     l_user_id := get_user_id(p_user_name);
1394     IF l_user_id = -1 THEN
1395         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1396         fnd_msg_pub.add();
1397         raise fnd_api.g_exc_error;
1398     END IF;
1399 
1400     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1401     check_for_spec_element(l_spec_id);
1402 
1403     IF fnd_api.to_boolean(p_commit) THEN
1404         COMMIT;
1405     END IF;
1406 
1407 EXCEPTION
1408 
1409     WHEN fnd_api.g_exc_error THEN
1410         ROLLBACK TO complete_spec_definition;
1411         x_return_status := fnd_api.g_ret_sts_error;
1412         fnd_msg_pub.count_and_get(
1413             p_count => x_msg_count,
1414             p_data  => x_msg_data
1415         );
1416 
1417      WHEN fnd_api.g_exc_unexpected_error THEN
1418         ROLLBACK TO complete_spec_definition;
1419         x_return_status := fnd_api.g_ret_sts_unexp_error;
1420         fnd_msg_pub.count_and_get(
1421             p_count => x_msg_count,
1422             p_data  => x_msg_data
1423         );
1424 
1425      WHEN OTHERS THEN
1426         ROLLBACK TO complete_spec_definition;
1427         x_return_status := fnd_api.g_ret_sts_unexp_error;
1428         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1429             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1430         END IF;
1431         fnd_msg_pub.count_and_get(
1432             p_count => x_msg_count,
1433             p_data  => x_msg_data
1434         );
1435 
1436 END complete_spec_processing;
1437 
1438 
1439 PROCEDURE delete_spec_private(p_spec_id IN NUMBER) IS
1440 --
1441 -- The real work of deleting a specification and all its
1442 -- spec elements.  Do not commit.
1443 --
1444 BEGIN
1445 
1446     DELETE
1447     FROM qa_spec_chars
1448     WHERE spec_id = p_spec_id;
1449 
1450     DELETE
1451     FROM qa_specs
1452     WHERE spec_id = p_spec_id;
1453 
1454 END delete_spec_private;
1455 
1456 PROCEDURE delete_spec_element_private(
1457     p_spec_id IN NUMBER,
1458     p_element_id IN NUMBER) IS
1459 
1460 BEGIN
1461 
1462     DELETE
1463     FROM qa_spec_chars
1464     WHERE spec_id = p_spec_id
1465     AND char_id = p_element_id;
1466 
1467 END delete_spec_element_private;
1468 
1469 
1470 --
1471 -- Should not allow deletion if there exists
1472 -- at least one child spec. Use child_spec_exists
1473 -- rkunchal
1474 --
1475 
1476 PROCEDURE delete_specification(
1477     p_api_version               IN      NUMBER,
1478     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1479     p_user_name                 IN      VARCHAR2 := NULL,
1480     p_spec_name                 IN      VARCHAR2,
1481     p_organization_code         IN      VARCHAR2,
1482     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1483     x_msg_count                 OUT     NOCOPY NUMBER,
1484     x_msg_data                  OUT     NOCOPY VARCHAR2,
1485     x_return_status             OUT     NOCOPY VARCHAR2) IS
1486 
1487     l_api_name                  CONSTANT VARCHAR2(30):= 'delete_specification';
1488     l_api_version               CONSTANT NUMBER      := 1.0;
1489 
1490     l_user_id      NUMBER;
1491     l_spec_id      NUMBER;
1492     l_org_id       NUMBER;
1493 
1494 BEGIN
1495 
1496     -- Standard Start of API savepoint
1497 
1498     SAVEPOINT   delete_specification;
1499 
1500     -- Standard call to check for call compatibility.
1501     IF NOT fnd_api.compatible_api_call(
1502         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1503         RAISE fnd_api.g_exc_unexpected_error;
1504     END IF;
1505 
1506     -- Initialize message list if p_init_msg_list is set to TRUE.
1507     IF fnd_api.to_boolean(p_init_msg_list) THEN
1508         fnd_msg_pub.initialize;
1509     END IF;
1510 
1511     --  Initialize API return status to success
1512     x_return_status := fnd_api.g_ret_sts_success;
1513 
1514     l_user_id := get_user_id(p_user_name);
1515     IF l_user_id = -1 THEN
1516         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1517         fnd_msg_pub.add();
1518         raise fnd_api.g_exc_error;
1519     END IF;
1520 
1521     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1522 
1523     -- Perfect place to check for child specs
1524     IF child_spec_exists(l_spec_id) THEN
1525         fnd_message.set_name('QA', 'QA_CHILD_SPECS_EXIST');
1526         fnd_msg_pub.add();
1527         raise fnd_api.g_exc_error;
1528     END IF;
1529 
1530     delete_spec_private(l_spec_id);
1531 
1532     IF fnd_api.to_boolean(p_commit) THEN
1533         COMMIT;
1534     END IF;
1535 
1536 EXCEPTION
1537 
1538     WHEN fnd_api.g_exc_error THEN
1539         ROLLBACK TO delete_specification;
1540         x_return_status := fnd_api.g_ret_sts_error;
1541         fnd_msg_pub.count_and_get(
1542             p_count => x_msg_count,
1543             p_data  => x_msg_data
1544         );
1545 
1546      WHEN fnd_api.g_exc_unexpected_error THEN
1547         ROLLBACK TO delete_specification;
1548         x_return_status := fnd_api.g_ret_sts_unexp_error;
1549         fnd_msg_pub.count_and_get(
1550             p_count => x_msg_count,
1551             p_data  => x_msg_data
1552         );
1553 
1554      WHEN OTHERS THEN
1555         ROLLBACK TO delete_specification;
1556         x_return_status := fnd_api.g_ret_sts_unexp_error;
1557         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1558             fnd_msg_pub.Add_Exc_Msg(g_pkg_name, l_api_name);
1559         END IF;
1560         fnd_msg_pub.count_and_get(
1561             p_count => x_msg_count,
1562             p_data  => x_msg_data
1563         );
1564 
1565 END delete_specification;
1566 
1567 --
1568 -- Though this will not effectively do anything for child specs,
1569 -- we want to give an impression to caller that this operation
1570 -- on a child spec is not functionally valid and is discouraged.
1571 --
1572 -- rkunchal
1573 --
1574 
1575 PROCEDURE delete_spec_element(
1576     p_api_version               IN      NUMBER,
1577     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1578     p_user_name                 IN      VARCHAR2 := NULL,
1579     p_spec_name                 IN      VARCHAR2,
1580     p_organization_code         IN      VARCHAR2,
1581     p_element_name              IN      VARCHAR2,
1582     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1583     x_msg_count                 OUT     NOCOPY NUMBER,
1584     x_msg_data                  OUT     NOCOPY VARCHAR2,
1585     x_return_status             OUT     NOCOPY VARCHAR2) IS
1586 
1587     l_api_name                  CONSTANT VARCHAR2(30):= 'delete_spec_element';
1588     l_api_version               CONSTANT NUMBER      := 1.0;
1589 
1590     l_user_id   NUMBER;
1591     l_spec_id   NUMBER;
1592     l_char_id   NUMBER;
1593     l_org_id    NUMBER;
1594 
1595 BEGIN
1596 
1597     -- Standard Start of API savepoint
1598 
1599     SAVEPOINT delete_spec_element;
1600 
1601     -- Standard call to check for call compatibility.
1602     IF NOT fnd_api.compatible_api_call(
1603         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1604         RAISE fnd_api.g_exc_unexpected_error;
1605     END IF;
1606 
1607     -- Initialize message list if p_init_msg_list is set to TRUE.
1608     IF fnd_api.to_boolean(p_init_msg_list) THEN
1609         fnd_msg_pub.initialize;
1610     END IF;
1611 
1612     --  Initialize API return status to success
1613     x_return_status := fnd_api.g_ret_sts_success;
1614 
1615     l_user_id := get_user_id(p_user_name);
1616     IF l_user_id = -1 THEN
1617         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1618         fnd_msg_pub.add();
1619         raise fnd_api.g_exc_error;
1620     END IF;
1621 
1622     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1623 
1624     -- We must be checking here if the spec is a child
1625     IF is_child_spec(l_spec_id) THEN
1626         fnd_message.set_name('QA', 'QA_DELETE_SPEC_ELEM_ON_CHILD');
1627         fnd_msg_pub.add();
1628         raise fnd_api.g_exc_error;
1629     END IF;
1630 
1631     l_char_id := get_context_element_id(p_element_name);
1632 
1633     delete_spec_element_private(l_spec_id, l_char_id);
1634 
1635     IF fnd_api.to_boolean(p_commit) THEN
1636         COMMIT;
1637     END IF;
1638 
1639 EXCEPTION
1640 
1641     WHEN fnd_api.g_exc_error THEN
1642         ROLLBACK TO delete_spec_element;
1643         x_return_status := fnd_api.g_ret_sts_error;
1644         fnd_msg_pub.count_and_get(
1645             p_count => x_msg_count,
1646             p_data  => x_msg_data
1647         );
1648 
1649      WHEN fnd_api.g_exc_unexpected_error THEN
1650         ROLLBACK TO delete_spec_element;
1651         x_return_status := fnd_api.g_ret_sts_unexp_error;
1652         fnd_msg_pub.count_and_get(
1653             p_count => x_msg_count,
1654             p_data  => x_msg_data
1655         );
1656 
1657      WHEN OTHERS THEN
1658         ROLLBACK TO delete_spec_element;
1659         x_return_status := fnd_api.g_ret_sts_unexp_error;
1660         IF fnd_msg_pub.Check_Msg_Level(FND_MSG_PUB.G_MSG_LVL_UNEXP_ERROR) THEN
1661             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1662         END IF;
1663         fnd_msg_pub.count_and_get(
1664             p_count => x_msg_count,
1665             p_data  => x_msg_data
1666         );
1667 
1668 END delete_spec_element;
1669 
1670 --
1671 -- We should not copy Spec Elements if the spec being copied is a child.
1672 -- The new, copied spec still references the same master spec.
1673 -- Copying child is seemless and caller will not see any message.
1674 --
1675 -- rkunchal
1676 --
1677 
1678 PROCEDURE copy_specification(
1679     p_api_version               IN      NUMBER,
1680     p_init_msg_list             IN      VARCHAR2 := fnd_api.g_false,
1681     p_user_name                 IN      VARCHAR2 := NULL,
1682     p_spec_name                 IN      VARCHAR2,
1683     p_organization_code         IN      VARCHAR2,
1684     p_to_spec_name              IN      VARCHAR2,
1685     p_to_organization_code      IN      VARCHAR2,
1686     p_to_item_name              IN      VARCHAR2,
1687     p_to_item_revision          IN      VARCHAR2 := NULL,
1688     p_commit                    IN      VARCHAR2 := fnd_api.g_false,
1689     x_spec_id                   OUT     NOCOPY NUMBER,
1690     x_msg_count                 OUT     NOCOPY NUMBER,
1691     x_msg_data                  OUT     NOCOPY VARCHAR2,
1692     x_return_status             OUT     NOCOPY VARCHAR2) IS
1693 
1694     l_api_name                  CONSTANT VARCHAR2(30):= 'copy_specification';
1695     l_api_version               CONSTANT NUMBER      := 1.0;
1696 
1697     l_user_id                   NUMBER;
1698     l_spec_id                   NUMBER;
1699     l_org_id                    NUMBER;
1700     l_spec_name                 NUMBER;
1701     l_to_org_id                 NUMBER;
1702     l_category_set_id           NUMBER;
1703     l_category_id               NUMBER;
1704     l_to_item_id                NUMBER;
1705     l_to_item_revision          NUMBER;
1706     l_vendor_id                 NUMBER;
1707     l_customer_id               NUMBER;
1708     l_char_id                   NUMBER;
1709     l_spec_element_value        VARCHAR2(150);
1710     l_existing_spec_name        VARCHAR2(30);
1711 
1712     --BUG 3500244
1713     --we do NOT support ERES in APIs as documented in QA FDA HLD
1714     --so this should behave as though ERES profile is No
1715     --which means spec_status of 40 which is No Approval Reqd
1716     --should be used for spec creation since it is a NON-Null Column
1717 
1718     l_spec_status               NUMBER := 40;
1719 
1720 BEGIN
1721 
1722     -- Standard Start of API savepoint
1723 
1724     SAVEPOINT copy_specification;
1725 
1726     -- Standard call to check for call compatibility.
1727     IF NOT fnd_api.compatible_api_call(
1728         l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
1729         RAISE fnd_api.g_exc_unexpected_error;
1730     END IF;
1731 
1732     -- Initialize message list if p_init_msg_list is set to TRUE.
1733     IF fnd_api.to_boolean(p_init_msg_list) THEN
1734         fnd_msg_pub.initialize;
1735     END IF;
1736 
1737     --  Initialize API return status to success
1738     x_return_status := fnd_api.g_ret_sts_success;
1739 
1740     l_user_id := get_user_id(p_user_name);
1741     IF l_user_id = -1 THEN
1742         fnd_message.set_name('QA', 'QA_API_INVALID_USER');
1743         fnd_msg_pub.add();
1744         raise fnd_api.g_exc_error;
1745     END IF;
1746 
1747     l_spec_id := get_spec_id(p_spec_name, p_organization_code);
1748     l_org_id := organization_id(l_spec_id);
1749 
1750     l_to_org_id := qa_plans_api.get_org_id(p_to_organization_code);
1751     IF (l_to_org_id IS NULL) THEN
1752         fnd_message.set_name('QA', 'QA_API_INVALID_ORG_CODE');
1753         fnd_msg_pub.add();
1754         RAISE fnd_api.g_exc_error;
1755     END IF;
1756 
1757     IF (spec_exists(p_to_spec_name)) THEN
1758         fnd_message.set_name('QA', 'QA_API_DUPLICATE_SPEC_NAME');
1759         fnd_msg_pub.add();
1760         RAISE fnd_api.g_exc_error;
1761     END IF;
1762 
1763     l_to_item_id := process_item_and_revision(p_to_item_name,
1764         p_to_item_revision, l_org_id);
1765 
1766     l_category_set_id           := category_set_id(l_spec_id);
1767     l_category_id               := category_id(l_spec_id);
1768     l_vendor_id                 := vendor_id(l_spec_id);
1769     l_customer_id               := customer_id(l_spec_id);
1770     l_char_id                   := char_id(l_spec_id);
1771     l_spec_element_value        := spec_element_value(l_spec_id);
1772 
1773     IF (combination_exists(l_category_set_id, l_category_id, l_to_item_id,
1774         p_to_item_revision, l_org_id, l_vendor_id, l_customer_id, l_char_id,
1775         l_spec_element_value, l_existing_spec_name)) THEN
1776 
1777         fnd_message.set_name('QA', 'QA_SPEC_COMBINATION_EXISTS');
1778         fnd_message.set_token('ENTITY1', l_existing_spec_name);
1779         fnd_msg_pub.add();
1780         RAISE fnd_api.g_exc_error;
1781     END IF;
1782 
1783     SELECT qa_specs_s.nextval INTO x_spec_id FROM DUAL;
1784 
1785     INSERT INTO qa_specs(
1786         spec_id,
1787         last_update_date,
1788         last_updated_by,
1789         creation_date,
1790         created_by,
1791         last_update_login,
1792         spec_name,
1793         organization_id,
1794         effective_from,
1795         effective_to,
1796         common_spec_id,
1797         assignment_type,
1798         category_set_id,
1799         category_id,
1800         item_id,
1801         item_revision,
1802         vendor_id,
1803         customer_id,
1804         hide_plan_chars_flag,
1805         char_id,
1806         spec_element_value,
1807         spec_status ) --Bug 3500244
1808     SELECT
1809         x_spec_id,
1810         sysdate,
1811         l_user_id,
1812         sysdate,
1813         l_user_id,
1814         l_user_id,
1815         p_to_spec_name,
1816         l_to_org_id,
1817         effective_from,
1818         effective_to,
1819         common_spec_id,
1820         assignment_type,
1821         category_set_id,
1822         category_id,
1823         l_to_item_id,
1824         nvl(p_to_item_revision, 'NONE'),
1825         vendor_id,
1826         customer_id,
1827         hide_plan_chars_flag,
1828         char_id,
1829         spec_element_value,
1830         40                 --Bug 3500244 see note below
1831     FROM qa_specs
1832     WHERE spec_id = l_spec_id;
1833 
1834     --Bug 3500244
1835     --In above Select we have not used the variable l_spec_status
1836     --But purposely used the literal 40 so it is very clear for readability
1837     --that we are not selecting from database, but it is kind of a constant
1838 
1839 
1840     -- Prevent this insertion if the spec being copied is a child spec
1841     IF NOT is_child_spec(l_spec_id) THEN
1842       INSERT INTO qa_spec_chars(
1843         spec_id,
1844         char_id,
1845         last_update_date,
1846         last_updated_by,
1847         creation_date,
1848         created_by,
1849         last_update_login,
1850         enabled_flag,
1851         target_value,
1852         upper_spec_limit,
1853         lower_spec_limit,
1854         upper_reasonable_limit,
1855         lower_reasonable_limit,
1856         upper_user_defined_limit,
1857         lower_user_defined_limit)
1858       SELECT
1859         x_spec_id,
1860         char_id,
1861         sysdate,
1862         l_user_id,
1863         sysdate,
1864         l_user_id,
1865         l_user_id,
1866         enabled_flag,
1867         target_value,
1868         upper_spec_limit,
1869         lower_spec_limit,
1870         upper_user_defined_limit,
1871         lower_user_defined_limit,
1872         upper_reasonable_limit,
1873         lower_reasonable_limit
1874       FROM qa_spec_chars
1875       WHERE spec_id = l_spec_id;
1876     END IF;
1877 
1878     --
1879     -- Bug 5231952.  After copying, we should copy attachments.
1880     --
1881     qa_specs_pkg.copy_attachment(
1882         p_from_spec_id => l_spec_id,
1883         p_to_spec_id => x_spec_id);
1884 
1885     IF fnd_api.to_boolean(p_commit) THEN
1886         COMMIT;
1887     END IF;
1888 
1889 EXCEPTION
1890 
1891     WHEN fnd_api.g_exc_error THEN
1892         ROLLBACK TO copy_specification;
1893         x_return_status := fnd_api.g_ret_sts_error;
1894         fnd_msg_pub.count_and_get(
1895             p_count => x_msg_count,
1896             p_data  => x_msg_data
1897         );
1898 
1899      WHEN fnd_api.g_exc_unexpected_error THEN
1900         ROLLBACK TO copy_specification;
1901         x_return_status := fnd_api.g_ret_sts_unexp_error;
1902         fnd_msg_pub.count_and_get(
1903             p_count => x_msg_count,
1904             p_data  => x_msg_data
1905         );
1906 
1907      WHEN OTHERS THEN
1908         ROLLBACK TO copy_specification;
1909         x_return_status := fnd_api.g_ret_sts_unexp_error;
1910         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1911             fnd_msg_pub.Add_Exc_Msg(g_pkg_name, l_api_name);
1912         END IF;
1913         fnd_msg_pub.count_and_get(
1914             p_count => x_msg_count,
1915             p_data  => x_msg_data
1916         );
1917 
1918 END copy_specification;
1919 
1920 
1921 END qa_specs_pub;
1922