DBA Data[Home] [Help]

PACKAGE BODY: APPS.OE_CONFIG_VALIDATION_PVT

Source


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