DBA Data[Home] [Help]

PACKAGE BODY: APPS.BOM_CONFIG_VALIDATION_PUB

Source


1 PACKAGE BODY BOM_Config_Validation_Pub AS
2 /* $Header: BOMPCFGB.pls 120.1 2005/12/02 04:44:03 hgelli noship $ */
3 
4 G_PKG_NAME      CONSTANT    VARCHAR2(30):='BOM_Config_Validation_Pub';
5 
6 
7 /*-----------------------------------------------------------------------
8 Forward Declarations
9 ------------------------------------------------------------------------*/
10 
11 Procedure Check_Min_Max
12 ( p_top_bill_sequence_id     IN  NUMBER
13  ,p_model_qty                IN  NUMBER
14  ,p_effective_date           IN  DATE
15  ,p_options_tbl              IN  VALIDATE_OPTIONS_TBL_TYPE
16  ,x_valid_config             OUT NOCOPY VARCHAR2
17  ,x_return_status            OUT NOCOPY VARCHAR2);
18 
19 
20 PROCEDURE Check_Ratio_And_Parent
21 (p_options_tbl             IN  VALIDATE_OPTIONS_TBL_TYPE
22 ,p_top_model_line_id       IN  NUMBER
23 ,x_return_status           OUT NOCOPY VARCHAR2);
24 
25 
26 PROCEDURE Check_Class_Has_Options
27 (p_options_tbl             IN  VALIDATE_OPTIONS_TBL_TYPE
28 ,x_complete_config         OUT NOCOPY VARCHAR2
29 ,x_return_status           OUT NOCOPY VARCHAR2);
30 
31 
32 PROCEDURE Check_Mut_Excl_Options
33  ( p_top_bill_sequence_id     IN  NUMBER
34   ,p_effective_date           IN  DATE
35   ,p_options_tbl              IN  VALIDATE_OPTIONS_TBL_TYPE
36   ,x_valid_config             OUT NOCOPY VARCHAR2
37   ,x_return_status            OUT NOCOPY VARCHAR2);
38 
39 
40 PROCEDURE Check_Mandatory_Classes
41  ( p_top_bill_sequence_id     IN  NUMBER
42   ,p_top_model_line_id        IN  NUMBER
43   ,p_effective_date           IN  DATE
44   ,p_options_tbl              IN  VALIDATE_OPTIONS_TBL_TYPE
45   ,x_complete_config          OUT NOCOPY VARCHAR2
46   ,x_return_status            OUT NOCOPY VARCHAR2);
47 
48 
49 FUNCTION Mutually_Exclusive_Comps_exist
50 ( p_options_tbl     IN   VALIDATE_OPTIONS_TBL_TYPE
51  ,p_component_code  IN   VARCHAR2)
52 RETURN BOOLEAN;
53 
54 
55 FUNCTION Mandatory_Comps_Missing
56 ( p_options_tbl     IN   VALIDATE_OPTIONS_TBL_TYPE
57  ,p_component_code  IN   VARCHAR2)
58 RETURN BOOLEAN;
59 
60 
61 FUNCTION Get_Parent_Quantity
62 ( p_component_code     IN  VARCHAR2
63  ,p_top_model_line_id  IN  NUMBER
64  ,p_options_tbl        IN  VALIDATE_OPTIONS_TBL_TYPE)
65 RETURN NUMBER;
66 
67 
68 FUNCTION Check_Option_Exist
69 ( p_component_code   IN  VARCHAR2
70  ,p_options_tbl      IN  VALIDATE_OPTIONS_TBL_TYPE)
71 RETURN BOOLEAN;
72 
73 
74 FUNCTION Check_Parent_Exists
75 ( p_component_code     IN  VARCHAR2
76  ,p_index              IN  NUMBER
77  ,p_top_model_line_id  IN  NUMBER
78  ,p_options_tbl        IN  VALIDATE_OPTIONS_TBL_TYPE)
79 RETURN BOOLEAN;
80 
81 
82 PROCEDURE Handle_Ret_Status
83 (p_valid_config    IN VARCHAR2 := NULL
84 ,p_complete_config IN VARCHAR2 := NULL);
85 
86 
87 PROCEDURE Print_Time(p_msg   IN  VARCHAR2);
88 
89 /*-----------------------------------------------------------------------
90 PROCEDURE: Bom_Based_Config_Validation
91 
92 This API takes a list of selected options (p_options_tbl) for the
93 top level model(p_top_model_line_id ) in OM.
94 
95 It performs certain validations based on the BOM setup.
96 1) if the ordered quantity of any option is not out side of
97    the Min - Max quantity settings in BOM.
98 2) if the ratio of ordered quantity of a class to model
99    and option to class is integer ratio i.e. exact multiple.
100 3) to see that a class does not exist w/o any options selected for it.
101 4) if a class that has mutually exclusive options, does not have
102    more than one options selected under it.
103 5) if at least one option is selected per mandatory class.
104 
105 If any of the validation fails, it will populate error messages
106 and will return with a status of error.
107 
108 Change Record:
109 
110 ER2625376: changes made to BOM should be visible to Order unitl Booking.
111 
112 OE_Config_Util.Get_Config_effective_Date should be used to decide
113 the date for effective/diabled filter on bom_explosions sqls.
114 
115 p_creatione_date parameter will be renamed to p_effective_date.
116 ------------------------------------------------------------------------*/
117 
118 Procedure Bom_Based_Config_Validation
119 ( p_top_model_line_id     IN  NUMBER
120  ,p_options_tbl           IN  VALIDATE_OPTIONS_TBL_TYPE
121  ,x_valid_config          OUT NOCOPY VARCHAR2
122  ,x_complete_config       OUT NOCOPY VARCHAR2
123  ,x_return_status         OUT NOCOPY VARCHAR2
124  )
125 IS
126   l_return_status           VARCHAR2(1) :=  FND_API.G_RET_STS_SUCCESS;
127   l_top_bill_sequence_id    NUMBER;
128   l_effective_date          DATE;
129   l_model_qty               NUMBER;
130   l_valid_config            VARCHAR2(10);
131   l_complete_config         VARCHAR2(10);
132   l_old_behavior            VARCHAR2(1);
133   l_frozen_model_bill       VARCHAR2(1);
134   --
135   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
136   --
137 BEGIN
138 
139   IF l_debug_level  > 0 THEN
140       oe_debug_pub.add('ENTERING BOM_BASED_CONFIG_VALIDATION' , 1 ) ;
141   END IF;
142   Print_Time('Bom_Based_Config_Validation start time');
143 
144   G_VALID_CONFIG    := 'TRUE';
145   G_COMPLETE_CONFIG := 'TRUE';
146 
147   BEGIN
148     SELECT component_sequence_id, ordered_quantity
149     INTO   l_top_bill_sequence_id, l_model_qty
150     FROM   oe_order_lines
151     WHERE  line_id = p_top_model_line_id;
152   EXCEPTION
153     WHEN OTHERS THEN
154       IF l_debug_level  > 0 THEN
155           oe_debug_pub.add('SELECT FAILED '|| SQLERRM , 1 ) ;
156       END IF;
157       RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
158   END;
159 
160 
161   OE_Config_Util.Get_Config_Effective_Date
162   ( p_model_line_id         => p_top_model_line_id
163    ,x_old_behavior          => l_old_behavior
164    ,x_config_effective_date => l_effective_date
165    ,x_frozen_model_bill     => l_frozen_model_bill);
166 
167 
168   IF l_debug_level  > 0 THEN
169       oe_debug_pub.add('CALLING CHECK_RATIO_AND_PARENT' , 1 ) ;
170   END IF;
171 
172   Check_Ratio_And_Parent
173  ( p_options_tbl              => p_options_tbl
174   ,p_top_model_line_id        => p_top_model_line_id
175   ,x_return_status            => l_return_status);
176 
177   IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
178     Handle_Ret_Status(p_valid_config   => l_valid_config);
179   END IF;
180 
181   IF l_debug_level  > 0 THEN
182       oe_debug_pub.add('CALLING CHECK_MIN_MAX' , 1 ) ;
183   END IF;
184 
185   Check_Min_Max
186  ( p_top_bill_sequence_id     => l_top_bill_sequence_id
187   ,p_model_qty                => l_model_qty
188   ,p_effective_date           => l_effective_date
189   ,p_options_tbl              => p_options_tbl
190   ,x_valid_config             => l_valid_config
191   ,x_return_status            => l_return_status);
192 
193   IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
194     Handle_Ret_Status(p_valid_config   => l_valid_config);
195   END IF;
196 
197 
198   IF l_debug_level  > 0 THEN
199       oe_debug_pub.add('CALLING CHECK_CLASS_HAS_OPTIONS' , 1 ) ;
200   END IF;
201 
202   Check_Class_Has_Options
203  ( p_options_tbl              => p_options_tbl
204   ,x_complete_config          => l_complete_config
205   ,x_return_status            => l_return_status);
206 
207   IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
208     Handle_Ret_Status(p_complete_config   => l_complete_config);
209   END IF;
210 
211   IF l_debug_level  > 0 THEN
212       oe_debug_pub.add('CALLING CHECK_MUT_EXCL_OPTIONS' , 1 ) ;
213   END IF;
214 
215   Check_Mut_Excl_Options
216  ( p_top_bill_sequence_id     => l_top_bill_sequence_id
217   ,p_effective_date           => l_effective_date
218   ,p_options_tbl              => p_options_tbl
219   ,x_valid_config             => l_valid_config
220   ,x_return_status            => l_return_status);
221 
222   IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
223     Handle_Ret_Status(p_valid_config   => l_valid_config);
224   END IF;
225 
226 
227   IF l_debug_level  > 0 THEN
228       oe_debug_pub.add('CALLIN CHECK_MANDATORY_CLASSES' , 1 ) ;
229   END IF;
230 
231   Check_Mandatory_Classes
232  ( p_top_bill_sequence_id     => l_top_bill_sequence_id
233   ,p_top_model_line_id        => p_top_model_line_id
234   ,p_effective_date           => l_effective_date
235   ,p_options_tbl              => p_options_tbl
236   ,x_complete_config          => l_complete_config
237   ,x_return_status            => l_return_status);
238 
239   IF l_return_status <> FND_API.G_RET_STS_SUCCESS THEN
240     Handle_Ret_Status(p_complete_config   => l_complete_config);
241   END IF;
242 
243 
244   x_valid_config     := G_VALID_CONFIG;
245   x_complete_config  := G_COMPLETE_CONFIG;
246 
247   IF G_VALID_CONFIG    = 'FALSE' OR
248      G_COMPLETE_CONFIG = 'FALSE' THEN
249     x_return_status := FND_API.G_RET_STS_ERROR;
250   ELSE
251     x_return_status := FND_API.G_RET_STS_SUCCESS;
252   END IF;
253 
254   Print_Time('Bom_Based_Config_Validation end time');
255   IF l_debug_level  > 0 THEN
256       oe_debug_pub.add('LEAVING BOM_BASED_CONFIG_VALIDATION'
257                        || X_RETURN_STATUS , 1 ) ;
258   END IF;
259 EXCEPTION
260   WHEN OTHERS THEN
261     IF l_debug_level  > 0 THEN
262         oe_debug_pub.add('BOM_BASED_CONFIG_VALIDATION EXCEPTION'|| SQLERRM,1);
263     END IF;
264     x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
265     RAISE;
266 END Bom_Based_Config_Validation;
267 
268 
269 /*------------------------------------------------------------------------
270 PROCEDURE: Check_Ratio_And_Parent
271 This procedure performs 2 checks,
272 1) that the child's ordered qty  should be excat mutilple of the parent.
273 2) option do not exist w/o its parent class.
274 
275 get the top model's quantity. We loop throgh the option table.
276 check the ratio of the quatities.
277 in the same run, check that the parent exists using a helper.
278 
279 any error in this check should not be allowed to be saved.
280 so raise exception.
281 
282  Part of the logic in this procedure will not be used any more
283  -- the decimal ratio check due to Decimal quantities for ATO Options
284  Project.The decimal ratio check will be part of line entity validation
285  in OEXLLINB.pls
286 -------------------------------------------------------------------------*/
287 
288 PROCEDURE Check_Ratio_And_Parent
289 (p_options_tbl             IN  VALIDATE_OPTIONS_TBL_TYPE
290 ,p_top_model_line_id       IN  NUMBER
291 ,x_return_status           OUT NOCOPY VARCHAR2)
292 IS
293   l_return_status          VARCHAR2(1):= FND_API.G_RET_STS_SUCCESS;
294   l_parent_qty             NUMBER;
295   I                        NUMBER;
296   l_parent_exists          BOOLEAN := FALSE;
297   l_ordered_item           VARCHAR2(2000);
298   l_item_type_code         VARCHAR2(30);
299   --
300   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
301   --
302 BEGIN
303   IF l_debug_level  > 0 THEN
304       oe_debug_pub.add('ENTERING CHECK_RATIO_AND_PARENT' , 1 ) ;
305   END IF;
306   Print_Time('Check_Ratio_And_Parent start time');
307 
308   SELECT ordered_quantity
309   INTO   l_parent_qty
310   FROM   oe_order_lines
311   WHERE  line_id = p_top_model_line_id;
312 
313   I := p_options_tbl.FIRST ;
314 
315   WHILE I is not null
316   LOOP
317     IF INSTR(p_options_tbl(I).component_code , '-') <> 0 THEN -- not for model
318 
319       /****************** commneted during OM pack J project
320       IF p_options_tbl(I).ordered_quantity = 0 THEN
321         IF l_debug_level  > 0 THEN
322             oe_debug_pub.add('QTY IS 0 , DONT CHECK'|| L_PARENT_QTY , 2 ) ;
323         END IF;
324 
325       ELSE
326         IF TRUNC(p_options_tbl(I).ordered_quantity/l_parent_qty) <>
327                 (p_options_tbl(I).ordered_quantity/l_parent_qty)
328         THEN
329           IF l_debug_level  > 0 THEN
330               oe_debug_pub.add('DECIMAL RATIO '||P_OPTIONS_TBL ( I ) .COMPONENT_CODE , 1 ) ;
331           END IF;
332 
333           FND_MESSAGE.Set_Name('ONT', 'OE_CONFIG_DECIMAL_RATIO');
334 
335           IF p_options_tbl(I).bom_item_type = 1 THEN
336             l_item_type_code := 'MODEL';
337           ELSIF p_options_tbl(I).bom_item_type = 2 THEN
338             l_item_type_code := 'CLASS';
339           ELSE
340             l_item_type_code := 'OPTION';
341           END IF;
342 
343           FND_MESSAGE.Set_TOKEN('ITEM', p_options_tbl(I).ordered_item);
344           FND_MESSAGE.Set_TOKEN('TYPECODE', l_item_type_code);
345           FND_MESSAGE.Set_TOKEN
346           ('VALUE', p_options_tbl(I).ordered_quantity/l_parent_qty);
347 
348           SELECT ordered_item, item_type_code
349           INTO   l_ordered_item, l_item_type_code
350           FROM   oe_order_lines
351           WHERE  line_id = p_top_model_line_id;
352 
353           FND_MESSAGE.Set_TOKEN('MODEL', l_ordered_item);
354           FND_MESSAGE.Set_TOKEN('PTYPECODE', l_item_type_code);
355 
356           OE_Msg_Pub.Add;
357 
358           RAISE FND_API.G_EXC_ERROR;
359         END IF;
360 
361       END IF; -- if the qty = 0
362 
363       *********************************************************/
364 
365       IF l_debug_level  > 0 THEN
366           oe_debug_pub.add('NOW CHECKING IF PARENT PRESENT' , 1 ) ;
367       END IF;
368       l_parent_exists :=  Check_Parent_Exists
369                         ( p_component_code => p_options_tbl(I).component_code
373 
370                          ,p_index              => I
371                          ,p_top_model_line_id  =>    p_top_model_line_id
372                          ,p_options_tbl        =>    p_options_tbl);
374       IF NOT l_parent_exists THEN
375         IF l_debug_level  > 0 THEN
376             oe_debug_pub.add('MAJOR ERROR , CAN NOT GO FURTHER' , 2 ) ;
377         END IF;
378         RAISE FND_API.G_EXC_ERROR;
379       END IF;
380 
381     END IF; -- if not model
382 
383     I := p_options_tbl.NEXT(I);
384   END LOOP;
385 
386   x_return_status := l_return_status;
387 
388   Print_Time('Check_Ratio_And_Parent end time');
389   IF l_debug_level  > 0 THEN
390       oe_debug_pub.add('LEAVING CHECK_RATIO_AND_PARENT' , 1 ) ;
391   END IF;
392 
393 EXCEPTION
394   WHEN OTHERS THEN
395     IF l_debug_level  > 0 THEN
396         oe_debug_pub.add('CHECK_RATIO_AND_PARENT EXCEPTION'|| SQLERRM , 1 ) ;
397     END IF;
398     RAISE;
399 END Check_Ratio_And_Parent;
400 
401 
402 /*-----------------------------------------------------------------------
403 PROCEDURE: Check_Parent_Exists
404 This procedure is used to detect corrupt data(Oracle IT had this).
405 To see if every item in the configuration has immediate parent selected.
406 ------------------------------------------------------------------------*/
407 FUNCTION Check_Parent_Exists
408 ( p_component_code     IN  VARCHAR2
409  ,p_index              IN  NUMBER
410  ,p_top_model_line_id  IN  NUMBER
411  ,p_options_tbl        IN  VALIDATE_OPTIONS_TBL_TYPE)
412 RETURN BOOLEAN
413 IS
414   I                        NUMBER;
415   l_open_flag              VARCHAR2(1);
416   l_ordered_item           VARCHAR2(2000);
417   l_line                   VARCHAR2(100);
418   l_line_number            NUMBER;
419   l_shipment_number        NUMBER;
420   l_option_number          NUMBER;
421   --
422   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
423   --
424 BEGIN
425 
426   IF l_debug_level  > 0 THEN
427       oe_debug_pub.add('ENTERING CHECK_PARENT_EXISTS'|| P_COMPONENT_CODE , 1 ) ;
428   END IF;
429   Print_Time('Check_Parent_Exists start time');
430 
431   I := p_options_tbl.FIRST;
432   WHILE I is not null
433   LOOP
434     IF p_options_tbl(I).component_code =  SUBSTR(p_component_code, 1,
435                                          INSTR(p_component_code, '-', -1) - 1)
436     THEN
437       IF l_debug_level  > 0 THEN
438           oe_debug_pub.add('PARENT FOUND '|| P_OPTIONS_TBL ( I ) .COMPONENT_CODE , 1 ) ;
439       END IF;
440       RETURN TRUE;
441     END IF;
442 
443     I := p_options_tbl.NEXT(I);
444   END LOOP;
445 
446   IF l_debug_level  > 0 THEN
447       oe_debug_pub.add('PARENT NOT FOUND , MAY BE CANCELED' , 1 ) ;
448   END IF;
449 
450   BEGIN
451 
452     -- should not get more than 1 rows in all cases.
453     SELECT open_flag
454     INTO l_open_flag
455     FROM oe_order_lines
456     where line_id =
457     (SELECT line_id
458      FROM   oe_order_lines
459      WHERE  top_model_line_id = p_top_model_line_id
460      AND    component_code = SUBSTR(p_component_code, 1,
461                              INSTR(p_component_code, '-', -1) - 1));
462 
463     IF l_debug_level  > 0 THEN
464         oe_debug_pub.add('OPEN_FLAG , QTY: '|| L_OPEN_FLAG , 3 ) ;
465     END IF;
466 
467     IF l_open_flag = 'N' THEN
468       IF l_debug_level  > 0 THEN
469           oe_debug_pub.add('PARENT WAS CANCELLED' , 3 ) ;
470       END IF;
471       RETURN TRUE;
472     END IF;
473 
474   EXCEPTION
475     WHEN NO_DATA_FOUND THEN
476       IF l_debug_level  > 0 THEN
477           oe_debug_pub.add('NO PARENT' , 3 ) ;
478       END IF;
479 
480       FND_MESSAGE.Set_Name('ONT', 'OE_CONFIG_NO_PARENT');
481       FND_MESSAGE.Set_TOKEN('ITEM', p_options_tbl(p_index).ordered_item);
482 
483       BEGIN
484         SELECT ordered_item, line_number, shipment_number, option_number
485         INTO   l_ordered_item, l_line_number, l_shipment_number, l_option_number
486         FROM   oe_order_lines
487         WHERE  top_model_line_id = p_top_model_line_id
488         AND    component_code = p_component_code;
489 
490         l_line := l_line_number || '.'|| l_shipment_number ||'.'|| l_option_number;
491 
492       EXCEPTION
493         WHEN NO_DATA_FOUND THEN
494           l_line := null;
495       END;
496 
497       IF l_debug_level  > 0 THEN
498           oe_debug_pub.add('NOT YET CREATED' , 3 ) ;
499       END IF;
500 
501       FND_MESSAGE.Set_TOKEN('LINE', l_line);
502       OE_MSG_PUB.Add;
503 
504       RAISE FND_API.G_EXC_ERROR;
505   END;
506 
507   RETURN FALSE;
508 
509 EXCEPTION
510   WHEN OTHERS THEN
511     IF l_debug_level  > 0 THEN
512         oe_debug_pub.add('CHECK_PARENT_EXISTS EXCEPTION'|| SQLERRM , 1 ) ;
513     END IF;
514       RETURN FALSE;
515 END Check_Parent_Exists;
516 
517 
518 
519 /*-----------------------------------------------------------------------
520 PROCEDURE: Check_Min_Max
521 This procedure loops through the options table.
522 For each option,
523 it selects the min and max quantity from bom_explosions table. Some or all
524 of the options might not have the min max range set up in the BOM set up.
525 if the ordered quantity is not within the range, it popuplates a message
526 and it sets the return staus to error.
527 If all the options are within the min max range, we return success.
528 ------------------------------------------------------------------------*/
529 Procedure Check_Min_Max
533  ,p_options_tbl              IN  VALIDATE_OPTIONS_TBL_TYPE
530 ( p_top_bill_sequence_id     IN  NUMBER
531  ,p_model_qty                IN  NUMBER
532  ,p_effective_date           IN  DATE
534  ,x_valid_config             OUT NOCOPY VARCHAR2
535  ,x_return_status            OUT NOCOPY VARCHAR2)
536 IS
537   I                               NUMBER;
538   l_max_allowed_qty               NUMBER;
539   l_min_allowed_qty               NUMBER;
540   l_return_status                 VARCHAR2(1) := FND_API.G_RET_STS_SUCCESS;
541   l_valid_config                  VARCHAR2(10) := 'TRUE';
542   --
543   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
544   --
545 BEGIN
546   IF l_debug_level  > 0 THEN
547       oe_debug_pub.add('ENTERING CHECK_MIN_MAX' , 1 ) ;
548   END IF;
549   Print_Time('Check_Min_Max start time');
550 
551   I := p_options_tbl.FIRST;
552 
553   WHILE I is not NULL
554 
555   LOOP
556     IF l_debug_level  > 0 THEN
557         oe_debug_pub.add('CHECKING MIN MAK FOR: '|| P_OPTIONS_TBL ( I ) .COMPONENT_CODE , 1 ) ;
558     END IF;
559     -- if the qty is 0, we delete the line before cancellation
560     -- we close the line after cancellation, so no need to do this check.
561 
562     IF p_options_tbl(I).ordered_quantity = 0 THEN
563       IF l_debug_level  > 0 THEN
564           oe_debug_pub.add('NO CHECK SINCE QTY = 0' ) ;
565       END IF;
566     ELSE
567 
568       SELECT /*+ INDEX(BE1 BOM_EXPLOSIONS_N1) */
569           nvl(be1.high_quantity,0), nvl(be1.low_quantity,0)
570       INTO   l_max_allowed_qty, l_min_allowed_qty
571       FROM   bom_explosions be1
572       WHERE  be1.TOP_BILL_SEQUENCE_ID = p_top_bill_sequence_id
573       AND    be1.component_code = p_options_tbl(I).component_code
574       AND    be1.effectivity_date <=
575                           p_effective_date
576       AND    be1.disable_date >
577                           p_effective_date
578       AND    be1.explosion_type = 'OPTIONAL'
579       AND    be1.plan_level >= 0;
580       --AND    be1.sort_order = p_options_tbl(I).sort_order;
581 
582       IF l_min_allowed_qty <> 0 AND l_max_allowed_qty <> 0 THEN
583 
584         -- the trunc functions below were added for bugfix 3870948
585         IF trunc(p_options_tbl(I).ordered_quantity/p_model_qty,9) < l_min_allowed_qty OR
586            trunc(p_options_tbl(I).ordered_quantity/p_model_qty,9) > l_max_allowed_qty
587         THEN
588 
589           IF l_debug_level  > 0 THEN
590               oe_debug_pub.add('ORDERED QTY OUT OF RANGE' || P_OPTIONS_TBL ( I ) .ORDERED_QUANTITY , 1 ) ;
591           END IF;
592           IF l_debug_level  > 0 THEN
593               oe_debug_pub.add('MIN: '||L_MIN_ALLOWED_QTY || 'MAX: '||L_MAX_ALLOWED_QTY , 1 ) ;
594           END IF;
595           IF l_debug_level  > 0 THEN
596               oe_debug_pub.add('ITEM'|| P_OPTIONS_TBL ( I ) .ORDERED_ITEM , 1 ) ;
597           END IF;
598 
599           FND_MESSAGE.Set_Name('ONT', 'OE_VAL_CONFIG_QTY_OUT_OF_RANGE');
600           FND_MESSAGE.Set_Token('ITEM', p_options_tbl(I).ordered_item);
601           FND_MESSAGE.Set_Token('LOW', l_min_allowed_qty);
602           FND_MESSAGE.Set_Token('HIGH', l_max_allowed_qty);
603           OE_Msg_Pub.Add;
604           l_valid_config  := 'FALSE';
605           l_return_status := FND_API.G_RET_STS_ERROR;
606         END IF;
607 
608       ELSE
609         IF l_debug_level  > 0 THEN
610             oe_debug_pub.add('MIN MAX RANGE NOT SET' , 1 ) ;
611         END IF;
612       END IF; -- if there is min max setting
613 
614     END IF; -- if the qty was 0
615 
616     I := p_options_tbl.NEXT(I);
617   END LOOP;
618 
619   x_valid_config  := l_valid_config;
620   x_return_status := l_return_status;
621 
622   Print_Time('Check_Min_Max end time');
623   IF l_debug_level  > 0 THEN
624       oe_debug_pub.add('LEAVING CHECK_MIN_MAX' , 1 ) ;
625   END IF;
626 
627 EXCEPTION
628   WHEN OTHERS THEN
629     IF l_debug_level  > 0 THEN
630         oe_debug_pub.add('CHECK_MIN_MAX EXCEPTION'|| SQLERRM , 1 ) ;
631     END IF;
632     RAISE;
633 END Check_Min_Max;
634 
635 
636 /*------------------------------------------------------------------------
637 FUNCTION: Check_Class_Has_Options
638 All the classes in a configuration should have at least
639 one option selected.
640 -------------------------------------------------------------------------*/
641 PROCEDURE Check_Class_Has_Options
642 (p_options_tbl             IN  VALIDATE_OPTIONS_TBL_TYPE
643 ,x_complete_config         OUT NOCOPY VARCHAR2
644 ,x_return_status           OUT NOCOPY VARCHAR2)
645 IS
646   I                 NUMBER;
647   l_no_child        BOOLEAN;
648   l_return_status   VARCHAR2(1):= FND_API.G_RET_STS_SUCCESS;
649   l_complete_config VARCHAR2(10) := 'TRUE';
650   --
651   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
652   --
653 BEGIN
654   IF l_debug_level  > 0 THEN
655       oe_debug_pub.add('ENTERING CHECK_CLASS_HAS_OPTIONS' , 1 ) ;
656   END IF;
657   Print_Time('Check_Class_Has_Options start time');
658 
659   I := p_options_tbl.FIRST ;
660 
661   WHILE I is not null
662   LOOP
663     IF l_debug_level  > 0 THEN
664         oe_debug_pub.add('BOM_ITEM_TYPE: '|| P_OPTIONS_TBL ( I ) .BOM_ITEM_TYPE , 1 ) ;
665     END IF;
666     -- model line has null, so will not go in.
667     IF p_options_tbl(I).bom_item_type = 2 THEN
668 
669       IF p_options_tbl(I).ordered_quantity = 0 THEN
670         IF l_debug_level  > 0 THEN
671             oe_debug_pub.add('NO NEED TO CHECK , EITHER DELETE OR CLOSE' , 1 ) ;
672         END IF;
673 
674       ELSE
675 
676         l_no_child := Check_Option_Exist
680           FND_MESSAGE.Set_Name('ONT', 'OE_VAL_CONFIG_CLASS_NO_OPTION');
677                       ( p_component_code   => p_options_tbl(I).component_code
678                        ,p_options_tbl      => p_options_tbl);
679         IF NOT l_no_child THEN
681           FND_MESSAGE.Set_Token('CLASS', p_options_tbl(I).ordered_item);
682           OE_Msg_Pub.Add;
683           l_complete_config  := 'FALSE';
684           l_return_status    := FND_API.G_RET_STS_ERROR;
685         END IF; -- if no child
686 
687       END IF; -- if qty = 0
688 
689     END IF; -- if a class
690 
691     I := p_options_tbl.NEXT(I);
692   END LOOP;
693 
694   x_complete_config  := l_complete_config;
695   x_return_status    := l_return_status;
696 
697   Print_Time('Check_Class_Has_Options end time');
698   IF l_debug_level  > 0 THEN
699       oe_debug_pub.add('LEAVING CHECK_CLASS_HAS_OPTIONS' , 1 ) ;
700   END IF;
701 EXCEPTION
702   WHEN OTHERS THEN
703     IF l_debug_level  > 0 THEN
704         oe_debug_pub.add('CHECK_CLASS_HAS_OPTIONS EXCEPTION'|| SQLERRM , 1 ) ;
705     END IF;
706     RAISE;
707 END Check_Class_Has_Options;
708 
709 
710 /*------------------------------------------------------------------------
711 FUNCTION: Check_Option_Exist
712 p_component_code is the class for which we will find out
713 if a option exist or not.
714 -------------------------------------------------------------------------*/
715 FUNCTION Check_Option_Exist
716 ( p_component_code   IN  VARCHAR2
717  ,p_options_tbl      IN  VALIDATE_OPTIONS_TBL_TYPE)
718 RETURN BOOLEAN
719 IS
720   I    NUMBER;
721   --
722   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
723   --
724 BEGIN
725   IF l_debug_level  > 0 THEN
726       oe_debug_pub.add('ENTERING CHECK_OPTION_EXIST' , 1 ) ;
727   END IF;
728 
729   I := p_options_tbl.FIRST;
730   WHILE I is not null
731   LOOP
732     IF p_component_code = SUBSTR(p_options_tbl(I).component_code, 1,
733                                  INSTR(p_options_tbl(I).component_code, '-', -1) - 1)
734     THEN
735       IF l_debug_level  > 0 THEN
736           oe_debug_pub.add('CHILD FOUND '|| P_OPTIONS_TBL ( I ) .COMPONENT_CODE , 1 ) ;
737       END IF;
738       RETURN true;
739     END IF;
740 
741     I := p_options_tbl.NEXT(I);
742   END LOOP;
743 
744   IF l_debug_level  > 0 THEN
745       oe_debug_pub.add('LEAVING CHECK_OPTION_EXIST WITH NO CHILD' , 1 ) ;
746   END IF;
747   RETURN false;
748 EXCEPTION
749   WHEN OTHERS THEN
750     IF l_debug_level  > 0 THEN
751         oe_debug_pub.add('CHECK_OPTION_EXIST EXCEPTION'|| SQLERRM , 1 ) ;
752     END IF;
753     RAISE;
754 END Check_Option_Exist;
755 
756 
757 /*------------------------------------------------------------------------
758 PROCEDURE: Check_Mut_Excl_Options
759 Opens a cursor of all the classes which have mutually exclusive options
760 set up in the BOM.
761 For every such class,
762 finds out if more than one option is selected. If so, it popuplates a error
763 message and sets the return status to error.
764 If all the classes with mutually exclusive options have only one option
765 selected, it returs success.
766 -------------------------------------------------------------------------*/
767 
768 PROCEDURE Check_Mut_Excl_Options
769  ( p_top_bill_sequence_id     IN  NUMBER
770   ,p_effective_date           IN  DATE
771   ,p_options_tbl              IN  VALIDATE_OPTIONS_TBL_TYPE
772   ,x_valid_config             OUT NOCOPY VARCHAR2
773   ,x_return_status            OUT NOCOPY VARCHAR2)
774 IS
775   I                               NUMBER;
776   l_top_bill_sequence_id          NUMBER;
777   l_description                   VARCHAR2(240);
778   l_component_code                VARCHAR2(1000);
779   l_result                        BOOLEAN;
780   l_return_status                 VARCHAR2(1):= FND_API.G_RET_STS_SUCCESS;
781   l_valid_config                  VARCHAR2(10) := 'TRUE';
782 
783   CURSOR MUTUALLY_EXCLUSIVE_OPTIONS IS
784   SELECT   /*+ INDEX(BOMEXP BOM_EXPLOSIONS_N1) */
785       bomexp.description, bomexp.component_code
786   FROM     BOM_EXPLOSIONS BOMEXP
787   WHERE    bomexp.explosion_type = 'OPTIONAL'
788   AND      bomexp.top_bill_sequence_id = p_top_bill_sequence_id
789   AND      bomexp.plan_level >= 0
790   AND      bomexp.effectivity_date <=
791            p_effective_date
792   AND      bomexp.disable_date >
793            p_effective_date
794   AND      bomexp.bom_item_type in ( 1, 2 ) /* Model, Class */
795   AND      bomexp.mutually_exclusive_options = 1 /* Exclusive */
796   ORDER BY bomexp.sort_order;
797 
798 --
799 l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
800 --
801 BEGIN
802   IF l_debug_level  > 0 THEN
803       oe_debug_pub.add('ENTERING CHECK_MUT_EXCL_OPTIONS' , 1 ) ;
804   END IF;
805   Print_Time('Check_Mut_Excl_Options start time');
806 
807   FOR bom_rec in MUTUALLY_EXCLUSIVE_OPTIONS
808   LOOP
809     l_result := Mutually_Exclusive_Comps_exist
810                 ( p_options_tbl     => p_options_tbl
811                  ,p_component_code  => bom_rec.component_code);
812 
813     IF l_result THEN
814       FND_MESSAGE.Set_Name('ONT', 'OE_VAL_CONFIG_EXCLUSIVE_CLASS');
815       FND_MESSAGE.Set_Token('CLASS', bom_rec.description);
816       OE_Msg_Pub.Add;
817       l_valid_config  := 'FALSE';
818       l_return_status := FND_API.G_RET_STS_ERROR;
819     END IF;
820 
821   END LOOP;
822 
823   x_valid_config  := l_valid_config;
824   x_return_status := l_return_status;
825 
826   Print_Time('Check_Mut_Excl_Options end time');
827   IF l_debug_level  > 0 THEN
831   WHEN OTHERS THEN
828       oe_debug_pub.add('LEAVING CHECK_MUT_EXCL_OPTIONS' , 1 ) ;
829   END IF;
830 EXCEPTION
832     IF l_debug_level  > 0 THEN
833         oe_debug_pub.add('CHECK_MUT_EXCL_OPTIONS EXCEPTION'|| SQLERRM , 1 ) ;
834     END IF;
835     RAISE;
836 END Check_Mut_Excl_Options;
837 
838 
839 /*------------------------------------------------------------------------
840 FUNCTION Mutually_Exclusive_Comps_exist
841 
842 This function will be called for 1 class with
843 mutually exclusive options at a time.
844 
845 Loop through options table, find ou number of options for class
846 p_component_code, using the component_code field.
847 e.g.:
848 p_component_code => 100-200
849 p_options_tbl    =>
850 100-200     -- mutually exclusive options set in BOM.
851 100-200-300 -- 1st
852 100-200-400 -- 2nd, this is error
853 100-500
854 100
855 
856 IF a configuration has more than 1 components from a class
857 that has mutually exclusive options, this function returns true.
858 Else it returns false.
859 -------------------------------------------------------------------------*/
860 
861 FUNCTION Mutually_Exclusive_Comps_exist
862 ( p_options_tbl     IN  VALIDATE_OPTIONS_TBL_TYPE
863  ,p_component_code  IN  VARCHAR2)
864 RETURN BOOLEAN
865 IS
866   l_count       NUMBER;
867   I             NUMBER;
868   l_component   VARCHAR2(1000);
869   --
870   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
871   --
872 BEGIN
873   IF l_debug_level  > 0 THEN
874       oe_debug_pub.add('ENTERING MUTUALLY_EXCLUSIVE_COMPS_EXIST' , 1 ) ;
875   END IF;
876 
877  I := p_options_tbl.FIRST;
878 
879   l_count := 0;
880 
881   WHILE I is not NULL AND l_count < 2
882   LOOP
883     l_component := SUBSTR(p_options_tbl(I).component_code,
884                           1, (INSTR(p_options_tbl(I).component_code, '-', -1) - 1));
885 
886     IF l_component = p_component_code AND
887        p_options_tbl(I).ordered_quantity <> 0 -- if 0, either will be deleted or closed
888     THEN
889       l_count := l_count + 1;
890       IF l_debug_level  > 0 THEN
891           oe_debug_pub.add(  L_COUNT ||' OPTION PRESENT'|| P_OPTIONS_TBL ( I ) .COMPONENT_CODE , 2 ) ;
892       END IF;
893     END IF;
894 
895     I := p_options_tbl.NEXT(I);
896   END LOOP;
897 
898   IF l_count >= 2 THEN
899     RETURN true;
900   ELSE
901     IF l_debug_level  > 0 THEN
902         oe_debug_pub.add('NO MUTAUL EXCLUSION IN CLASS '|| P_COMPONENT_CODE , 1 ) ;
903     END IF;
904     RETURN false;
905   END IF;
906 
907   IF l_debug_level  > 0 THEN
908       oe_debug_pub.add('LEAVING MUTUALLY_EXCLUSIVE_COMPS_EXIST' , 1 ) ;
909   END IF;
910 EXCEPTION
911   WHEN OTHERS THEN
912     IF l_debug_level  > 0 THEN
913         oe_debug_pub.add('MUTUALLY_EXCLUSIVE_COMPS_EXIST EXCEPTION'|| SQLERRM , 1 ) ;
914     END IF;
915     RAISE;
916 END Mutually_Exclusive_Comps_exist;
917 
918 
919 /*------------------------------------------------------------------------
920 PROCEDURE: Check_Mandatory_Classes
921 Opens a cursor which has all classes which are mandatory to this model.
922 For every such class,
923 check if at least one option is selectd. If not populte error messate and
924 set retruns status to error.
925 -------------------------------------------------------------------------*/
926 
927 PROCEDURE Check_Mandatory_Classes
928  ( p_top_bill_sequence_id     IN  NUMBER
929   ,p_top_model_line_id        IN  NUMBER
930   ,p_effective_date           IN  DATE
931   ,p_options_tbl              IN  VALIDATE_OPTIONS_TBL_TYPE
932   ,x_complete_config          OUT NOCOPY VARCHAR2
933   ,x_return_status            OUT NOCOPY VARCHAR2)
934 IS
935   l_top_bill_sequence_id          NUMBER;
936   l_description                   VARCHAR2(240);
937   l_component_code                VARCHAR2(1000);
938   l_result                        BOOLEAN;
939   l_return_status                 VARCHAR2(1):= FND_API.G_RET_STS_SUCCESS;
940   l_complete_config               VARCHAR2(10) := 'TRUE';
941 
942   CURSOR MANDATORY_COMPONENTS IS
943   SELECT /*+ INDEX(BOMEXP BOM_EXPLOSIONS_N1) */
944       bomexp.description, bomexp.component_code
945         --,bomexp.sort_order???? perf
946   FROM  bom_explosions bomexp
947   WHERE bomexp.explosion_type = 'OPTIONAL'
948   AND   bomexp.top_bill_sequence_id = p_top_bill_sequence_id
949   AND   bomexp.plan_level >= 0
950   AND   bomexp.effectivity_date <=
951         p_effective_date
952   AND   bomexp.disable_date >
953         p_effective_date
954   AND   bomexp.bom_item_type IN ( 1, 2 )  -- Model, Class
955   AND   bomexp.optional = 2;               -- Mandatory
956 
957 /*
958   CURSOR MANDATORY_COMPONENTS IS
959   SELECT bomexp.description, bomexp.component_code
960   FROM     OE_ORDER_LINES OECFG
961   ,        BOM_EXPLOSIONS BOMEXP
962   WHERE   OECFG.TOP_MODEL_LINE_ID = p_top_model_line_id
963   AND     OECFG.SERVICE_REFERENCE_LINE_ID IS NULL
964   AND     OECFG.ITEM_TYPE_CODE IN ( 'MODEL', 'CLASS' )
965   AND     BOMEXP.EXPLOSION_TYPE = 'OPTIONAL'
966   AND     BOMEXP.TOP_BILL_SEQUENCE_ID = p_top_bill_sequence_id ???????? + 0
967   AND     BOMEXP.PLAN_LEVEL >= 0
968   AND     BOMEXP.EFFECTIVITY_DATE <= sysdate
969   AND     BOMEXP.DISABLE_DATE > sysdate
970   AND     BOMEXP.BOM_ITEM_TYPE IN ( 1, 2 )  Model, Class
971   AND     BOMEXP.OPTIONAL = 2  Mandatory
972   AND     BOMEXP.Component_code like OECFG.component_code || '%'
973   AND     SUBSTR( BOMEXP.COMPONENT_CODE, 1,
974           LENGTH( RTRIM( BOMEXP.COMPONENT_CODE,
975                  '0123456789' ) ) - 1 ) = OECFG.COMPONENT_CODE
976   AND     NOT EXISTS (
977           SELECT NULL
981           AND    OEOPT.COMPONENT_CODE = BOMEXP.COMPONENT_CODE
978           FROM   OE_ORDER_LINES OEOPT
979           WHERE  OEOPT.TOP_MODEL_LINE_ID = p_top_model_line_id
980           AND    OEOPT.SERVICE_REFERENCE_LINE_ID IS NULL
982           )
983   ORDER BY BOMEXP.SORT_ORDER;
984 */
985 --
986 l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
987 --
988 BEGIN
989   IF l_debug_level  > 0 THEN
990       oe_debug_pub.add('ENTERING CHECK_MANDATORY_CLASSES' , 1 ) ;
991   END IF;
992   Print_Time('Check_Mandatory_Classes start time');
993 
994   for bom_rec in MANDATORY_COMPONENTS
995   LOOP
996     l_result := Mandatory_Comps_Missing
997                 ( p_options_tbl     => p_options_tbl
998                  ,p_component_code  => bom_rec.component_code);
999 
1000     IF l_result THEN
1001       FND_MESSAGE.Set_Name('ONT', 'OE_VAL_CONFIG_MANDATORY_CLASS');
1002       FND_MESSAGE.Set_Token('CLASS', bom_rec.description);
1003       OE_Msg_Pub.Add;
1004       l_complete_config  := 'FALSE';
1005       l_return_status    := FND_API.G_RET_STS_ERROR;
1006     END IF;
1007 
1008   END LOOP;
1009 
1010   x_complete_config  := l_complete_config;
1011   x_return_status    := l_return_status;
1012 
1013   Print_Time('Check_Mandatory_Classes end time');
1014   IF l_debug_level  > 0 THEN
1015       oe_debug_pub.add('LEAVING CHECK_MANDATORY_CLASSES '|| L_RETURN_STATUS , 1 ) ;
1016   END IF;
1017 EXCEPTION
1018   WHEN OTHERS THEN
1019     IF l_debug_level  > 0 THEN
1020         oe_debug_pub.add('CHECK_MANDATORY_CLASSES EXCEPTION'|| SQLERRM , 1 ) ;
1021     END IF;
1022     RAISE;
1023 END Check_Mandatory_Classes;
1024 
1025 
1026 /*------------------------------------------------------------------------
1027 FUNCTION: Mandatory_Comps_Missing
1028 
1029 This function finds out if a mandatory component is missing
1030 in the configuration, working on one class at a time.
1031 
1032 It uses the pl/sql table of options => p_options_tbl to figure out if
1033 any of the mandatory components for a particular class/model =>
1034 p_component_code is missing.
1035 
1036 Returns true, if finds out that mandatory component is missing.
1037 Else returns false.
1038 e.g.=>
1039 p_component_code => 100-500
1040 p_options_tbl    =>
1041 100-200
1042 100-200-300
1043 100-500 -- mandatory class w/o options is error.
1044 100
1045 
1046 -------------------------------------------------------------------------*/
1047 FUNCTION Mandatory_Comps_Missing
1048 ( p_options_tbl     IN   VALIDATE_OPTIONS_TBL_TYPE
1049  ,p_component_code  IN   VARCHAR2)
1050 RETURN BOOLEAN
1051 IS
1052 I             NUMBER;
1053 l_found       BOOLEAN;
1054 l_component   VARCHAR2(1000);
1055 J             NUMBER;
1056 l_parent      BOOLEAN;
1057 l_parent_component   VARCHAR2(1000);
1058 --
1059 l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
1060 --
1061 BEGIN
1062 
1063   IF l_debug_level  > 0 THEN
1064       oe_debug_pub.add('ENTERING MANDATORY_COMPS_MISSING' , 1 ) ;
1065   END IF;
1066   IF l_debug_level  > 0 THEN
1067       oe_debug_pub.add('COMPONENT IN ' || P_COMPONENT_CODE , 2 ) ;
1068   END IF;
1069 
1070   -- Check for mandatory component parent existance in the table.
1071   -- Look for options only if the parent of the passed component is
1072   -- found. Other wise return false.
1073 
1074   l_parent := false;
1075 
1076   l_parent_component :=  SUBSTR(p_component_code,1,
1077                          (INSTR(p_component_code, '-', -1) -1));
1078 
1079   J  := p_options_tbl.FIRST;
1080 
1081   WHILE J is not NULL AND NOT l_parent
1082   LOOP
1083 
1084    --bug3542229: Front porting
1085    --Make sure that the option class itself is present
1086    --The parent may be present due to selection of some other child
1087    --as well
1088    IF l_debug_level > 0 THEN
1089       oe_debug_pub.add('ORDQTY:'||p_options_tbl(J).ordered_quantity);
1090    END IF;
1091 
1092    --IF  p_options_tbl(J).component_code = p_component_code AND
1093    IF p_options_tbl(J).component_code = l_parent_component AND --fp: 3618150
1094        p_options_tbl(J).ordered_quantity <> 0
1095    THEN
1096        l_parent := true;
1097        IF l_debug_level  > 0 THEN
1098           oe_debug_pub.add('PARENT FOUND ' || L_PARENT_COMPONENT , 2 ) ;
1099        END IF;
1100    END IF;
1101 
1102    J :=  p_options_tbl.NEXT(J);
1103 
1104   END LOOP;
1105 
1106 
1107  IF l_parent THEN
1108     I := p_options_tbl.FIRST;
1109 
1110     l_found := false;
1111 
1112     WHILE I is not NULL AND NOT l_found
1113     LOOP
1114        l_component := SUBSTR(p_options_tbl(I).component_code, 1,
1115 				  (INSTR(p_options_tbl(I).component_code, '-', -1) - 1));
1116 
1117        IF l_component = p_component_code AND
1118           p_options_tbl(I).ordered_quantity <> 0
1119        THEN
1120          IF l_debug_level  > 0 THEN
1121              oe_debug_pub.add('MANDATORY OPTION PRESENT'|| P_OPTIONS_TBL ( I ) .COMPONENT_CODE , 2 ) ;
1122          END IF;
1123          l_found := true;
1124        END IF;
1125 
1126        I := p_options_tbl.NEXT(I);
1127     END LOOP;
1128 
1129     IF l_found THEN
1130        RETURN false;
1131     ELSE
1132        IF l_debug_level  > 0 THEN
1133            oe_debug_pub.add('MANDATORY COMP MISSING IN CLASS '|| L_COMPONENT , 1 ) ;
1134        END IF;
1135        RETURN true;
1136     END IF;
1137 
1138  ELSE
1139 
1140    RETURN false;
1141 
1142  END IF;
1143 
1144   IF l_debug_level  > 0 THEN
1145       oe_debug_pub.add('LEAVING MANDATORY_COMPS_MISSING' , 1 ) ;
1146   END IF;
1147 EXCEPTION
1151     END IF;
1148   WHEN OTHERS THEN
1149     IF l_debug_level  > 0 THEN
1150         oe_debug_pub.add('MANDATORY_COMPS_MISSING EXCEPTION'|| SQLERRM , 1 ) ;
1152     RAISE;
1153 END Mandatory_Comps_Missing;
1154 
1155 
1156 /*------------------------------------------------------------------------
1157 PROCEDURE Print_Time
1158 
1159 -------------------------------------------------------------------------*/
1160 
1161 PROCEDURE Print_Time(p_msg   IN  VARCHAR2)
1162 IS
1163   l_time    VARCHAR2(100);
1164   --
1165   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
1166   --
1167 BEGIN
1168   l_time := to_char (new_time (sysdate, 'PST', 'EST'),
1169                                  'DD-MON-YY HH24:MI:SS');
1170   IF l_debug_level  > 0 THEN
1171       oe_debug_pub.add(  P_MSG || ': '|| L_TIME , 1 ) ;
1172   END IF;
1173 END Print_Time;
1174 
1175 
1176 /*------------------------------------------------------------------------
1177 PROCEDURE Handle_Ret_Status
1178 
1179 -------------------------------------------------------------------------*/
1180 
1181 PROCEDURE Handle_Ret_Status
1182 (p_valid_config    IN VARCHAR2 := NULL
1183 ,p_complete_config IN VARCHAR2 := NULL)
1184 IS
1185 --
1186 l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
1187 --
1188 BEGIN
1189   IF nvl(p_valid_config, 'TRUE') = 'FALSE' THEN
1190     IF l_debug_level  > 0 THEN
1191         oe_debug_pub.add('SETTING VALID_CONFIG TO FALSE' , 1 ) ;
1192     END IF;
1193     G_VALID_CONFIG := 'FALSE';
1194   END IF;
1195 
1196   IF nvl(p_complete_config, 'TRUE') = 'FALSE' THEN
1197     IF l_debug_level  > 0 THEN
1198         oe_debug_pub.add('SETTING COMPLETE_CONFIG TO FALSE' , 1 ) ;
1199     END IF;
1200     G_VALID_CONFIG := 'FALSE';
1201   END IF;
1202 END Handle_Ret_Status;
1203 
1204 
1205 
1206 /*------------------------------------------------------------------------
1207 FUNCTION: Get_Parent_Quantity
1208 Loops through p_options_tbl. Finds out  the parent of p_component_code
1209 using component_code field in the p_options_tbl. returns parent's qty.
1210 
1211 Not used, similar code in Check_Parent_Exists.
1212 -------------------------------------------------------------------------*/
1213 FUNCTION Get_Parent_Quantity
1214 ( p_component_code     IN  VARCHAR2
1215  ,p_top_model_line_id  IN  NUMBER
1216  ,p_options_tbl        IN  VALIDATE_OPTIONS_TBL_TYPE)
1217 RETURN NUMBER
1218 IS
1219   I                    NUMBER;
1220   l_open_flag          VARCHAR2(1);
1221   l_ordered_quantity   NUMBER;
1222   l_ordered_item       VARCHAR2(2000);
1223   l_line_number        NUMBER;
1224   l_shipment_number    NUMBER;
1225   l_option_number      NUMBER;
1226   --
1227   l_debug_level CONSTANT NUMBER := oe_debug_pub.g_debug_level;
1228   --
1229 BEGIN
1230   IF l_debug_level  > 0 THEN
1231       oe_debug_pub.add('ENTERING GET_PARENT_QUANTITY' , 1 ) ;
1232   END IF;
1233   IF l_debug_level  > 0 THEN
1234       oe_debug_pub.add('FIND PARENT QTY FOR: '|| P_COMPONENT_CODE , 1 ) ;
1235   END IF;
1236 
1237   I := p_options_tbl.FIRST;
1238   WHILE I is not null
1239   LOOP
1240     IF p_options_tbl(I).component_code =  SUBSTR(p_component_code, 1,
1241                                           INSTR(p_component_code, '-', -1) - 1)
1242     THEN
1243       IF l_debug_level  > 0 THEN
1244           oe_debug_pub.add('PARENT FOUND '|| P_OPTIONS_TBL ( I ) .COMPONENT_CODE , 1 ) ;
1245       END IF;
1246       RETURN p_options_tbl(I).ordered_quantity;
1247     END IF;
1248 
1249     I := p_options_tbl.NEXT(I);
1250   END LOOP;
1251 
1252   IF l_debug_level  > 0 THEN
1253       oe_debug_pub.add('NO PARENT FOR ' || P_COMPONENT_CODE , 1 ) ;
1254   END IF;
1255   RAISE FND_API.G_EXC_ERROR;
1256 
1257 EXCEPTION
1258   WHEN FND_API.G_EXC_ERROR THEN
1259     IF l_debug_level  > 0 THEN
1260         oe_debug_pub.add('PARENT NOT FOUND , MAY BE CANCELED' , 1 ) ;
1261     END IF;
1262 
1263     BEGIN
1264 
1265       SELECT open_flag, ordered_quantity
1266       INTO l_open_flag, l_ordered_quantity
1267       FROM oe_order_lines
1268       where line_id =
1269       (SELECT line_id
1270        FROM   oe_order_lines
1271        WHERE  top_model_line_id = p_top_model_line_id
1272        AND    component_code = SUBSTR(p_component_code, 1,
1273                                INSTR(p_component_code, '-', -1) - 1));
1274 
1275        IF l_debug_level  > 0 THEN
1276            oe_debug_pub.add('OPEN_FLAG , QTY: '|| L_OPEN_FLAG || L_ORDERED_QUANTITY , 3 ) ;
1277        END IF;
1278 
1279       IF l_open_flag = 'N' THEN
1280         IF l_debug_level  > 0 THEN
1281             oe_debug_pub.add('PARENT WAS CANCELLED' , 3 ) ;
1282         END IF;
1283         RETURN l_ordered_quantity;
1284       END IF;
1285     EXCEPTION
1286       WHEN NO_DATA_FOUND THEN
1287         IF l_debug_level  > 0 THEN
1288             oe_debug_pub.add('NO PARENT' , 3 ) ;
1289         END IF;
1290 
1291         SELECT ordered_item, line_number, shipment_number, option_number
1292         INTO   l_ordered_item, l_line_number, l_shipment_number, l_option_number
1293         FROM   oe_order_lines
1294         WHERE  top_model_line_id = p_top_model_line_id
1295         AND    component_code = p_component_code;
1296 
1297         FND_MESSAGE.Set_Name('ONT', 'OE_CONFIG_NO_PARENT');
1298         FND_MESSAGE.Set_TOKEN('ITEM', l_ordered_item);
1299         FND_MESSAGE.Set_TOKEN
1300         ('LINE', l_line_number || '.'|| l_shipment_number ||'.'|| l_option_number);
1301         OE_MSG_PUB.Add;
1302         RAISE FND_API.G_EXC_ERROR;
1303     END;
1304 
1305   WHEN OTHERS THEN
1306     IF l_debug_level  > 0 THEN
1310 END Get_Parent_Quantity;
1307         oe_debug_pub.add('GET_PARENT_QUANTITY EXCEPTION'|| SQLERRM , 1 ) ;
1308     END IF;
1309     RAISE;
1311 
1312 END BOM_Config_Validation_Pub;