DBA Data[Home] [Help]

PACKAGE BODY: APPS.WMS_RULE_PVT

Source


1 PACKAGE BODY wms_rule_pvt AS
2   /* $Header: WMSVPPRB.pls 120.39.12010000.6 2009/01/21 10:32:10 avuppala ship $ */
3   --
4   -- File        : WMSVPPRB.pls
5   -- Content     : WMS_Rule_PVT package body
6   -- Description : wms rule private API's
7   -- Notes       :
8   -- Modified    : 02/08/99 mzeckzer created
9   --               03/29/99 bitang modified
10   --     01/17/99 jcearley added GenerateRulePackage function,
11   --             changed Apply to call stored function
12   --               02/11/00 lezhang added AssignTT procedures for task type
13   --                        assignment. Added CalcRuleWeight for this
14   --                        functionality. Also modified GenerateRulePackage and
15   --                        BuildRuleSQL.
16   --
17   --               06/30/02 grao added procedures to call pick, putaway, task,
18   --                        label rules statically. open cursor, fetch cursor and
19   --                        cursor calls affected. All the current dynamic calls
20   --                        to handle rules are disabled and not used any more.
21   --                        APPLY(), AssignTT(), ASSIGNLABEL()
22   --                        fetchcursor(), fetchPutaway() are modified.
23   --
24   --               07/11/02 grao Modified the Rules package generating code to
25   --                        conver all global variables in the rules packages to
26   --                        local variables and defined Pick and Putaway cursors
27   --                        as ref cursor, which is passed from the
28   --                        WMS_RULE_PVT as a ref Cursor. Also modified the open,
29   --                        fetch and close calls for Pick and Putaway rules
30 
31   --
32   -- Package global variable that stores the package name
33   g_pkg_name             CONSTANT VARCHAR2(30)                                            := 'WMS_Rule_PVT';
34   --
35   -- API versions used within this API
36   g_qty_tree_api_version CONSTANT NUMBER                                                  := 1.0; -- INV_Quantity_Tree_PVT
37   --
38   -- Caching locator record in DoProjectCheck
39   g_locator_id    NUMBER;
40   g_locator       INV_VALIDATE.locator;
41   g_transaction_type_id 	NUMBER;
42   g_organization_id 	NUMBER;
43   g_inventory_item_id 	NUMBER;
44   g_subinventory_code 	WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
45   g_allowed 	        VARCHAR2(1);
46   g_st_locator_id    NUMBER;
47   g_lpn_controlled_flag 	NUMBER;
48 
49   --g_serial_objects_used NUMBER ;
50 
51   -- Caching in function getconversionrate
52   g_gcr_organization_id    NUMBER;
53   g_gcr_inventory_item_id  NUMBER;
54   g_gcr_uom_code           VARCHAR2(3);
55   g_gcr_conversion_rate    NUMBER;
56 
57   g_debug                  NUMBER;
58   --
59   -- constants and global variables needed for dynamic SQL
60   --
61 
62   /* LG. need to talk to gopal, for all the non restircted loc, should do an outter join*/
63   g_put_base_no_restrict          LONG
64   := '
65  select  msei.secondary_inventory_name subinventory_code               --changed
66         ,mil.inventory_location_id locator_id
67         ,msei.organization_id organization_id                          --changed
68         ,mil.project_id project_id
69         ,mil.task_id task_id
70         ,g_inventory_item_id inventory_item_id
71         ,mil.location_current_units location_current_units
72         ,mil.inventory_item_id locator_inventory_item_id
73         ,mil.empty_flag empty_flag
74         ,mil.mixed_items_flag mixed_items_flag
75         ,mil.LAST_UPDATE_DATE
76         ,mil.LAST_UPDATED_BY
77         ,mil.CREATION_DATE
78         ,mil.CREATED_BY
79         ,mil.LAST_UPDATE_LOGIN
80         ,mil.DESCRIPTION
81         ,mil.DESCRIPTIVE_TEXT
82         ,mil.DISABLE_DATE
83         ,mil.INVENTORY_LOCATION_TYPE
84         ,mil.PICKING_ORDER
85         ,mil.PHYSICAL_LOCATION_CODE
86         ,mil.LOCATION_MAXIMUM_UNITS
87         ,mil.LOCATION_WEIGHT_UOM_CODE
88         ,mil.MAX_WEIGHT
89         ,mil.VOLUME_UOM_CODE
90         ,mil.MAX_CUBIC_AREA
91         ,mil.X_COORDINATE
92         ,mil.Y_COORDINATE
93         ,mil.Z_COORDINATE
94         ,mil.INVENTORY_ACCOUNT_ID
95         ,mil.SEGMENT1
96         ,mil.SEGMENT2
97         ,mil.SEGMENT3
98         ,mil.SEGMENT4
99         ,mil.SEGMENT5
100         ,mil.SEGMENT6
101         ,mil.SEGMENT7
102         ,mil.SEGMENT8
103         ,mil.SEGMENT9
104         ,mil.SEGMENT10
105         ,mil.SEGMENT11
106         ,mil.SEGMENT12
107         ,mil.SEGMENT13
108         ,mil.SEGMENT14
109         ,mil.SEGMENT15
110         ,mil.SEGMENT16
111         ,mil.SEGMENT17
112         ,mil.SEGMENT18
113         ,mil.SEGMENT19
114         ,mil.SEGMENT20
115         ,mil.SUMMARY_FLAG
116         ,mil.ENABLED_FLAG
117         ,mil.START_DATE_ACTIVE
118         ,mil.END_DATE_ACTIVE
119         ,mil.ATTRIBUTE_CATEGORY
120         ,mil.ATTRIBUTE1
121         ,mil.ATTRIBUTE2
122         ,mil.ATTRIBUTE3
123         ,mil.ATTRIBUTE4
124         ,mil.ATTRIBUTE5
125         ,mil.ATTRIBUTE6
126         ,mil.ATTRIBUTE7
127         ,mil.ATTRIBUTE8
128         ,mil.ATTRIBUTE9
129         ,mil.ATTRIBUTE10
130         ,mil.ATTRIBUTE11
131         ,mil.ATTRIBUTE12
132         ,mil.ATTRIBUTE13
133         ,mil.ATTRIBUTE14
134         ,mil.ATTRIBUTE15
135         ,mil.REQUEST_ID
136         ,mil.PROGRAM_APPLICATION_ID
137         ,mil.PROGRAM_ID
138         ,mil.PROGRAM_UPDATE_DATE
139         ,mil.PHYSICAL_LOCATION_ID
140         ,mil.PICK_UOM_CODE
141         ,mil.DIMENSION_UOM_CODE
142         ,mil.LENGTH
143         ,mil.WIDTH
144         ,mil.HEIGHT
145         ,mil.LOCATOR_STATUS
146         ,mil.STATUS_ID
147         ,mil.CURRENT_CUBIC_AREA
148         ,mil.AVAILABLE_CUBIC_AREA
149         ,mil.CURRENT_WEIGHT
150         ,mil.AVAILABLE_WEIGHT
151         ,mil.LOCATION_AVAILABLE_UNITS
152         ,mil.SUGGESTED_CUBIC_AREA
153         ,mil.SUGGESTED_WEIGHT
154         ,mil.LOCATION_SUGGESTED_UNITS
155         ,mil.rowid
156    from MTL_ITEM_LOCATIONS mil
157        ,MTL_SECONDARY_INVENTORIES msei
158   where mil.organization_id(+) = msei.organization_id
159     and mil.subinventory_code(+) = msei.secondary_inventory_name
160     and NVL(msei.disable_date, sysdate+1) > sysdate
161     and NVL(mil.disable_date, sysdate+1) > sysdate
162 ';
163   g_put_base_sub_restrict         LONG
164   := '
165  select  msei.secondary_inventory_name subinventory_code            -- changed
166         ,mil.inventory_location_id locator_id
167         ,msei.organization_id organization_id                       -- changed
168         ,mil.project_id project_id
169         ,mil.task_id task_id
170         ,g_inventory_item_id inventory_item_id
171         ,mil.location_current_units location_current_units
172         ,mil.inventory_item_id locator_inventory_item_id
173         ,mil.empty_flag empty_flag
174         ,mil.mixed_items_flag mixed_items_flag
175         ,mil.LAST_UPDATE_DATE
176         ,mil.LAST_UPDATED_BY
177         ,mil.CREATION_DATE
178         ,mil.CREATED_BY
179         ,mil.LAST_UPDATE_LOGIN
180         ,mil.DESCRIPTION
181         ,mil.DESCRIPTIVE_TEXT
182         ,mil.DISABLE_DATE
183         ,mil.INVENTORY_LOCATION_TYPE
184         ,mil.PICKING_ORDER
185         ,mil.PHYSICAL_LOCATION_CODE
186         ,mil.LOCATION_MAXIMUM_UNITS
187         ,mil.LOCATION_WEIGHT_UOM_CODE
188         ,mil.MAX_WEIGHT
189         ,mil.VOLUME_UOM_CODE
190         ,mil.MAX_CUBIC_AREA
191         ,mil.X_COORDINATE
192         ,mil.Y_COORDINATE
193         ,mil.Z_COORDINATE
194         ,mil.INVENTORY_ACCOUNT_ID
195         ,mil.SEGMENT1
196         ,mil.SEGMENT2
197         ,mil.SEGMENT3
198         ,mil.SEGMENT4
199         ,mil.SEGMENT5
200         ,mil.SEGMENT6
201         ,mil.SEGMENT7
202         ,mil.SEGMENT8
203         ,mil.SEGMENT9
204         ,mil.SEGMENT10
205         ,mil.SEGMENT11
206         ,mil.SEGMENT12
207         ,mil.SEGMENT13
208         ,mil.SEGMENT14
209         ,mil.SEGMENT15
210         ,mil.SEGMENT16
211         ,mil.SEGMENT17
212         ,mil.SEGMENT18
213         ,mil.SEGMENT19
214         ,mil.SEGMENT20
215         ,mil.SUMMARY_FLAG
216         ,mil.ENABLED_FLAG
217         ,mil.START_DATE_ACTIVE
218         ,mil.END_DATE_ACTIVE
219         ,mil.ATTRIBUTE_CATEGORY
220         ,mil.ATTRIBUTE1
221         ,mil.ATTRIBUTE2
222         ,mil.ATTRIBUTE3
223         ,mil.ATTRIBUTE4
224         ,mil.ATTRIBUTE5
225         ,mil.ATTRIBUTE6
226         ,mil.ATTRIBUTE7
227         ,mil.ATTRIBUTE8
228         ,mil.ATTRIBUTE9
229         ,mil.ATTRIBUTE10
230         ,mil.ATTRIBUTE11
231         ,mil.ATTRIBUTE12
232         ,mil.ATTRIBUTE13
233         ,mil.ATTRIBUTE14
234         ,mil.ATTRIBUTE15
235         ,mil.REQUEST_ID
236         ,mil.PROGRAM_APPLICATION_ID
237         ,mil.PROGRAM_ID
238         ,mil.PROGRAM_UPDATE_DATE
239         ,mil.PHYSICAL_LOCATION_ID
240         ,mil.PICK_UOM_CODE
241         ,mil.DIMENSION_UOM_CODE
242         ,mil.LENGTH
243         ,mil.WIDTH
244         ,mil.HEIGHT
245         ,mil.LOCATOR_STATUS
246         ,mil.STATUS_ID
247         ,mil.CURRENT_CUBIC_AREA
248         ,mil.AVAILABLE_CUBIC_AREA
249         ,mil.CURRENT_WEIGHT
250         ,mil.AVAILABLE_WEIGHT
251         ,mil.LOCATION_AVAILABLE_UNITS
252         ,mil.SUGGESTED_CUBIC_AREA
253         ,mil.SUGGESTED_WEIGHT
254         ,mil.LOCATION_SUGGESTED_UNITS
255   ,mil.rowid
256 from MTL_ITEM_LOCATIONS mil
257        ,MTL_SECONDARY_INVENTORIES msei
258        ,MTL_ITEM_SUB_INVENTORIES misi
259   where mil.organization_id(+) = msei.organization_id
260     and mil.subinventory_code(+) = msei.secondary_inventory_name
261     and NVL(msei.disable_date, sysdate+1) > sysdate
262     and NVL(mil.disable_date, sysdate+1) > sysdate
263     and mil.organization_id = misi.organization_id
264     and mil.subinventory_code = misi.secondary_inventory
265     and misi.inventory_item_id = g_inventory_item_id
266 ';
267   g_put_base_loc_restrict         LONG
268   := '
269  select  mil.subinventory_code subinventory_code
270         ,mil.inventory_location_id locator_id
271         ,mil.organization_id organization_id
272         ,mil.project_id project_id
273         ,mil.task_id task_id
274         ,g_inventory_item_id inventory_item_id
275         ,mil.location_current_units location_current_units
276         ,mil.inventory_item_id locator_inventory_item_id
277         ,mil.empty_flag empty_flag
278         ,mil.mixed_items_flag mixed_items_flag
279         ,mil.LAST_UPDATE_DATE
280         ,mil.LAST_UPDATED_BY
281         ,mil.CREATION_DATE
282         ,mil.CREATED_BY
283         ,mil.LAST_UPDATE_LOGIN
284         ,mil.DESCRIPTION
285         ,mil.DESCRIPTIVE_TEXT
286         ,mil.DISABLE_DATE
287         ,mil.INVENTORY_LOCATION_TYPE
288         ,mil.PICKING_ORDER
289         ,mil.PHYSICAL_LOCATION_CODE
290         ,mil.LOCATION_MAXIMUM_UNITS
291         ,mil.LOCATION_WEIGHT_UOM_CODE
292         ,mil.MAX_WEIGHT
293         ,mil.VOLUME_UOM_CODE
294         ,mil.MAX_CUBIC_AREA
295         ,mil.X_COORDINATE
296         ,mil.Y_COORDINATE
297         ,mil.Z_COORDINATE
298         ,mil.INVENTORY_ACCOUNT_ID
299         ,mil.SEGMENT1
300         ,mil.SEGMENT2
301         ,mil.SEGMENT3
302         ,mil.SEGMENT4
303         ,mil.SEGMENT5
304         ,mil.SEGMENT6
305         ,mil.SEGMENT7
306         ,mil.SEGMENT8
307         ,mil.SEGMENT9
308         ,mil.SEGMENT10
309         ,mil.SEGMENT11
310         ,mil.SEGMENT12
311         ,mil.SEGMENT13
312         ,mil.SEGMENT14
313         ,mil.SEGMENT15
314         ,mil.SEGMENT16
315         ,mil.SEGMENT17
316         ,mil.SEGMENT18
317         ,mil.SEGMENT19
318         ,mil.SEGMENT20
319         ,mil.SUMMARY_FLAG
320         ,mil.ENABLED_FLAG
321         ,mil.START_DATE_ACTIVE
322         ,mil.END_DATE_ACTIVE
323         ,mil.ATTRIBUTE_CATEGORY
324         ,mil.ATTRIBUTE1
325         ,mil.ATTRIBUTE2
326         ,mil.ATTRIBUTE3
327         ,mil.ATTRIBUTE4
328         ,mil.ATTRIBUTE5
329         ,mil.ATTRIBUTE6
330         ,mil.ATTRIBUTE7
331         ,mil.ATTRIBUTE8
332         ,mil.ATTRIBUTE9
333         ,mil.ATTRIBUTE10
334         ,mil.ATTRIBUTE11
335         ,mil.ATTRIBUTE12
336         ,mil.ATTRIBUTE13
337         ,mil.ATTRIBUTE14
338         ,mil.ATTRIBUTE15
339         ,mil.REQUEST_ID
340         ,mil.PROGRAM_APPLICATION_ID
341         ,mil.PROGRAM_ID
342         ,mil.PROGRAM_UPDATE_DATE
343         ,mil.PHYSICAL_LOCATION_ID
344         ,mil.PICK_UOM_CODE
345         ,mil.DIMENSION_UOM_CODE
346         ,mil.LENGTH
347         ,mil.WIDTH
348         ,mil.HEIGHT
349         ,mil.LOCATOR_STATUS
350         ,mil.STATUS_ID
351         ,mil.CURRENT_CUBIC_AREA
352         ,mil.AVAILABLE_CUBIC_AREA
353         ,mil.CURRENT_WEIGHT
354         ,mil.AVAILABLE_WEIGHT
355         ,mil.LOCATION_AVAILABLE_UNITS
356         ,mil.SUGGESTED_CUBIC_AREA
357         ,mil.SUGGESTED_WEIGHT
358         ,mil.LOCATION_SUGGESTED_UNITS
359         ,mil.rowid
360    from MTL_ITEM_LOCATIONS mil
361        ,MTL_SECONDARY_INVENTORIES msei
362        ,MTL_ITEM_SUB_INVENTORIES misi
363        ,MTL_SECONDARY_LOCATORS msl
364   where mil.organization_id = msei.organization_id
365     and mil.subinventory_code = msei.secondary_inventory_name
366     and NVL(msei.disable_date, sysdate+1) > sysdate
367     and NVL(mil.disable_date, sysdate+1) > sysdate
368     and mil.organization_id = misi.organization_id
369     and mil.subinventory_code = misi.secondary_inventory
370     and misi.inventory_item_id = g_inventory_item_id
371     and mil.organization_id = msl.organization_id
372     and mil.inventory_location_id = msl.secondary_locator
373     and msl.inventory_item_Id = g_inventory_item_id
374 ';
375   g_put_base             CONSTANT LONG
376         := '
377  select  x.organization_id
378         ,x.inventory_item_id
379         ,x.subinventory_code
380         ,x.locator_id
381   from (
382   -- subs not restricted and locator controlled
383   select msi.ORGANIZATION_ID    ORGANIZATION_ID
384         ,msi.INVENTORY_ITEM_ID    INVENTORY_ITEM_ID
385         ,msei.SECONDARY_INVENTORY_NAME  SUBINVENTORY_CODE
386         ,mil.INVENTORY_LOCATION_ID  LOCATOR_ID
387         ,mil.PROJECT_ID     PROJECT_ID
388         ,mil.TASK_ID      TASK_ID
389     from MTL_ITEM_LOCATIONS                      mil
390         ,MTL_SECONDARY_INVENTORIES               msei
391         ,MTL_PARAMETERS                          mp
392         ,MTL_SYSTEM_ITEMS                        msi
393    where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 2
394      and nvl(msi.RESTRICT_LOCATORS_CODE,2)       = 2
395      and mp.ORGANIZATION_ID                      = msi.ORGANIZATION_ID
396      and msei.ORGANIZATION_ID                    = msi.ORGANIZATION_ID
397      and nvl(msei.DISABLE_DATE,sysdate+1)        > sysdate
398      and decode(mp.STOCK_LOCATOR_CONTROL_CODE,
399                 4,decode(msei.LOCATOR_TYPE,
400                          5,nvl(msi.LOCATION_CONTROL_CODE,1),
401                          nvl(msei.LOCATOR_TYPE,1)),
402                 mp.STOCK_LOCATOR_CONTROL_CODE)   > 1
403      and mil.INVENTORY_LOCATION_ID               > 0  -- force U1 to be used
404      and mil.ORGANIZATION_ID                     = msei.ORGANIZATION_ID
405      and mil.SUBINVENTORY_CODE                   = msei.SECONDARY_INVENTORY_NAME
406      and nvl(mil.DISABLE_DATE,sysdate+1)         > sysdate
407   union all
408   -- subs restricted and locator controlled
409   select msi.ORGANIZATION_ID
410         ,msi.INVENTORY_ITEM_ID
411         ,misi.SECONDARY_INVENTORY
412         ,mil.INVENTORY_LOCATION_ID
413         ,mil.PROJECT_ID
414         ,mil.TASK_ID
415     from MTL_ITEM_LOCATIONS                      mil
416         ,MTL_SECONDARY_INVENTORIES               msei
417         ,MTL_ITEM_SUB_INVENTORIES                misi
418         ,MTL_PARAMETERS                          mp
419         ,MTL_SYSTEM_ITEMS                        msi
420    where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 1
421      and nvl(msi.RESTRICT_LOCATORS_CODE,2)       = 2
422      and mp.ORGANIZATION_ID                      = msi.ORGANIZATION_ID
423      and misi.ORGANIZATION_ID                    = msi.ORGANIZATION_ID
424      and misi.INVENTORY_ITEM_ID                  = msi.INVENTORY_ITEM_ID
425      and msei.ORGANIZATION_ID                    = misi.ORGANIZATION_ID
426      and msei.SECONDARY_INVENTORY_NAME           = misi.SECONDARY_INVENTORY
427      and nvl(msei.DISABLE_DATE,sysdate+1)        > sysdate
428      and decode(mp.STOCK_LOCATOR_CONTROL_CODE,
429                 4,decode(msei.LOCATOR_TYPE,
430                          5,nvl(msi.LOCATION_CONTROL_CODE,1),
431                          nvl(msei.LOCATOR_TYPE,1)),
432                 mp.STOCK_LOCATOR_CONTROL_CODE)   > 1
433      and mil.INVENTORY_LOCATION_ID               > 0  -- force U1 to be used
434      and mil.ORGANIZATION_ID                     = misi.ORGANIZATION_ID
435      and mil.SUBINVENTORY_CODE                   = misi.SECONDARY_INVENTORY
436      and nvl(mil.DISABLE_DATE,sysdate+1)         > sysdate
437   union all
438   -- locators restricted
439   select msi.ORGANIZATION_ID
440         ,msi.INVENTORY_ITEM_ID
441         ,misi.SECONDARY_INVENTORY
442         ,msl.SECONDARY_LOCATOR
443         ,mil.PROJECT_ID
444         ,mil.TASK_ID
445     from MTL_ITEM_LOCATIONS                      mil
446         ,MTL_SECONDARY_LOCATORS                  msl
447         ,MTL_SECONDARY_INVENTORIES               msei
448         ,MTL_ITEM_SUB_INVENTORIES                misi
449         ,MTL_PARAMETERS                          mp
450         ,MTL_SYSTEM_ITEMS                        msi
451    where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 1
452      and nvl(msi.RESTRICT_LOCATORS_CODE,2)       = 1
453      and mp.ORGANIZATION_ID                      = msi.ORGANIZATION_ID
454      and misi.ORGANIZATION_ID                    = msi.ORGANIZATION_ID
455      and misi.INVENTORY_ITEM_ID                  = msi.INVENTORY_ITEM_ID
456      and msei.ORGANIZATION_ID                    = misi.ORGANIZATION_ID
457      and msei.SECONDARY_INVENTORY_NAME           = misi.SECONDARY_INVENTORY
458      and nvl(msei.DISABLE_DATE,sysdate+1)        > sysdate
459      and msl.ORGANIZATION_ID                     = misi.ORGANIZATION_ID
460      and msl.INVENTORY_ITEM_ID                   = misi.INVENTORY_ITEM_ID
461      and msl.SUBINVENTORY_CODE                   = misi.SECONDARY_INVENTORY
462      and mil.ORGANIZATION_ID                     = msl.ORGANIZATION_ID
463      and mil.INVENTORY_LOCATION_ID               = msl.SECONDARY_LOCATOR
464      and nvl(mil.DISABLE_DATE,sysdate+1)         > sysdate
465   ) x
466   group by x.organization_id
467          , x.inventory_item_id
468          , x.subinventory_code
469          , x.locator_id
470   ';
471   -- /*LPN Status Project*/
472   g_pick_base_serial_detail              LONG
473   := '
474    select  msn.current_organization_id organization_id
475     ,msn.inventory_item_id
476     ,msn.revision
477     ,msn.lot_number
478     ,lot.expiration_date lot_expiration_date
479     ,msn.current_subinventory_code subinventory_code
480     ,msn.current_locator_id locator_id
481     ,msn.cost_group_id
482     ,msn.status_id   --added status_id
483     ,msn.serial_number
484     ,msn.initialization_date date_received
485     ,1 primary_quantity
486     ,null secondary_quantity                            -- new
487     ,lot.grade_code grade_code                          -- new
488     ,sub.reservable_type
489     ,nvl(loc.reservable_type,1)  locreservable          -- Bug 6719290
490     ,nvl(lot.reservable_type,1)  lotreservable          -- Bug 6719290
491     ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
492     ,WMS_Rule_PVT.GetConversionRate(
493          nvl(loc.pick_uom_code, sub.pick_uom_code)
494         ,msn.current_organization_id
495         ,msn.inventory_item_id) conversion_rate
496     ,msn.lpn_id lpn_id
497     ,loc.project_id project_id
498     ,loc.task_id task_id
499           ,NULL locator_inventory_item_id
500           ,NULL empty_flag
501           ,NULL location_current_units
502    from  mtl_serial_numbers msn
503     ,mtl_secondary_inventories sub
504     ,mtl_item_locations loc
505     ,mtl_lot_numbers lot
506    where msn.current_status = 3
507       and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
508       decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
509       and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
510       --and (g_detail_serial IN ( 1,2)
511         and ( g_detail_any_serial = 2   or   (g_detail_any_serial = 1
512             and g_from_serial_number <= msn.serial_number
513             and lengthb(g_from_serial_number) = lengthb(msn.serial_number)
514             and g_to_serial_number >=  msn.serial_number
515             and lengthb(g_to_serial_number) = lengthb(msn.serial_number))
516              or ( g_from_serial_number is null or g_to_serial_number is null)
517           )
518       and sub.organization_id = msn.current_organization_id
519       and sub.secondary_inventory_name = msn.current_subinventory_code
520       and loc.organization_id (+)= msn.current_organization_id
521       and loc.inventory_location_id (+)= msn.current_locator_id
522       and lot.organization_id (+)= msn.current_organization_id
523       and lot.inventory_Item_id (+)= msn.inventory_item_id
524       and lot.lot_number (+)= msn.lot_number
525      ';
526 
527  /*LPN Status Project*/
528   g_pick_base_serial              LONG
529         := '
530          select  msn.current_organization_id organization_id
531           ,msn.inventory_item_id
532           ,msn.revision
533           ,msn.lot_number
534           ,lot.expiration_date lot_expiration_date
535           ,msn.current_subinventory_code subinventory_code
536           ,msn.current_locator_id locator_id
537           ,msn.cost_group_id
538 	   ,msn.status_id   --added status_id
539           ,msn.serial_number
540           ,msn.initialization_date date_received
541           ,1 primary_quantity
542           ,null secondary_quantity                            -- new
543           ,lot.grade_code grade_code                          -- new
544           ,sub.reservable_type
545           ,nvl(loc.reservable_type,1)  locreservable          -- Bug 6719290
546           ,nvl(lot.reservable_type,1)  lotreservable          -- Bug 6719290
547           ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
548           ,WMS_Rule_PVT.GetConversionRate(
549                nvl(loc.pick_uom_code, sub.pick_uom_code)
550               ,msn.current_organization_id
551               ,msn.inventory_item_id) conversion_rate
552           ,msn.lpn_id lpn_id
553           ,loc.project_id project_id
554           ,loc.task_id task_id
555                 ,NULL locator_inventory_item_id
556                 ,NULL empty_flag
557                 ,NULL location_current_units
558            from  mtl_serial_numbers msn
559           ,mtl_secondary_inventories sub
560           ,mtl_item_locations loc
561           ,mtl_lot_numbers lot
562           where msn.current_status = 3
563             and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
564             decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
565             and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
566             and (g_detail_serial = 4
567                 OR(g_detail_any_serial = 1
568              OR (g_from_serial_number <= msn.serial_number
569                 AND lengthb(g_from_serial_number) = lengthb(msn.serial_number)
570                 AND g_to_serial_number >=  msn.serial_number
571                       AND lengthb(g_to_serial_number) = lengthb(msn.serial_number)
572                 )))
573             and sub.organization_id = msn.current_organization_id
574             and sub.secondary_inventory_name = msn.current_subinventory_code
575             and loc.organization_id (+)= msn.current_organization_id
576             and loc.inventory_location_id (+)= msn.current_locator_id
577             and lot.organization_id (+)= msn.current_organization_id
578             and lot.inventory_Item_id (+)= msn.inventory_item_id
579             and lot.lot_number (+)= msn.lot_number
580              ';
581  -------------------------------------------------
582 /*LPN Status Project*/
583  --- Added the following query to validate the serial status inside the rules package
584    g_pick_base_serial_v              LONG
585    := '
586     select  msn.current_organization_id organization_id
587      ,msn.inventory_item_id
588      ,msn.revision
589      ,msn.lot_number
590      ,lot.expiration_date lot_expiration_date
591      ,msn.current_subinventory_code subinventory_code
592      ,msn.current_locator_id locator_id
593      ,msn.cost_group_id
594      ,msn.status_id	--added status_id
595      ,msn.serial_number
596      ,msn.initialization_date date_received
597      ,1 primary_quantity
598      ,null secondary_quantity                            -- new
599      ,lot.grade_code grade_code                          -- new
600      ,sub.reservable_type
601      ,nvl(loc.reservable_type,1)   locreservable                -- Bug 6719290
602      ,nvl(lot.reservable_type,1)   lotreservable                -- Bug 6719290
603      ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
604      ,WMS_Rule_PVT.GetConversionRate(
605           nvl(loc.pick_uom_code, sub.pick_uom_code)
606          ,msn.current_organization_id
607          ,msn.inventory_item_id) conversion_rate
608      ,msn.lpn_id lpn_id
609      ,loc.project_id project_id
610      ,loc.task_id task_id
611            ,NULL locator_inventory_item_id
612            ,NULL empty_flag
613            ,NULL location_current_units
614       from  mtl_serial_numbers msn
615      ,mtl_secondary_inventories sub
616      ,mtl_item_locations loc
617      ,mtl_lot_numbers lot
618     where msn.current_status = 3
619        and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
620        decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
621        and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
622        and (g_detail_serial = 3
623            OR(g_detail_any_serial = 1
624         OR (g_from_serial_number <= msn.serial_number
625            AND lengthb(g_from_serial_number) = lengthb(msn.serial_number)
626            AND g_to_serial_number >=  msn.serial_number
627                  AND lengthb(g_to_serial_number) = lengthb(msn.serial_number)
628            )))
629        and sub.organization_id = msn.current_organization_id
630        and sub.secondary_inventory_name = msn.current_subinventory_code
631        and loc.organization_id (+)= msn.current_organization_id
632        and loc.inventory_location_id (+)= msn.current_locator_id
633        and lot.organization_id (+)= msn.current_organization_id
634        and lot.inventory_Item_id (+)= msn.inventory_item_id
635        and lot.lot_number (+)= msn.lot_number
636        and inv_detail_util_pvt.is_serial_trx_allowed(
637                                         g_transaction_type_id
638                                         ,msn.current_organization_id
639                                         ,msn.inventory_item_id
640                                         ,msn.status_id) = ''Y'' ';
641  /*LPN Status Project*/
642  -- Bug #3697741 modified the base query to get the project_id and task_id from mtl_inventory_locations
643   g_pick_base_lpn_only   CONSTANT LONG
644         := '
645    select  x.organization_id
646           ,x.inventory_item_id
647           ,x.revision
648           ,x.lot_number
649           ,lot.expiration_date lot_expiration_date
650           ,x.subinventory_code
651           ,sub.reservable_type
652 	  ,nvl(x.reservable_type,1) locreservable             -- Bug 6719290
653 	  ,nvl(lot.reservable_type,1) lotreservable           -- Bug 6719290
654           ,x.locator_id
655           ,x.cost_group_id
656 	  ,x.status_id		--added status_id
657           ,x.date_received date_received
658           ,x.primary_quantity primary_quantity
659           ,x.secondary_quantity       secondary_quantity            -- new
660           ,lot.grade_code             grade_code                    -- new
661           ,x.lpn_id lpn_id
662           ,x.project_id project_id
663           ,x.task_id task_id
664      from
665           (SELECT
666              moq.organization_id
667             ,moq.inventory_item_id
668             ,moq.revision
669             ,moq.lot_number
670             ,moq.subinventory_code
671             ,moq.locator_id
672             ,moq.cost_group_id
673 	    ,moq.status_id		--added status_id
674 	    ,mils.reservable_type                                  -- Bug 6719290
675             ,min(NVL(moq.orig_date_received,
676                  moq.date_received)) date_received
677             ,sum(moq.primary_transaction_quantity) primary_quantity
678             ,sum(moq.secondary_transaction_quantity) secondary_quantity   -- new
679             ,moq.lpn_id lpn_id
680             ,mils.project_id project_id
681             ,mils.task_id task_id
682           FROM
683               mtl_onhand_quantities_detail  moq
684             , mtl_item_locations            mils
685           WHERE
686                moq.organization_id = g_organization_id
687            AND moq.inventory_item_id = g_inventory_item_id
688            AND moq.organization_id = mils.organization_id
689            AND moq.subinventory_code = mils.subinventory_code
690            AND moq.locator_id = mils.inventory_location_id
691            AND moq.lpn_id IS NOT NULL
692            AND NOT EXISTS(
693                 select lpn_id
694                 from wms_license_plate_numbers wlpn1
695                 where wlpn1.parent_lpn_id = moq.lpn_id)
696            AND
697                1 = (select count(distinct(moq1.inventory_item_id))
698                from mtl_onhand_quantities_detail moq1
699                where   moq1.organization_id = moq.organization_id
700                     and moq1.subinventory_code = moq.subinventory_code
701                     and moq1.locator_id = moq.locator_id
702                     and moq1.lpn_id = moq.lpn_id)
703            GROUP BY
704                moq.organization_id, moq.inventory_item_id
705               ,moq.revision, moq.lot_number
706               ,moq.subinventory_code, moq.locator_id   --added status_id
707               ,moq.cost_group_id,moq.status_id,mils.reservable_type,moq.lpn_id       -- Bug 6719290
708               ,mils.project_id, mils.task_id
709           ) x
710           ,mtl_secondary_inventories sub
711           ,mtl_lot_numbers lot
712     where x.primary_quantity > 0
713       and x.organization_id = sub.organization_id
714       and x.subinventory_code = sub.secondary_inventory_name
715       and x.organization_id = lot.organization_id (+)
716       and x.inventory_item_id = lot.inventory_item_id (+)
717       and x.lot_number = lot.lot_number (+)
718 ';
719  /*LPN Status Project*/
720 -- Bug #3697741 modified the base query to get the project_id and task_id from mtl_inventory_locations
721 -- LG convergence, for this bug, an item is not locator controlled may not have
722 -- any records in mils. so the join will fail. put decode and outter join
723 -- need to talk to grao about this.
724   g_pick_base_lpn_loose  CONSTANT LONG
725         := '
726    select  x.organization_id
727           ,x.inventory_item_id
728           ,x.revision
729           ,x.lot_number
730           ,lot.expiration_date lot_expiration_date
731           ,x.subinventory_code
732           ,sub.reservable_type
733 	  ,nvl(x.reservable_type,1)   locreservable                          -- Bug 6719290
734 	  ,nvl(lot.reservable_type,1) lotreservable                          -- Bug 6719290
735           ,x.locator_id
736           ,x.cost_group_id
737 	  ,x.status_id		--added status_id
738           ,x.date_received date_received
739           ,x.primary_quantity primary_quantity
740           ,x.secondary_quantity       secondary_quantity            -- new
741           ,lot.grade_code             grade_code                    -- new
742           ,x.lpn_id lpn_id
743           ,x.project_id project_id
744           ,x.task_id task_id
745      from
746           (SELECT
747              moq.organization_id
748             ,moq.inventory_item_id
749             ,moq.revision
750             ,moq.lot_number
751             ,moq.subinventory_code
752             ,moq.locator_id
753             ,moq.cost_group_id
754 	    ,moq.status_id		--added status_id
755 	    ,mils.reservable_type                                  -- Bug 6719290
756             ,min(NVL(moq.orig_date_received,
757                  moq.date_received)) date_received
758             ,sum(moq.primary_transaction_quantity) primary_quantity
759             ,sum(moq.secondary_transaction_quantity) secondary_quantity   -- new
760             ,moq.lpn_id lpn_id
761             ,decode(mils.project_id, mils.project_id, moq.project_id) project_id
762             ,decode(mils.task_id, mils.task_id, moq.task_id) task_id
763           FROM
764             mtl_onhand_quantities_detail moq,mtl_item_locations mils
765           WHERE
766                moq.organization_id = g_organization_id
767            AND moq.inventory_item_id = g_inventory_item_id
768            AND moq.organization_id = mils.organization_id (+)
769            AND moq.subinventory_code = mils.subinventory_code (+)
770            AND moq.locator_id = mils.inventory_location_id (+)
771           GROUP BY
772                moq.organization_id, moq.inventory_item_id
773               ,moq.revision, moq.lot_number
774               ,moq.subinventory_code, moq.locator_id		--added status_id
775               ,moq.cost_group_id,moq.status_id, mils.reservable_type, moq.lpn_id         -- Bug 6719290
776               ,decode(mils.project_id, mils.project_id, moq.project_id)
777               ,decode(mils.task_id, mils.task_id, moq.task_id)
778           ) x
779           ,mtl_secondary_inventories sub
780           ,mtl_lot_numbers lot
781     where x.primary_quantity > 0
782       and x.organization_id = sub.organization_id
783       and x.subinventory_code = sub.secondary_inventory_name
784       and x.organization_id = lot.organization_id (+)
785       and x.inventory_item_id = lot.inventory_item_id (+)
786       and x.lot_number = lot.lot_number (+)
787 ';
788   g_pick_base                     LONG;
789   --
790   g_base_table_alias              wms_db_objects.table_alias%TYPE;
791   g_input_table_alias             wms_db_objects.table_alias%TYPE;
792   g_base_select                   LONG;
793   g_base_group_by                 LONG;
794   g_rule_select                   LONG;
795   g_rule_select_serial            LONG;
796   g_rule_group_by                 LONG;
797   g_base_from                     LONG;
798   g_base_from_serial              LONG; --used if item is lot controlled
799   g_base_from_serial_v            LONG; --used for serial controlled item / Validation required
800   g_base_from_serial_detail       LONG; -- New
801   g_rule_from                     LONG;
802   g_input_where                   LONG;
803   g_rule_where                    LONG;
804   g_rule_order                    LONG;
805   g_stmt                          LONG;
806   g_stmt_task_type                LONG; --used for task type assignment  TTA
807   g_stmt_serial                   LONG;
808   g_stmt_serial_validate          LONG;
809   g_stmt_serial_detail            LONG;
810   g_stmt_serial_detail_new        LONG;
811   g_build_package_row             NUMBER;
812   g_build_package_tbl             DBMS_SQL.varchar2s;
813   g_default_pick_task_type_id     NUMBER;
814   g_default_putaway_task_type_id  NUMBER;
815   g_default_cc_task_type_id       NUMBER;
816   g_default_repl_task_type_id     NUMBER;
817   g_default_moxfer_task_type_id   NUMBER;
818   g_default_moissue_task_type_id  NUMBER;
819   g_default_operation_plan_id     NUMBER;
820   g_current_organization_id       NUMBER;
821   --
822   g_line_feed            CONSTANT VARCHAR2(1)                                             := '
823 ';
824   --global values for allocation mode
825   g_alloc_lpn_only                NUMBER                                                  := 1;
826   g_alloc_lpn_loose               NUMBER                                                  := 2;
827   g_alloc_no_lpn                  NUMBER                                                  := 3;
828   g_alloc_pick_uom                NUMBER                                                  := 4;
829 
830   -- Added for R12.1 Replenishment Project - 6681109
831   g_alloc_strict_pick_uom         NUMBER                                                  := 5;
832 
833   --Used for storing both the current record being dealt with and a
834   -- a variety of stored records.  This represents a single row returned
835   -- by the FetchCursor function, which gets the row from the Rule.
836   -- This records are stored in an array, but are accessed like linked
837   -- lists.  Each record contains the index of the next record
838   -- that should be looked at (next_rec).
839   TYPE t_location_rec IS RECORD(
840     revision                      wms_transactions_temp.revision%TYPE
841   , lot_number                    wms_transactions_temp.lot_number%TYPE
842   , lot_expiration_date           wms_transactions_temp.lot_expiration_date%TYPE
843   , subinventory_code             wms_transactions_temp.from_subinventory_code%TYPE
844   , locator_id                    wms_transactions_temp.from_locator_id%TYPE
845   , cost_group_id                 wms_transactions_temp.from_cost_group_id%TYPE
846   , uom_code                      VARCHAR2(3)
847   , lpn_id                        NUMBER
848   , serial_number                 VARCHAR2(30)
849   , quantity                      wms_transactions_temp.primary_quantity%TYPE
850   , secondary_quantity            wms_transactions_temp.secondary_quantity%TYPE
851   , grade_code                    wms_transactions_temp.grade_code%TYPE
852   , secondary_uom_code            VARCHAR2(3)
853   , consist_string                VARCHAR2(1000)
854   , order_by_string               VARCHAR2(1000)
855   , next_rec                      NUMBER);
856 
857   TYPE t_location_table IS TABLE OF t_location_rec
858     INDEX BY BINARY_INTEGER;
859 
860   --these arrays store location recs in sequential order. However, when
861   -- the records are read from the array, they are read in the order
862   -- dictated by the pointer in the location_rec (next_rec)
863   g_locs                          t_location_table; -- array of all locators read from cursor
864   g_locs_index                    NUMBER                                                  := 0;
865 
866   -- This record is used to store information about a consistency group.
867   -- A consistency group consists of all records which share the same
868   -- consist_string.  The consist_string is the concatenation of each
869   -- record's values for the columns which are defined as a rule's
870   -- consistencies.  For example, if a rule's consistency restrictions
871   -- are lot number and locator_id, then the consist string would
872   -- lot_number||locator_id.  Each record could have different
873   -- values for the consist string, like LOTA123, or LOTB1000.
874   -- For creating pick suggestions for rules that have consistency
875   -- restrictions, we need to keep track of the quantity available
876   -- for each consistency group.
877   -- 2/26/02
878   -- Group record altered to support LPNs
879   TYPE t_group_rec IS RECORD(
880     consist_string                VARCHAR2(1000)
881   , lpn_id                        NUMBER
882   , quantity                      NUMBER
883   , total_quantity                NUMBER
884   , secondary_quantity            NUMBER                               -- new
885   , secondary_total_quantity      NUMBER                               -- new
886   , grade_code                    VARCHAR2(150)                        -- new
887   , order_by_rank                 NUMBER
888   , first_rec                     NUMBER
889   , last_rec                      NUMBER
890   , prev_group                    NUMBER
891   , next_group                    NUMBER
892   , prev_consist_lpn_id           NUMBER
893   , next_consist_lpn_id           NUMBER
894   , parent_consist_group          NUMBER);
895 
896   TYPE t_group_table IS TABLE OF t_group_rec
897     INDEX BY BINARY_INTEGER;
898 
899   g_consists                      t_group_table;
900   g_lpns                          t_group_table;
901   g_first_order_by_rank           NUMBER                                                  := NULL;
902   g_first_consist_group           NUMBER                                                  := 0;
903   g_last_consist_group            NUMBER;
904   g_first_lpn_group               NUMBER;
905   g_last_lpn_group                NUMBER;
906   g_trace_recs                    wms_search_order_globals_pvt.pre_suggestions_record_tbl;
907 
908   PROCEDURE FetchCursorRows(
909     x_return_status       OUT NOCOPY    VARCHAR2
910   , x_msg_count           OUT NOCOPY    NUMBER
911   , x_msg_data            OUT NOCOPY    VARCHAR2
912   , p_cursor              IN            wms_rule_pvt.cv_pick_type
913   , p_rule_id             IN            NUMBER
914   );
915 
916   -- =============================================
917   -- Procedure to log message for Label Printing
918   -- =============================================
919   PROCEDURE TRACE(p_message IN VARCHAR2) IS
920   BEGIN
921     inv_log_util.TRACE(p_message, 'RULE_ENGINE', 4);
922   END TRACE;
923 
924   --Procedures for logging messages
925   PROCEDURE log_event(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
926     l_module VARCHAR2(255);
927   BEGIN
928     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
929     inv_log_util.trace(p_message, l_module, 9);
930    /* fnd_log.STRING(log_level => fnd_log.level_event, module => l_module, message => p_message);
931     inv_log_util.trace(p_message, l_module, 9);
932     gmi_reservation_util.println(p_message); */
933   END log_event;
934 
935   PROCEDURE log_error(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
936     l_module VARCHAR2(255);
937   BEGIN
938     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
939     inv_log_util.trace(p_message, l_module, 9); /*
940     fnd_log.STRING(log_level => fnd_log.level_error, module => l_module, message => p_message);
941     inv_log_util.trace(p_message, l_module, 9);
942     gmi_reservation_util.println(p_message); */
943   END log_error;
944 
945   PROCEDURE log_error_msg(p_api_name VARCHAR2, p_label VARCHAR2) IS
946     l_module VARCHAR2(255);
947   BEGIN
948     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
949     inv_log_util.trace('err:', l_module, 9); /*
950     fnd_log.message(log_level => fnd_log.level_error, module => l_module, pop_message => FALSE);
951     inv_log_util.trace('err:', l_module, 9);
952     gmi_reservation_util.println(p_label); */
953   END log_error_msg;
954 
955   PROCEDURE log_procedure(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
956     l_module VARCHAR2(255);
957   BEGIN
958     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
959     inv_log_util.trace(p_message, l_module, 9);/*
960     fnd_log.STRING(log_level => fnd_log.level_procedure, module => l_module, message => p_message);
961     inv_log_util.trace(p_message, l_module, 9);
962     gmi_reservation_util.println(p_message); */
963   END log_procedure;
964 
965   PROCEDURE log_statement(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
966     l_module VARCHAR2(255);
967   BEGIN
968     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
969     inv_log_util.trace(p_message, l_module, 9);/*
970     fnd_log.STRING(log_level => fnd_log.level_statement, module => l_module, message => p_message);
971     inv_log_util.trace(p_message, l_module, 9);
972     gmi_reservation_util.println(p_label||' '||p_message);*/
973   END log_statement;
974   ----
975   ---- Function to check if Restriction , Sort-criteria and Consistency was defined for a given picking rule
976   ---- using serial object
977 
978   FUNCTION IsSerialObjectUsed( p_organization_id  NUMBER )
979   RETURN BOOLEAN IS
980   l_serial_object_used          NUMBER ;
981   BEGIN
982     /* Trace( ' Start IsSerialObjectUsed');
983      Trace( ' Start IsSerialObjectUsed p_organization_id '|| to_char(p_organization_id));
984      Trace( ' Start IsSerialObjectUsed g_serial_objects_used ' || to_char( g_serial_objects_used));
985      */
986 
987     l_serial_object_used  := 0 ;
988   IF ( wms_rule_pvt.g_serial_objects_used IS NULL )   THEN
989      --Trace( ' IsSerialObjectUsed -- If condition is true ');
990      SELECT count( DISTINCT p.object_id)
991        INTO l_serial_object_used
992        FROM wms_selection_criteria_txn wsc,
993             wms_strategies_b wsb,
994             wms_strategy_members wsm,
995             wms_rules_b wrb,
996             wms_restrictions r,
997             wms_sort_criteria s,
998             wms_rule_consistencies c,
999             wms_parameters_b p
1000       WHERE wsc.rule_type_code = 2
1001         AND wsc.enabled_flag = 1
1002         AND wsc.return_type_code = 'S'
1003         AND wsc.from_organization_id = p_organization_id
1004         AND wsc.return_type_id = wsb.strategy_id
1005         AND wsb.strategy_id = wsm.strategy_id
1006         AND wsm.rule_id = wrb.rule_id
1007         AND (
1008              ( wrb.rule_id = r.rule_id AND ((r.parameter_id = p.parameter_id ) OR (r.operand_parameter_id = p.parameter_id)))
1009                 OR (wrb.rule_id = s.rule_id AND s.parameter_id = p.parameter_id)                OR (wrb.rule_id = c.rule_id AND c.parameter_id = p.parameter_id)              )
1010         AND wrb.organization_id IN (p_organization_id, -1)
1011         AND p.object_id = 26; --- 26 is Serial object
1012 
1013         wms_rule_pvt.g_serial_objects_used := l_serial_object_used;
1014 
1015         --Trace( ' IsSerialObjectUsed -- l_serial_object_used ' || wms_rule_pvt.g_serial_object_used);
1016   ELSE
1017     l_serial_object_used  := wms_rule_pvt.g_serial_objects_used;
1018   END IF;
1019 
1020   If l_serial_object_used  >= 1  THEN
1021      RETURN TRUE;
1022   ELSE
1023      RETURN FALSE;
1024   END IF;
1025 
1026   EXCEPTION WHEN OTHERS THEN
1027      RETURN FALSE;
1028   END IsSerialObjectUsed;
1029 
1030   --
1031   -- Name        : FreeGlobals
1032   -- Function    : Initializes global variables.
1033   -- Notes       : privat procedure for internal use only
1034   --
1035   PROCEDURE freeglobals IS
1036   BEGIN
1037     g_base_select         := NULL;
1038     g_rule_select         := NULL;
1039     g_rule_select_serial  := NULL;
1040     g_base_from           := NULL;
1041     g_base_from_serial    := NULL;
1042     g_base_from_serial_v  := NULL;
1043     g_base_from_serial_detail := NULL;
1044     g_rule_from           := NULL;
1045     g_input_where         := NULL;
1046     g_rule_where          := NULL;
1047     g_rule_order          := NULL;
1048     g_base_group_by       := NULL;
1049     g_rule_group_by       := NULL;
1050     g_stmt                := NULL;
1051     g_stmt_serial         := NULL;
1052     g_stmt_serial_detail  := NULL;
1053     g_stmt_serial_detail_new  := NULL;
1054     g_pick_base           := NULL;
1055     -- clean up the serial number detailing table
1056     -- Commenting out for Bug 5251221
1057     --inv_detail_util_pvt.init_output_serial_rows;
1058     -- clean up the bind variables table
1059     inv_sql_binding_pvt.initbindtables;
1060   END freeglobals;
1061 
1062   ----
1063   ----
1064 
1065   --------------
1066   --- Build Rules List
1067   ---  Generate all static rule list package  for diffrent rule types.
1068   ---- Total of  15 packages will be generated
1069   ---- WMS_RULE_PICK_PKG, WMS_RULE_PICK_PKG1, WMS_RULE_PICK_PKG2
1070   PROCEDURE buildrulespkg(errbuf OUT NOCOPY VARCHAR2, retcode OUT NOCOPY NUMBER, x_return_status OUT NOCOPY VARCHAR2) IS
1071     l_return_status VARCHAR2(1);
1072     l_msg_count     NUMBER;
1073     l_msg_data      VARCHAR2(240);
1074     l_rule_id       NUMBER;
1075     l_error_string  VARCHAR2(240);
1076   BEGIN
1077 
1078     --
1079     -- kkoothan  Bug Fix:2561401
1080     -- Initialized the value of X_RETURN_STATUS to Success
1081     -- at the start of the procedure and set its value accordingly
1082     -- when the procedure returns Failure/Error.
1083     --
1084     X_RETURN_STATUS := fnd_api.g_ret_sts_success;
1085 
1086     --- Updates  the table wms_rule_list_package ,
1087     --- for all rule type package counter with value 3
1088     --- so that all three "rules list packages" for all type of
1089     ----Rules will be generated.
1090 
1091     UPDATE wms_rule_list_package
1092        SET package_name_count = 3;
1093 
1094     wms_rule_gen_pkgs.generateruleexecpkgs(
1095       p_api_version                => 1.0
1096     , p_init_msg_list              => fnd_api.g_true
1097     , p_validation_level           => fnd_api.g_valid_level_full
1098     , x_return_status              => l_return_status
1099     , x_msg_count                  => l_msg_count
1100     , x_msg_data                   => l_msg_data
1101     , p_pick_code                  => 2
1102     , p_put_code                   => 1
1103     , p_task_code                  => 3
1104     , p_label_code                 => 4
1105     , p_cg_code                    => 5
1106     , p_op_code                    => 7
1107     , p_pkg_type                   => 'B'
1108     );
1109 
1110     IF (l_return_status = fnd_api.g_ret_sts_success) THEN
1111       FND_FILE.put_line(FND_FILE.LOG, 'Success from GenerateRuleExecPkgs');
1112     ELSE
1113       FND_FILE.put_line(FND_FILE.LOG, 'Error from GenerateRuleExecPkgs:');
1114       X_RETURN_STATUS :=  fnd_api.g_ret_sts_error; -- Expected Error
1115       retcode  := 1;
1116 
1117       FOR i IN 1 .. l_msg_count LOOP
1118         --fnd_file.put_line(fnd_file.LOG, 'Error:');
1119         l_error_string  := fnd_message.get;
1120         --fnd_file.put_line(fnd_file.LOG, l_error_string);
1121         errbuf          := errbuf || ' Error: GenerateRuleExecPkgs ' || l_error_string;
1122       END LOOP;
1123     END IF;
1124   EXCEPTION
1125     WHEN OTHERS THEN
1126       X_RETURN_STATUS := fnd_api.g_ret_sts_unexp_error; -- Unexpecetd Error
1127       retcode  := 2;
1128       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1129         fnd_msg_pub.add_exc_msg(g_pkg_name, 'BuildRulePkg');
1130       END IF;
1131 
1132       fnd_msg_pub.count_and_get(p_count => l_msg_count, p_data => l_msg_data);
1133       --fnd_file.put_line(fnd_file.LOG, 'Exception');
1134       --fnd_file.put_line(fnd_file.LOG, l_msg_data);
1135       errbuf   := errbuf || 'Error in BuildRulesPkg:' || l_msg_data;
1136   END buildrulespkg;
1137 
1138   --
1139   -- Name        : GetConversionRate
1140   -- Function    : Finds the conversion rate between the given UOM and
1141   --    the base UOM of the class which contains the
1142   --    item's primary UOM. Support interclass and intraclass
1143   --    conversions.
1144   -- Notes       : private procedure for internal use only;
1145   --               Similar to inv_convert.inv_um_converstion, but no
1146   --     Used to order locations returned from rule package
1147   FUNCTION getconversionrate(p_uom_code VARCHAR2, p_organization_id NUMBER, p_inventory_item_id NUMBER)
1148     RETURN NUMBER IS
1149     l_conversion_rate NUMBER;
1150     l_from_class      VARCHAR2(10);
1151     l_to_class        VARCHAR2(10);
1152     l_class_rate      NUMBER;
1153 
1154     --get conversion rate between given uom and that uom class's
1155     -- base uom
1156     CURSOR c_conversion_rate IS
1157       SELECT   conversion_rate
1158              , uom_class
1159           FROM mtl_uom_conversions
1160          WHERE uom_code = p_uom_code
1161            AND inventory_item_id IN (p_inventory_item_id, 0)
1162            AND NVL(disable_date, TRUNC(SYSDATE) + 1) > TRUNC(SYSDATE)
1163       ORDER BY inventory_item_id DESC;
1164 
1165     -- find the uom class for the item's primary uom
1166     CURSOR c_primary_uom_class IS
1167       SELECT uom_class
1168         FROM mtl_units_of_measure muom, mtl_system_items msi
1169        WHERE msi.organization_id = p_organization_id
1170          AND msi.inventory_item_id = p_inventory_item_id
1171          AND muom.uom_code = msi.primary_uom_code;
1172 
1173     -- find the conversion rate between the base uoms of two classes
1174     CURSOR c_class_conversion_rate IS
1175       SELECT   conversion_rate
1176           FROM mtl_uom_class_conversions
1177          WHERE from_uom_class = l_from_class
1178            AND to_uom_class = l_to_class
1179            AND inventory_item_id IN (p_inventory_item_id, 0)
1180            AND NVL(disable_date, TRUNC(SYSDATE) + 1) > TRUNC(SYSDATE)
1181       ORDER BY inventory_item_id DESC;
1182   BEGIN
1183     IF (p_uom_code IS NULL) THEN
1184       RETURN 0;
1185     END IF;
1186 
1187     IF (nvl(g_gcr_organization_id,-1) = p_organization_id
1188       AND nvl(g_gcr_inventory_item_id,-1) = p_inventory_item_id
1189       AND nvl(g_gcr_uom_code,'-1') = p_uom_code) THEN
1190       l_conversion_rate := g_gcr_conversion_rate;
1191     ELSE
1192       OPEN c_conversion_rate;
1193       --Cursor returns 0, 1, or 2 records
1194       -- Because the results are ordered by item_id desc, the results
1195       -- are also ordered from specific (item_Id > 0) to default (item_id = 0);
1196       --So, we only have to fetch one record
1197       FETCH c_conversion_rate INTO l_conversion_rate, l_to_class;
1198 
1199       IF (c_conversion_rate%NOTFOUND) THEN
1200         --don't raise error. Instead, just return 1
1201         l_conversion_rate  := 0;
1202       END IF;
1203 
1204       CLOSE c_conversion_rate;
1205 
1206       IF l_conversion_rate <> 0 THEN
1207         OPEN c_primary_uom_class;
1208         FETCH c_primary_uom_class INTO l_from_class;
1209 
1210         IF (c_primary_uom_class%NOTFOUND) THEN
1211           l_from_class       := NULL;
1212           l_conversion_rate  := 0;
1213         END IF;
1214 
1215         CLOSE c_primary_uom_class;
1216 
1217         -- check to see if interclass conversion - if so, get conversion
1218         -- between 2 classes
1219         IF  l_from_class IS NOT NULL
1220             AND l_to_class IS NOT NULL
1221             AND l_from_class <> l_to_class THEN
1222           OPEN c_class_conversion_rate;
1223           FETCH c_class_conversion_rate INTO l_class_rate;
1224 
1225           IF c_class_conversion_rate%NOTFOUND THEN
1226             l_class_rate  := 0;
1227           END IF;
1228 
1229           l_conversion_rate  := l_conversion_rate * l_class_rate;
1230         END IF;
1231       END IF;
1232       g_gcr_organization_id := p_organization_id;
1233       g_gcr_inventory_item_id := p_inventory_item_id;
1234       g_gcr_uom_code := p_uom_code;
1235       g_gcr_conversion_rate := l_conversion_rate;
1236     END IF;
1237 
1238     RETURN l_conversion_rate;
1239   END getconversionrate;
1240 
1241   --
1242   -- Name        : BuildBaseSQL
1243   -- Function    : Builds the base part of a pick or put away rule representing
1244   --               dynamic SQL cursor text.
1245   -- Notes       : privat procedure for internal use only
1246   --
1247   PROCEDURE buildbasesql(
1248     x_return_status      OUT NOCOPY    VARCHAR2
1249   , x_msg_count          OUT NOCOPY    NUMBER
1250   , x_msg_data           OUT NOCOPY    VARCHAR2
1251   , p_type_code          IN            NUMBER
1252   , p_allocation_mode_id IN            NUMBER
1253   ) IS
1254     l_api_name             VARCHAR2(30)                      := 'BuildBaseSQL';
1255     l_return_status        VARCHAR2(1)                       := fnd_api.g_ret_sts_success;
1256     --
1257     -- variables needed for dynamic SQL
1258     l_identifier           VARCHAR2(10);
1259     -- variables for the base and input representing DB objects
1260     l_input_table_name     wms_db_objects.table_name%TYPE;
1261     l_type_dependent_alias wms_db_objects.table_alias%TYPE;
1262 
1263     --
1264     -- cursor for the base and input representing DB objects
1265     CURSOR baseinp IS
1266       SELECT wdo1.table_alias
1267            , wdo2.table_name
1268            , wdo2.table_alias
1269         FROM wms_db_objects wdo1, wms_db_objects wdo2
1270        WHERE wdo1.db_object_id = 1
1271          AND wdo2.db_object_id = 2;
1272   --
1273   BEGIN
1274     --
1275     -- Initialize API return status to success
1276     x_return_status     := fnd_api.g_ret_sts_success;
1277 
1278     --
1279     -- debugging portion
1280     -- can be commented ut for final code
1281     log_procedure(l_api_name, 'start', 'Start BuildBaseSql');
1282     log_statement(l_api_name, 'type_code', 'type_code: ' || p_type_code);
1283     -- end of debugging section
1284     --
1285 
1286 
1287     -- get names and aliases of the base and input representing DB objects
1288     OPEN baseinp;
1289     FETCH baseinp INTO g_base_table_alias, l_input_table_name, g_input_table_alias;
1290 
1291     IF baseinp%NOTFOUND THEN
1292       CLOSE baseinp;
1293       log_statement(l_api_name, 'no_base_input', 'No base input found');
1294       RAISE NO_DATA_FOUND;
1295     END IF;
1296 
1297     CLOSE baseinp;
1298 
1299     --
1300     -- Build 'select' skeleton
1301     IF p_type_code = 1 THEN -- put away:
1302       l_type_dependent_alias  := g_input_table_alias; -- rev and lot from input
1303     ELSIF p_type_code = 2 THEN -- pick:
1304       l_type_dependent_alias  := g_base_table_alias; -- rev and lot from basis
1305     END IF;
1306 
1307     --
1308     --2/21/02 - remove all columns but sub and loc from picking query
1309     IF p_type_code = 2 THEN
1310       g_base_select  :=    l_type_dependent_alias
1311                         || '.REVISION'
1312                         || g_line_feed
1313                         || ','
1314                         || l_type_dependent_alias
1315                         || '.LOT_NUMBER'
1316                         || g_line_feed
1317                         || ','
1318                         || l_type_dependent_alias
1319                         || '.LOT_EXPIRATION_DATE'
1320                         || g_line_feed
1321                         || ','
1322                         || g_base_table_alias
1323                         || '.SUBINVENTORY_CODE'
1324                         || g_line_feed
1325                         || ','
1326                         || g_base_table_alias
1327                         || '.LOCATOR_ID'
1328                         || g_line_feed;
1329     ELSE
1330       g_base_select  := g_base_table_alias
1331                        || '.SUBINVENTORY_CODE'
1332                        || g_line_feed || ','
1333                        || g_base_table_alias
1334                        || '.LOCATOR_ID'
1335                        || g_line_feed;
1336     END IF;
1337 
1338     -- added to suport PJM
1339     IF p_type_code = 1 THEN
1340       g_base_select  := g_base_select
1341                        || ','
1342                        || g_base_table_alias
1343                        || '.PROJECT_ID'
1344                        || g_line_feed;
1345       g_base_select  := g_base_select
1346                        || ','
1347                        || g_base_table_alias
1348                        || '.TASK_ID'
1349                        || g_line_feed;
1350     END IF;
1351 
1352     --added to support Picking by UOM.
1353     --UOM only matters in picking
1354     IF p_type_code = 2 THEN --pick
1355       g_base_select  := g_base_select
1356                        || ','
1357                        || g_base_table_alias
1358                        || '.COST_GROUP_ID'
1359                        || g_line_feed;
1360       g_base_select  := g_base_select
1361                        || ','
1362                        || g_base_table_alias
1363                        || '.UOM_CODE'
1364                        || g_line_feed;
1365 
1366       IF p_allocation_mode_id IN (g_alloc_lpn_only, g_alloc_lpn_loose) THEN
1367         g_base_select  := g_base_select
1368                        || ','
1369                        || g_base_table_alias
1370                        || '.LPN_ID'
1371                        || g_line_feed;
1372       ELSE
1373         g_base_select  := g_base_select
1374                        || ',decode(g_lpn_id, -9999, NULL, g_lpn_id) LPN_ID'
1375                        || g_line_feed;
1376       END IF;
1377     /* 2/21/02 - no longer need these args, since put and pick packages
1378      * are not build differently
1379      * else  --put away
1380      *  --for put, get cost group from wms_transactions_temp,
1381      *  --  not input table (wms_trx_details_tmp_v)
1382      *  g_base_select := g_base_select ||',NULL cost_group_id'
1383      *                                 || g_line_feed;
1384      *  g_base_select := g_base_select ||',NULL uom_code'
1385      *                                 || g_line_feed;
1386      */
1387     END IF;
1388 
1389     --
1390     -- Build type code independent 'from' skeleton
1391     g_base_from                 := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1392     g_base_from_serial          := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1393     g_base_from_serial_v        := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1394     g_base_from_serial_detail   := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1395 
1396     --
1397     -- Add type code dependent part to 'from' skeleton
1398     -- We need to build 9 different putaway cursors using 3 different put
1399     -- bases.  So, here we insert a place holder (:g_put_base) which we will
1400     -- replace in GenerateRulePackage with the appropriate base
1401     IF p_type_code = 1 THEN -- put away
1402       g_base_from  := g_base_from || ',(:g_put_base)' || g_base_table_alias || g_line_feed;
1403     ELSIF p_type_code = 2 THEN -- pick
1404       --need to generate 2 pick bases - one for non-serial controlled,
1405       --and one for serial control, since we won't know whether
1406       -- the inventory item is serial controlled until the stored
1407       -- procedure is run.
1408       IF p_allocation_mode_id = g_alloc_lpn_only THEN
1409         g_pick_base  := g_pick_base_lpn_only;
1410       ELSIF p_allocation_mode_id = g_alloc_lpn_loose THEN
1411         g_pick_base  := g_pick_base_lpn_loose;
1412       ELSE
1413         /**
1414          *Bug 2310403
1415          *Errors allocating for LPN putaway move orders.
1416          *The problem occurs because we should only pick material
1417          *from a certain LPN, but the base returned by build_sql
1418          *does not have an LPN_ID.  So now, we'll use the lpn_loose
1419          *base, and add a group_by statement on the outermost query
1420          *so that we only get one rec per rev/lot/sub/loc when we
1421          *aren't allocating LPNs
1422                *--build non-serial controlled pick base
1423                *log_statement(l_api_name, 'build_sql_no_serial',
1424                *  'Calling inv_detail_util_pvt.build_sql for base');
1425                *inv_detail_util_pvt.build_sql
1426          *( x_return_status       => l_return_status    ,
1427          *  x_sql_statement       => g_pick_base
1428          *  );
1429                *IF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
1430                *  log_statement(l_api_name, 'err_build_sql',
1431                *      'Error in inv_detail_util_pvt.build_sql');
1432                *  RAISE fnd_api.g_exc_unexpected_error;
1433                *ELSIF l_return_status = fnd_api.g_ret_sts_error THEN
1434                *  log_statement(l_api_name, 'unexp_err_build_sql',
1435                *    'Unexp. error in inv_detail_util_pvt.build_sql');
1436                *  RAISE fnd_api.g_exc_error;
1437                *END IF;
1438                *log_statement(l_api_name, 'success_build_sql',
1439                *      'Inv_detail_util_pvt.build_sql successful');
1440 
1441                *-- replace the bind variables used in the base sql
1442                *-- with the global variables in the stored rule procedure
1443                *g_pick_base :=
1444          *   REPLACE(g_pick_base,':organization_id','g_organization_id');
1445                *g_pick_base :=
1446          *   REPLACE(g_pick_base,':inventory_item_id','g_inventory_item_id');
1447          */
1448         g_pick_base  := g_pick_base_lpn_loose;
1449       END IF;
1450 
1451 	 /*LPN Status Project*/
1452       -- The conversion_rate (found using GetConversionRate) is used
1453       --  to order picking locations from largest Pick UOM to smallest.
1454       -- The API call to is_sub_loc_lot_trx_allowed checks the status
1455       --  of the subinventory, locator, and lot to make sure that we can
1456       --  pick from this location
1457       g_pick_base         :=    g_line_feed
1458                  || 'SELECT x.organization_id       organization_id     '
1459                                        || g_line_feed
1460                  || '  ,x.inventory_item_id         inventory_item_id   '
1461                                        || g_line_feed
1462                  || '  ,x.revision                  revision            '
1463                                        || g_line_feed
1464                  || '  ,x.lot_number                lot_number          '
1465                                        || g_line_feed
1466                  || '  ,x.lot_expiration_date       lot_expiration_date '
1467                                        || g_line_feed
1468                  || '  ,x.subinventory_code         subinventory_code   '
1469                  || g_line_feed
1470                  || '  ,x.locator_id                locator_id          '
1471                                        || g_line_feed
1472                  || '  ,x.cost_group_id             cost_group_id       '
1473                                        || g_line_feed
1474 		 || '  ,x.status_id                 status_id       '   --added status_id
1475                               || g_line_feed
1476                  || '  ,NULL                        serial_number       '
1477                                        || g_line_feed
1478                  || '  ,x.lpn_id                    lpn_id              '
1479                                        || g_line_feed
1480                  || '  ,x.project_id                project_id          '
1481                                        || g_line_feed
1482                  || '  ,x.task_id                   task_id             '
1483                                        || g_line_feed
1484                  || '  ,x.date_received             date_received       '
1485                                        || g_line_feed
1486                  || '  ,x.primary_quantity          primary_quantity    '
1487                                        || g_line_feed
1488                  || '  ,x.secondary_quantity          secondary_quantity    '         -- new
1489                                        || g_line_feed                                 -- new
1490                  || '  ,x.grade_code                  grade_code            '         -- new
1491                                        || g_line_feed                                 -- new
1492                  || '  ,x.reservable_type           reservable_type     '
1493                                        || g_line_feed
1494                  || '  ,x.locreservable             locreservable '              -- Bug 6719290 Start
1495                                        || g_line_feed
1496                  || '  ,x.lotreservable             lotreservable '
1497                                        || g_line_feed                            -- Bug 6719290 End
1498                  || '  ,NVL(loc.pick_uom_code,sub.pick_uom_code) uom_code'
1499                                        || g_line_feed
1500                  || '  ,WMS_Rule_PVT.GetConversionRate(                 '
1501                                        || g_line_feed
1502                  || '       NVL(loc.pick_uom_code, sub.pick_uom_code)   '
1503                                        || g_line_feed
1504                  || '       ,x.organization_id            '
1505                                        || g_line_feed
1506                  || '       ,x.inventory_item_id) conversion_rate       '
1507                                        || g_line_feed
1508                  || '  ,NULL locator_inventory_item_id                  '
1509                                        || g_line_feed
1510                  || '  ,NULL empty_flag                                 '
1511                                        || g_line_feed
1512                  || '  ,NULL location_current_units                     '
1513                                        || g_line_feed
1514                  || 'FROM ('
1515                  || g_pick_base
1516                   --extra line feed?                  || g_line_feed
1517                  || '     ) x                                           '
1518                                        || g_line_feed
1519                  || '    ,mtl_secondary_inventories sub                 '
1520                                        || g_line_feed
1521                  || '    ,mtl_item_locations loc                        '
1522                                        || g_line_feed
1523                  || 'WHERE x.organization_id = loc.organization_id (+)  '
1524                                        || g_line_feed
1525                  || '   AND x.locator_id = loc.inventory_location_id (+)'
1526                                        || g_line_feed
1527                  || '   AND sub.organization_id = x.organization_id     '
1528                                        || g_line_feed
1529                  || '   AND sub.secondary_inventory_name = x.subinventory_code '
1530                                        || g_line_feed; /*
1531                  || '   AND inv_detail_util_pvt.is_sub_loc_lot_trx_allowed('
1532                                        || g_line_feed
1533                  || '       g_transaction_type_id,          '
1534                                        || g_line_feed
1535                  || '       x.organization_id,            '
1536                                        || g_line_feed
1537                  || '       x.inventory_item_id,            '
1538                                        || g_line_feed
1539                  || '       x.subinventory_code,            '
1540                                        || g_line_feed
1541                  || '       x.locator_id,             '
1542                                       || g_line_feed
1543                 || '       x.lot_number)=''Y''                   '
1544                                       || g_line_feed;    */
1545       --
1546 
1547       -- finally apply the corrections to the basis SQL
1548       g_base_from         := g_base_from || ',(' || g_pick_base || ') '
1549                           || g_base_table_alias || g_line_feed;
1550       --Construct the base for the serial cursor
1551       g_base_from_serial  := g_base_from_serial || ',(' || g_pick_base_serial;
1552       g_base_from_serial_v  := g_base_from_serial_v || ',(' || g_pick_base_serial_v;
1553       g_base_from_serial_detail  := g_base_from_serial_detail || ',(' || g_pick_base_serial_detail;
1554 
1555       --need to add restrictions to serial base if we are allocating
1556       -- entire LPNs only
1557       --bug 2943552
1558       --  previoulsy, we were adding the new clause directly to
1559       --  g_pick_base_serial.  However, g_pick_base_serial is a global
1560       --  constant string that never gets cleared.  As a result, all
1561       --  subsequent serial sql statements would get this restriction.
1562       --  Now, we add the entire lpn only clause to g_base_from_serial.
1563       --bug 3064635 - after above fix, we were missing initial
1564       -- parantheses, because we were concatenating clause with
1565       -- g_pick_base_serial.  Now, we concatenate clause with
1566       -- g_base_from_serial
1567       IF p_allocation_mode_id = g_alloc_lpn_only THEN
1568         g_base_from_serial  := g_base_from_serial
1569                          || 'and msn.lpn_id IS NOT NULL
1570                              and not exists(
1571                                   select lpn_id
1572                                   from wms_license_plate_numbers wlpn1
1573                                   where wlpn1.parent_lpn_id = msn.lpn_id)
1574                                      and
1575                                         1 = (select count(distinct(moq1.inventory_item_id))
1576                                              from mtl_onhand_quantities_detail moq1
1577                                              where moq1.organization_id = msn.current_organization_id
1578                              and moq1.subinventory_code = msn.current_subinventory_code
1579                              and moq1.locator_id = msn.current_locator_id
1580                              and moq1.lpn_id = msn.lpn_id)
1581                             ';
1582       -- END IF;
1583     /* g_base_from_serial := g_base_from_serial || ')' || g_base_table_alias
1584                        || g_line_feed; */
1585 
1586     ---
1587     g_base_from_serial_v  :=
1588                    g_base_from_serial_v
1589                 || ' and msn.lpn_id IS NOT NULL
1590           and not exists(
1591         select lpn_id
1592         from wms_license_plate_numbers wlpn1
1593         where wlpn1.parent_lpn_id = msn.lpn_id)
1594           and
1595              1 = (select count(distinct(moq1.inventory_item_id))
1596                    from mtl_onhand_quantities_detail moq1
1597                    where moq1.organization_id = msn.current_organization_id
1598          and moq1.subinventory_code = msn.current_subinventory_code
1599          and moq1.locator_id = msn.current_locator_id
1600          and moq1.lpn_id = msn.lpn_id)
1601          ';
1602 
1603     ---
1604     g_base_from_serial_detail  :=
1605                    g_base_from_serial_detail
1606                 || ' and msn.lpn_id IS NOT NULL
1607           and not exists(
1608         select lpn_id
1609         from wms_license_plate_numbers wlpn1
1610         where wlpn1.parent_lpn_id = msn.lpn_id)
1611           and
1612              1 = (select count(distinct(moq1.inventory_item_id))
1613                    from mtl_onhand_quantities_detail moq1
1614                    where moq1.organization_id = msn.current_organization_id
1615          and moq1.subinventory_code = msn.current_subinventory_code
1616          and moq1.locator_id = msn.current_locator_id
1617          and moq1.lpn_id = msn.lpn_id)
1618          ';
1619 
1620       END IF;
1621 
1622         g_base_from_serial := g_base_from_serial || ')' || g_base_table_alias
1623                 || g_line_feed;
1624         g_base_from_serial_v := g_base_from_serial_v || ')' || g_base_table_alias
1625                 || g_line_feed;
1626 
1627         g_base_from_serial_detail := g_base_from_serial_detail || ')' || g_base_table_alias
1628                 || g_line_feed;
1629 
1630     --
1631     END IF;
1632 
1633     --currently used only for serial controlled item, when you aren't
1634     -- detailing serial numbers
1635     g_base_group_by     :=    g_base_table_alias
1636                            || '.ORGANIZATION_ID'
1637                            || g_line_feed
1638                            || ','
1639                            || g_base_table_alias
1640                            || '.INVENTORY_ITEM_ID'
1641                            || g_line_feed
1642                            || ','
1643                            || l_type_dependent_alias
1644                            || '.REVISION'
1645                            || g_line_feed
1646                            || ','
1647                            || l_type_dependent_alias
1648                            || '.LOT_NUMBER'
1649                            || g_line_feed
1650                            || ','
1651                            || g_base_table_alias
1652                            || '.LOT_EXPIRATION_DATE'
1653                            || g_line_feed
1654                            || ','
1655                            || g_base_table_alias
1656                            || '.SUBINVENTORY_CODE'
1657                            || g_line_feed
1658                            || ','
1659                            || g_base_table_alias
1660                            || '.LOCATOR_ID'
1661                            || g_line_feed
1662                            || ','
1663                            || g_base_table_alias
1664                            || '.COST_GROUP_ID'
1665                            || g_line_feed
1666                            || ','
1667                            || g_base_table_alias
1668                            || '.PROJECT_ID'
1669                            || g_line_feed
1670                            || ','
1671                            || g_base_table_alias
1672                            || '.TASK_ID'
1673                            || g_line_feed
1674                            || ','
1675                            || g_base_table_alias
1676                            || '.UOM_CODE'
1677                            || g_line_feed
1678                            || ','                                               --new
1679                            || g_base_table_alias                                --new
1680                            || '.GRADE_CODE'                                     --new
1681                            || g_line_feed;                                      --new
1682 
1683     --
1684     -- group by the base lpn id only if the lpn id is in the select statement
1685     IF p_allocation_mode_id IN (g_alloc_lpn_only, g_alloc_lpn_loose) THEN
1686       g_base_group_by  := g_base_group_by || ',' || g_base_table_alias || '.LPN_ID' || g_line_feed;
1687     END IF;
1688 
1689     -- debugging portion
1690     -- can be commented ut for final code
1691     log_procedure(l_api_name, 'end', 'End BuildBaseSql');
1692   -- end of debugging section
1693   --
1694   EXCEPTION
1695     WHEN fnd_api.g_exc_error THEN
1696       x_return_status  := fnd_api.g_ret_sts_error;
1697       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1698       --
1699       log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
1700     --
1701     WHEN fnd_api.g_exc_unexpected_error THEN
1702       x_return_status  := fnd_api.g_ret_sts_unexp_error;
1703       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1704       --
1705       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
1706 
1707     --
1708     WHEN OTHERS THEN
1709       x_return_status  := fnd_api.g_ret_sts_unexp_error;
1710 
1711       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1712         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1713       END IF;
1714 
1715       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1716       --
1717       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
1718 
1719   END buildbasesql;
1720 
1721   --
1722   -- Name        : BuildRuleSQL
1723   -- Function    : Builds the rule dependent part of the rule's sql statement
1724   -- Notes       : private procedure for internal use only
1725   PROCEDURE buildrulesql(
1726     x_return_status      OUT NOCOPY    VARCHAR2
1727   , x_msg_count          OUT NOCOPY    NUMBER
1728   , x_msg_data           OUT NOCOPY    VARCHAR2
1729   , p_rule_id            IN            NUMBER
1730   , p_type_code          IN            NUMBER
1731   , p_allocation_mode_id IN            NUMBER
1732   ) IS
1733     --
1734     l_api_name                   VARCHAR2(30)                                              := 'BuildRuleSQL';
1735     -- variables needed for dynamic SQL
1736     l_identifier                 VARCHAR2(10);
1737     -- other variables
1738     l_db_object_id               wms_db_objects.db_object_id%TYPE;
1739     l_table_name                 wms_db_objects.table_name%TYPE;
1740     l_table_alias                wms_db_objects.table_alias%TYPE;
1741     l_context_dependent_flag     wms_db_objects.context_dependent_flag%TYPE;
1742     l_parent_table_alias         wms_db_objects.table_alias%TYPE;
1743     l_parameter_type_code        wms_parameters_b.parameter_type_code%TYPE;
1744     l_column_name                wms_parameters_b.column_name%TYPE;
1745     l_expression                 wms_parameters_b.expression%TYPE;
1746     l_data_type_code             wms_parameters_b.data_type_code%TYPE;
1747     l_parent_parameter_type_code wms_parameters_b.parameter_type_code%TYPE;
1748     l_parent_column_name         wms_parameters_b.column_name%TYPE;
1749     l_parent_expression          wms_parameters_b.expression%TYPE;
1750     l_parent_data_type_code      wms_parameters_b.data_type_code%TYPE;
1751     l_operand_type_code          wms_restrictions.operand_type_code%TYPE;
1752     l_operand_constant_number    wms_restrictions.operand_constant_number%TYPE;
1753     l_operand_constant_character wms_restrictions.operand_constant_character%TYPE;
1754     l_operand_constant_date      wms_restrictions.operand_constant_date%TYPE;
1755     l_operand_expression         wms_restrictions.operand_expression%TYPE;
1756     l_operand_flex_value_set_id  wms_restrictions.operand_flex_value_set_id%TYPE;
1757     l_bracket_open               wms_restrictions.bracket_open%TYPE;
1758     l_bracket_close              wms_restrictions.bracket_close%TYPE;
1759     l_validation_type            fnd_flex_value_sets.validation_type%TYPE;
1760     l_id_column_name             fnd_flex_validation_tables.id_column_name%TYPE;
1761     l_value_column_name          fnd_flex_validation_tables.value_column_name%TYPE;
1762     l_application_table_name     fnd_flex_validation_tables.application_table_name%TYPE;
1763     l_additional_where_clause    fnd_flex_validation_tables.additional_where_clause%TYPE;
1764     l_left_part_conv_fct         VARCHAR2(40);
1765     l_right_part_conv_fct        VARCHAR2(40);
1766     l_outer_join                 VARCHAR2(4);
1767     l_logical_operator           mfg_lookups.meaning%TYPE;
1768     l_asc_desc                   mfg_lookups.meaning%TYPE;
1769     l_operator                   mfg_lookups.meaning%TYPE;
1770     l_restriction_exist          BOOLEAN                                                   := FALSE;
1771     l_rule_id                    NUMBER;
1772     l_sequence_number            NUMBER;
1773     l_flex_column_name           fnd_flex_validation_tables.id_column_name%TYPE;
1774     l_order_by_string            VARCHAR2(1000);
1775     l_new_constant_character     VARCHAR2(500);
1776     --l_new_expression      VARCHAR2(4100);
1777     l_consist_string             VARCHAR2(1000);
1778 
1779     -- cursor for all DB objects used within the rule.
1780     -- Most objects found using this query correspond to a database table
1781     -- which must be added to the from clause.
1782     -- DB Objects 1 and 2 are always included in the from clause, so
1783     --  we don't need to get them with this query.
1784     --
1785     -- 2/21/02 - remove quantity function objects from this query.  For
1786     -- putaway, we check quantity function in the Apply function.
1787     -- For picking, the quantity function object is "base", which is always
1788     -- included
1789     CURSOR objects IS
1790       -- 1. all single referenced DB objects
1791       SELECT   wdo.db_object_id
1792              , wdo.table_name
1793              , wdo.table_alias
1794              , wdo.context_dependent_flag
1795           FROM wms_db_objects wdo
1796              , wms_parameters_b wpb
1797              , (SELECT wsc.parameter_id
1798                   FROM wms_sort_criteria wsc
1799                  WHERE wsc.rule_id = p_rule_id
1800                 UNION
1801                 SELECT wr.parameter_id
1802                   FROM wms_restrictions wr
1803                  WHERE wr.rule_id = p_rule_id
1804                 UNION
1805                 SELECT wr.operand_parameter_id
1806                   FROM wms_restrictions wr
1807                  WHERE wr.rule_id = p_rule_id
1808                    AND wr.operand_type_code = 4
1809                 UNION
1810                 SELECT wrc.parameter_id
1811                   FROM wms_rule_consistencies wrc
1812                  WHERE wrc.rule_id = p_rule_id) x
1813          WHERE wpb.parameter_id = x.parameter_id
1814            AND wpb.db_object_ref_type_code = 1
1815            AND wdo.db_object_id = wpb.db_object_id
1816            AND wdo.db_object_id NOT IN (1, 2)
1817       UNION
1818       -- 2. all parents of single referenced DB objects
1819       SELECT   wdo.db_object_id
1820              , wdo.table_name
1821              , wdo.table_alias
1822              , wdo.context_dependent_flag
1823           FROM wms_db_objects wdo
1824              , (SELECT     wdop.parent_db_object_id
1825                       FROM wms_db_objects_parents wdop
1826                      WHERE wdop.type_code = p_type_code
1827                 CONNECT BY wdop.db_object_id = PRIOR wdop.parent_db_object_id
1828                 START WITH wdop.db_object_id IN (SELECT wdod.db_object_id
1829                                                    FROM wms_db_objects wdod
1830                                                       , wms_parameters_b wpbd
1831                                                       , (SELECT wscd.parameter_id
1832                                                            FROM wms_sort_criteria wscd
1833                                                           WHERE wscd.rule_id = p_rule_id
1834                                                          UNION
1835                                                          SELECT wrd.parameter_id
1836                                                            FROM wms_restrictions wrd
1837                                                           WHERE wrd.rule_id = p_rule_id
1838                                                          UNION
1839                                                          SELECT wrd.operand_parameter_id
1840                                                            FROM wms_restrictions wrd
1841                                                           WHERE wrd.rule_id = p_rule_id
1842                                                             AND wrd.operand_type_code = 4
1843                                                          UNION
1844                                                          SELECT wrcd.parameter_id
1845                                                            FROM wms_rule_consistencies wrcd
1846                                                           WHERE wrcd.rule_id = p_rule_id) xd
1847                                                   WHERE wpbd.parameter_id = xd.parameter_id
1848                                                     AND wpbd.db_object_ref_type_code = 1
1849                                                     AND wdod.db_object_id = wpbd.db_object_id)) x
1850          WHERE wdo.db_object_id = x.parent_db_object_id
1851            AND wdo.db_object_id NOT IN (1, 2)
1852       -- 3. all multi referenced DB objects
1853       UNION
1854       SELECT   wdo.db_object_id
1855              , wdo.table_name
1856              , NVL(wdorm.table_alias, wdo.table_alias)
1857              , wdo.context_dependent_flag
1858           FROM wms_db_objects wdo
1859              , wms_db_obj_ref_members wdorm
1860              , wms_db_object_references wdor
1861              , wms_parameters_b wpb
1862              , (SELECT wsc.parameter_id
1863                   FROM wms_sort_criteria wsc
1864                  WHERE wsc.rule_id = p_rule_id
1865                 UNION
1866                 SELECT wr.parameter_id
1867                   FROM wms_restrictions wr
1868                  WHERE wr.rule_id = p_rule_id
1869                 UNION
1870                 SELECT wr.operand_parameter_id
1871                   FROM wms_restrictions wr
1872                  WHERE wr.rule_id = p_rule_id
1873                    AND wr.operand_type_code = 4
1874                 UNION
1875                 SELECT wrc.parameter_id
1876                   FROM wms_rule_consistencies wrc
1877                  WHERE wrc.rule_id = p_rule_id) x
1878          WHERE wpb.parameter_id = x.parameter_id
1879            AND wpb.db_object_ref_type_code = 2
1880            AND wdor.db_object_reference_id = wpb.db_object_reference_id
1881            AND wdorm.db_object_reference_id = wdor.db_object_reference_id
1882            AND wdo.db_object_id = wdorm.db_object_id
1883            AND wdo.db_object_id NOT IN (1, 2)
1884       UNION
1885       -- 4. all parents of multi referenced DB objects
1886       SELECT   wdo.db_object_id
1887              , wdo.table_name
1888              , wdo.table_alias
1889              , wdo.context_dependent_flag
1890           FROM wms_db_objects wdo
1891              , (SELECT     wdop.parent_db_object_id
1892                       FROM wms_db_objects_parents wdop
1893                      WHERE wdop.type_code = p_type_code
1894                 CONNECT BY wdop.db_object_id = PRIOR wdop.parent_db_object_id
1895                 START WITH wdop.db_object_id IN (SELECT wdoi.db_object_id
1896                                                    FROM wms_db_objects wdoi
1897                                                       , wms_db_obj_ref_members wdormi
1898                                                       , wms_db_object_references wdori
1899                                                       , wms_parameters_b wpbi
1900                                                       , (SELECT wsc.parameter_id
1901                                                            FROM wms_sort_criteria wsc
1902                                                           WHERE wsc.rule_id = p_rule_id
1903                                                          UNION
1904                                                          SELECT wr.parameter_id
1905                                                            FROM wms_restrictions wr
1906                                                           WHERE wr.rule_id = p_rule_id
1907                                                          UNION
1908                                                          SELECT wr.operand_parameter_id
1909                                                            FROM wms_restrictions wr
1910                                                           WHERE wr.rule_id = p_rule_id
1911                                                             AND wr.operand_type_code = 4
1912                                                          UNION
1913                                                          SELECT wrc.parameter_id
1914                                                            FROM wms_rule_consistencies wrc
1915                                                           WHERE wrc.rule_id = p_rule_id) xi
1916                                                   WHERE wpbi.parameter_id = xi.parameter_id
1917                                                     AND wpbi.db_object_ref_type_code = 2
1918                                                     AND wdori.db_object_reference_id = wpbi.db_object_reference_id
1919                                                     AND wdormi.db_object_reference_id = wdori.db_object_reference_id
1920                                                     AND wdoi.db_object_id = wdormi.db_object_id)) x
1921          WHERE wdo.db_object_id = x.parent_db_object_id
1922            AND wdo.db_object_id NOT IN (1, 2)
1923       ORDER BY 1;
1924 
1925     --
1926     -- Finds the join conditions to join a DB object to it's parent
1927     --  DB object.  This is used to build the where clause for the rule.
1928     CURSOR conditions IS
1929       SELECT wpb.parameter_type_code
1930            , wpb.column_name
1931            , wpb.expression
1932            , wpb.data_type_code
1933            , wpbp.parameter_type_code
1934            , wpbp.column_name
1935            , wpbp.expression
1936            , wpbp.data_type_code
1937            , wdop.table_alias -- alias n.a. for multi object based parameters
1938         FROM wms_db_objects wdop, wms_parameters_b wpbp, wms_parameters_b wpb, wms_db_object_joins wdoj
1939        WHERE wdoj.db_object_id = l_db_object_id
1940          AND wdoj.type_code = p_type_code
1941          AND wpb.parameter_id = wdoj.parameter_id
1942          AND wpbp.parameter_id = wdoj.parent_parameter_id
1943          AND wdop.db_object_id(+) = wpbp.db_object_id;
1944 
1945     --
1946     -- cursor for the quantity function parameter of the actual rule.
1947     -- Used only for picking and putaway
1948     CURSOR qtyfnct IS
1949       SELECT wpb.parameter_type_code
1950            , wpb.column_name
1951            , wpb.expression
1952            , wpb.data_type_code
1953            , wdo.table_alias -- alias n.a. for multi object based parameters
1954         FROM wms_db_objects wdo, wms_parameters_b wpb, wms_rules_b wrb
1955        WHERE wrb.rule_id = p_rule_id
1956          AND wpb.parameter_id = wrb.qty_function_parameter_id
1957          AND wdo.db_object_id(+) = wpb.db_object_id;
1958 
1959     --
1960     -- Finds the restrictions defined in the rule.
1961     --  Each restriction becomes part of the where clause.
1962     CURSOR RESTRICT IS
1963       SELECT   wpbl.parameter_type_code
1964              , wpbl.column_name
1965              , wpbl.expression
1966              , wpbl.data_type_code
1967              , wdol.table_alias -- alias n.a. for multi object based parameters
1968              , DECODE(
1969                  wr.operator_code
1970                , 1, '>'
1971                , 2, '<'
1972                , 3, '='
1973                , 4, '<>'
1974                , 5, '>='
1975                , 6, '<='
1976                , 7, 'IN'
1977                , 8, 'NOT IN'
1978                , 9, 'LIKE'
1979                , 10, 'NOT LIKE'
1980                , 11, 'IS NULL'
1981                , 12, 'IS NOT NULL'
1982                , NULL
1983                )
1984              , wr.operand_type_code
1985              , wr.operand_constant_number
1986              , wr.operand_constant_character
1987              , wr.operand_constant_date
1988              , wr.operand_expression
1989              , wr.operand_flex_value_set_id
1990              , DECODE(wr.logical_operator_code, 1, 'and', 2, 'or', NULL)
1991              , wr.bracket_open
1992              , wr.bracket_close
1993              , wpbr.parameter_type_code
1994              , wpbr.column_name
1995              , wpbr.expression
1996              , DECODE(
1997                  wr.operand_type_code
1998                , 4, wpbr.data_type_code
1999                , 5, wpbl.data_type_code
2000                , 6, DECODE(ffvs.format_type, 'N', 1, 'C', 2, 3)
2001                , 7, NULL
2002                , wr.operand_type_code
2003                )
2004              , wdor.table_alias -- alias n.a. for multi object based parameters
2005              , ffvs.validation_type -- only 'independent' and 'table' are supported
2006              , ffvt.id_column_name
2007              , ffvt.value_column_name
2008              , ffvt.application_table_name
2009              , ffvt.additional_where_clause
2010              , wr.rule_id
2011              , wr.sequence_number
2012           FROM fnd_flex_validation_tables ffvt
2013              , fnd_flex_value_sets ffvs
2014              , wms_db_objects wdor
2015              , wms_parameters_b wpbr
2016              , wms_db_objects wdol
2017              , wms_parameters_b wpbl
2018              , wms_restrictions wr
2019          WHERE wr.rule_id = p_rule_id
2020            AND wpbl.parameter_id = wr.parameter_id
2021            AND wdol.db_object_id(+) = wpbl.db_object_id
2022            AND wpbr.parameter_id(+) = wr.operand_parameter_id
2023            AND wdor.db_object_id(+) = wpbr.db_object_id
2024            AND ffvs.flex_value_set_id(+) = wr.operand_flex_value_set_id
2025            AND ffvt.flex_value_set_id(+) = wr.operand_flex_value_set_id
2026       ORDER BY wr.rule_id, wr.sequence_number -- order is important
2027                                              ;
2028 
2029     --
2030     -- Finds the Sort criteria entries for this rule.  Each sort criterion
2031     -- becomes a part of the order by clause of the sql statement.
2032     CURSOR sortcrit IS
2033       SELECT   wpb.parameter_type_code
2034              , wpb.column_name
2035              , wpb.expression
2036              , wpb.data_type_code
2037              , wdo.table_alias -- alias n.a. for multi object based parameters
2038              , wms_parameter_pvt.getflexdatatypecode(
2039                  wpb.data_type_code
2040                , wpb.db_object_ref_type_code
2041                , wpb.parameter_type_code
2042                , wpb.flexfield_usage_code
2043                , wpb.flexfield_application_id
2044                , wpb.flexfield_name
2045                , wpb.column_name
2046                )
2047              , DECODE(wsc.order_code, 1, 'asc', 2, 'desc', NULL)
2048              , wsc.rule_id
2049              , wsc.sequence_number
2050           FROM wms_db_objects wdo, wms_parameters_b wpb, wms_sort_criteria wsc
2051          WHERE wsc.rule_id = p_rule_id
2052            AND wpb.parameter_id = wsc.parameter_id
2053            AND wdo.db_object_id(+) = wpb.db_object_id
2054       ORDER BY wsc.rule_id, wsc.sequence_number;
2055 
2056     --
2057     -- Used to find all the consistency restrictions for the rule.
2058     -- Used to build portions of the Select and order by clauses.
2059     CURSOR consistencies IS
2060       SELECT wpb.parameter_type_code
2061            , wpb.column_name
2062            , wpb.expression
2063            , wdo.table_alias
2064         FROM wms_rule_consistencies wrc, wms_parameters_b wpb, wms_db_objects wdo
2065        WHERE wrc.rule_id = p_rule_id
2066          AND wpb.parameter_id = wrc.parameter_id
2067          AND wdo.db_object_id(+) = wpb.db_object_id;
2068   BEGIN
2069     -- Initialize API return status to success
2070     x_return_status    := fnd_api.g_ret_sts_success;
2071 
2072     log_procedure(l_api_name, 'start', 'Start BuildRuleSql');
2073     log_statement(l_api_name, 'rule_id', 'rule_id: ' || p_rule_id);
2074     log_statement(l_api_name, 'type_code', 'type_code: ' || p_type_code);
2075 
2076     -- end of debugging section
2077     --
2078     --If no rule, build default rule
2079     IF p_rule_id IS NULL THEN
2080       log_statement(l_api_name, 'null_rule_id', 'Rule id is NULL');
2081 
2082       -- if no rule and strategy is defined
2083       -- hardcoded this section
2084       IF p_type_code = 2 THEN
2085         g_rule_select  := 'NULL serial_number
2086                           ,nvl(base.primary_quantity,0)
2087                           ,nvl(base.secondary_quantity,0)              -- new
2088                           ,base.grade_code,                            -- new
2089                           ,NULL consist_string,
2090                           ,NULL order_by_string';
2091         g_rule_from    := ' mtl_system_items msi, ';
2092         g_rule_where   :=
2093                          ' and msi.ORGANIZATION_ID = mptdtv.FROM_ORGANIZATION_ID
2094                            and msi.INVENTORY_ITEM_ID = mptdtv.inventory_item_id ';
2095       ELSE
2096         g_rule_select  := 'NULL serial_number
2097                           ,nvl(WMS_Parameter_PVT.GetAvailableUnitCapacity
2098                                 (  mptdtv.TO_ORGANIZATION_ID
2099                                    ,base.SUBINVENTORY_CODE
2100                                    ,base.LOCATOR_ID
2101                                    ,mil.LOCATION_MAXIMUM_UNITS
2102                                 )
2103                                ,0)
2104                           ,NULL consist_string
2105                           ,NULL order_by_string';
2106         g_rule_from    := ' mtl_item_locations mil , ';
2107         g_rule_where   := ' and mil.ORGANIZATION_ID (+) = base.ORGANIZATION_ID
2108                             and mil.INVENTORY_LOCATION_ID (+) = base.locator_id ';
2109       END IF;
2110 
2111       g_rule_order     := NULL;
2112       --
2113       x_return_status  := fnd_api.g_ret_sts_success;
2114       RETURN;
2115     END IF;
2116 
2117     -- Find all DB objects referenced within the rule and add them to the
2118     -- from clause.
2119     log_statement(l_api_name, 'start_objects', 'start objects loop');
2120     OPEN objects;
2121 
2122     WHILE TRUE LOOP
2123       FETCH objects INTO l_db_object_id, l_table_name, l_table_alias, l_context_dependent_flag;
2124       EXIT WHEN objects%NOTFOUND;
2125       log_statement(l_api_name, 'db_object_id', 'db_object_id: ' || l_db_object_id);
2126 
2127       --
2128       -- Add DB objects to the from clause
2129 
2130       -- For TTA, if g_rule_from is NULL, do no add ','
2131       -- Don't add a comma for the first table in the from clause
2132       IF  (g_rule_from IS NULL)
2133           AND (p_type_code IN (3, 4, 5, 7)) THEN -- brach for TTA
2134         g_rule_from  := l_table_name || ' ' || l_table_alias;
2135       ELSE
2136         g_rule_from  := l_table_name || ' ' || l_table_alias || g_line_feed || ',' || g_rule_from;
2137       END IF; -- end TTA branch
2138 
2139       -- Find each join condition joining current db object to its
2140       -- parent db object.  Add these conditions to the where clause.
2141       log_statement(l_api_name, 'start_conditions', 'start conditions loop');
2142       OPEN conditions;
2143 
2144       WHILE TRUE LOOP
2145         FETCH conditions INTO l_parameter_type_code
2146                             , l_column_name
2147                             , l_expression
2148                             , l_data_type_code
2149                             , l_parent_parameter_type_code
2150                             , l_parent_column_name
2151                             , l_parent_expression
2152                             , l_parent_data_type_code
2153                             , l_parent_table_alias;
2154         EXIT WHEN conditions%NOTFOUND;
2155         --
2156         log_statement(l_api_name, 'param_type_code', 'param_type_code: ' || l_parameter_type_code);
2157         log_statement(l_api_name, 'column_name', 'column_name: ' || l_column_name);
2158         log_statement(l_api_name, 'expression', 'expression: ' || l_expression);
2159         log_statement(l_api_name, 'data_type_code', 'data_type_code: ' || l_data_type_code);
2160         log_statement(l_api_name, 'parent_param_type_code', 'parent_param_type_code: ' || l_parent_parameter_type_code);
2161         log_statement(l_api_name, 'parent_column_name', 'parent_column_name: ' || l_parent_column_name);
2162         log_statement(l_api_name, 'parent_expression', 'parent_expression: ' || l_parent_expression);
2163         log_statement(l_api_name, 'parent_data_type_code', 'parent_data_type_code: ' || l_parent_data_type_code);
2164         log_statement(l_api_name, 'parent_table_alias', 'parent_table_alias: ' || l_parent_table_alias);
2165         -- find out, if data type conversion is needed
2166         inv_sql_binding_pvt.getconversionstring(l_data_type_code, l_parent_data_type_code, l_left_part_conv_fct, l_right_part_conv_fct);
2167 
2168         --
2169         -- find out, if outer join has to be used
2170         IF l_context_dependent_flag = 'Y' THEN
2171           l_outer_join  := ' (+)';
2172         ELSIF l_context_dependent_flag = 'N' THEN
2173           l_outer_join  := NULL;
2174         ELSE
2175           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2176             fnd_message.set_name('WMS', 'WMS_BAD_CONTEXT_DEPT_FLAG');
2177             fnd_message.set_token('CONTEXT_DEPENDENT_FLAG', l_context_dependent_flag);
2178             log_error_msg(l_api_name, 'bad_context_depend_flag');
2179             fnd_msg_pub.ADD;
2180           END IF;
2181 
2182           RAISE fnd_api.g_exc_error;
2183         END IF;
2184 
2185         --
2186         -- add join conditions to where clause
2187         -- first, build the left side of the join
2188         g_rule_where  := g_rule_where || 'and ';
2189 
2190         IF l_parameter_type_code = 1 THEN -- based on column in table
2191           g_rule_where  := g_rule_where || l_table_alias || '.' || l_column_name || l_outer_join;
2192         ELSIF l_parameter_type_code = 2 THEN -- based on expression
2193           --g_rule_where  := g_rule_where || l_expression || l_outer_join;
2194           g_rule_where  := g_rule_where || l_expression ;    -- || l_outer_join; --Bug #3719043
2195         ELSE
2196           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2197             fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2198             fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2199             log_error_msg(l_api_name, 'bad_param_type_code_joins');
2200             fnd_msg_pub.ADD;
2201           END IF;
2202 
2203           RAISE fnd_api.g_exc_error;
2204         END IF;
2205 
2206         -- add equal sign
2207         g_rule_where  := g_rule_where || ' = ' || l_left_part_conv_fct;
2208 
2209         -- now, build right side of join condition
2210         IF l_parent_parameter_type_code = 1 THEN
2211           g_rule_where  := g_rule_where || l_parent_table_alias || '.' || l_parent_column_name;
2212         ELSIF l_parent_parameter_type_code = 2 THEN
2213           g_rule_where  := g_rule_where || l_parent_expression;
2214         ELSE
2215           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2216             fnd_message.set_name('WMS', 'WMS_BAD_PARENT_PARA_TYPE');
2217             fnd_message.set_token('PARENT_PARAMETER_TYPE_CODE', l_parent_parameter_type_code);
2218             log_error_msg(l_api_name, 'bad_parent_param_type_joins');
2219             fnd_msg_pub.ADD;
2220           END IF;
2221 
2222           RAISE fnd_api.g_exc_error;
2223         END IF;
2224 
2225         g_rule_where  := g_rule_where || l_right_part_conv_fct || g_line_feed;
2226       END LOOP;
2227 
2228       CLOSE conditions;
2229       log_statement(l_api_name, 'end_conditions', 'end of conditions loop');
2230     END LOOP;
2231 
2232     CLOSE objects;
2233     log_statement(l_api_name, 'end_objects', 'end of objects loop');
2234 
2235     -- Add qty function parameter
2236     -- added by jcearley on 12/8/99
2237     -- qtyfunction should be added only for picking or putaway
2238     -- 2/21/02 - we no longer add the quantity function to the putaway
2239     -- sql statement.  Instead, we check capacity in Apply.
2240     -- old code: IF (p_type_code IN (1,2)) THEN
2241     IF (p_type_code = 2) THEN
2242       -- Add serial number to select statement.  If item is serial controlled,
2243       -- and we are detailing it, then get serial number from base.  Otherwise,
2244       -- set serial number to NULL
2245       IF p_type_code = 2 THEN
2246         g_rule_select  := g_rule_select || ',' || g_base_table_alias || '.SERIAL_NUMBER' || g_line_feed;
2247       ELSE
2248         g_rule_select  := g_rule_select || ',NULL SERIAL_NUMBER' || g_line_feed;
2249       END IF;
2250 
2251       -- Used when we are detailing a serial controlled item but
2252       -- not detailing serial numbers.
2253       g_rule_select_serial  := g_rule_select_serial || ',NULL SERIAL_NUMBER' || g_line_feed;
2254       log_statement(l_api_name, 'qty_func', 'finding qty function');
2255       OPEN qtyfnct;
2256       FETCH qtyfnct INTO l_parameter_type_code, l_column_name, l_expression, l_data_type_code, l_table_alias;
2257 
2258       IF qtyfnct%NOTFOUND THEN
2259         CLOSE qtyfnct;
2260 
2261         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2262           fnd_message.set_name('WMS', 'WMS_QTY_FUNC_NOT_FOUND');
2263           log_error_msg(l_api_name, 'qty_func_not_found');
2264           fnd_msg_pub.ADD;
2265         END IF;
2266 
2267         RAISE fnd_api.g_exc_error;
2268       END IF;
2269 
2270       CLOSE qtyfnct;
2271       --
2272       log_statement(l_api_name, 'param_type_code_qty', 'param_type_code: ' || l_parameter_type_code);
2273       log_statement(l_api_name, 'column_name_qty', 'column_name: ' || l_column_name);
2274       log_statement(l_api_name, 'expression_qty', 'expression: ' || l_expression);
2275       log_statement(l_api_name, 'data_type_code_qty', 'data_type_code: ' || l_data_type_code);
2276       log_statement(l_api_name, 'table_alias_qty', 'table_alias: ' || l_table_alias);
2277 
2278       IF l_data_type_code <> 1 THEN
2279         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2280           fnd_message.set_name('WMS', 'WMS_BAD_QTY_FUNC_DATA_TYPE');
2281           fnd_message.set_token('DATATYPE', l_data_type_code);
2282           log_error_msg(l_api_name, 'bad_qty_func_data_type');
2283           fnd_msg_pub.ADD;
2284         END IF;
2285 
2286         RAISE fnd_api.g_exc_error;
2287       END IF;
2288 
2289       --
2290 
2291       -- Add qty function parameter to select clause
2292       IF l_parameter_type_code = 1 THEN
2293         g_rule_select         := g_rule_select || ',nvl(' || l_table_alias || '.' || l_column_name || ',0)' || g_line_feed;
2294         g_rule_select_serial  := g_rule_select_serial || ',sum(nvl(' || l_table_alias || '.' || l_column_name || ',0))' || g_line_feed;
2295       ELSIF l_parameter_type_code = 2 THEN
2296         -- Important Detail !!!
2297         -- Since the only quantity used by the engine internally
2298         -- for picking is the primary quantity,
2299         -- the expression from the parameter is ignored here.
2300         -- Instead, we only look at the primary quantity from the
2301         -- base.
2302         -- The next line is commented out and replaced with the
2303         -- line followed.
2304 
2305         --updated by jcearley on 12/7/99
2306         -- primary quantity is only useful for picking. Thus, I'm adding a check
2307         -- on the type_code.  If it's picking, use primary qty.  If it's put away,
2308         -- use the previously commented out line.
2309         IF (p_type_code = 1) THEN --put away
2310           g_rule_select         := g_rule_select
2311                                    || ',nvl(' || l_expression || ',0)'
2312                                    || g_line_feed;
2313           g_rule_select_serial  := g_rule_select_serial
2314                                    || ',sum(nvl(' || l_expression || ',0))'
2315                                    || g_line_feed;
2316         ELSIF (p_type_code = 2) THEN
2317           g_rule_select         := g_rule_select
2318                                 || ',base.primary_quantity ' || g_line_feed
2319                                 || ',base.secondary_quantity ' || g_line_feed         -- new
2320                                 || ',base.grade_code ' || g_line_feed;                -- new
2321           g_rule_select_serial  := g_rule_select_serial
2322                                 || ',sum(base.primary_quantity) ' || g_line_feed
2323                                 || ',sum(base.secondary_quantity) ' || g_line_feed         -- new
2324                                 || ',base.grade_code ' || g_line_feed;                -- new
2325         END IF;
2326       ELSE
2327         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2328           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2329           fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2330           log_error_msg(l_api_name, 'bad_param_type_code_qty');
2331           fnd_msg_pub.ADD;
2332         END IF;
2333 
2334         RAISE fnd_api.g_exc_error;
2335       END IF; -- parameter type code = 1
2336     END IF; -- type code in 1,2
2337 
2338     --
2339     log_statement(l_api_name, 'start_restrictions', 'start restrictions loop');
2340     -- Add restrictions
2341     OPEN RESTRICT;
2342 
2343     --
2344     --  Loop through all the restrictions, adding them to where clause
2345     WHILE TRUE LOOP
2346       FETCH RESTRICT INTO l_parameter_type_code
2347                         , l_column_name
2348                         , l_expression
2349                         , l_data_type_code
2350                         , l_table_alias
2351                         , l_operator
2352                         , l_operand_type_code
2353                         , l_operand_constant_number
2354                         , l_operand_constant_character
2355                         , l_operand_constant_date
2356                         , l_operand_expression
2357                         , l_operand_flex_value_set_id
2358                         , l_logical_operator
2359                         , l_bracket_open
2360                         , l_bracket_close
2361                         , l_parent_parameter_type_code
2362                         , l_parent_column_name
2363                         , l_parent_expression
2364                         , l_parent_data_type_code
2365                         , l_parent_table_alias
2366                         , l_validation_type
2367                         , l_id_column_name
2368                         , l_value_column_name
2369                         , l_application_table_name
2370                         , l_additional_where_clause
2371                         , l_rule_id
2372                         , l_sequence_number;
2373       EXIT WHEN RESTRICT%NOTFOUND;
2374       --
2375       log_statement(l_api_name, 'sequence_num', 'sequence_num: ' || l_sequence_number);
2376 
2377       -- For first restriction, add 'and (' before adding the restrictions.
2378       -- Needed to join restrictions and other join statements already in
2379       -- the where clause.
2380       IF l_restriction_exist = FALSE THEN
2381         l_restriction_exist  := TRUE;
2382         g_rule_where         := g_rule_where || 'and (' || g_line_feed;
2383       END IF;
2384 
2385       --
2386       -- find out, if data type conversion is needed
2387       inv_sql_binding_pvt.getconversionstring(l_parent_data_type_code, l_data_type_code, l_left_part_conv_fct, l_right_part_conv_fct);
2388       log_statement(l_api_name, 'left_part', 'add left part of res');
2389 
2390       -- add left part of the restrictions
2391       IF l_parameter_type_code = 1 THEN -- parameter is table.column
2392         g_rule_where  :=    g_rule_where
2393                          || l_logical_operator
2394                          || l_bracket_open
2395                          || ' '
2396                          || l_left_part_conv_fct
2397                          || l_table_alias
2398                          || '.'
2399                          || l_column_name
2400                          || l_right_part_conv_fct
2401                          || ' '
2402                          || l_operator
2403                          || ' ';
2404       ELSIF l_parameter_type_code = 2 THEN -- parameter is an expression
2405         g_rule_where  :=    g_rule_where
2406                          || l_logical_operator
2407                          || l_bracket_open
2408                          || ' '
2409                          || l_left_part_conv_fct
2410                          || l_expression
2411                          || l_right_part_conv_fct
2412                          || ' '
2413                          || l_operator
2414                          || ' ';
2415       ELSE
2416         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2417           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2418           fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2419           log_error_msg(l_api_name, 'bad_param_type_code_left_rest');
2420           fnd_msg_pub.ADD;
2421         END IF;
2422 
2423         RAISE fnd_api.g_exc_error;
2424       END IF;
2425 
2426       --
2427       log_statement(l_api_name, 'right_part', 'add right part of res');
2428 
2429       -- add right part of the restrictions
2430 
2431       IF l_operand_type_code = 1 THEN -- right side = const. number
2432         g_rule_where  := g_rule_where || l_operand_constant_number || l_operand_expression || l_bracket_close || g_line_feed;
2433       ELSIF l_operand_type_code = 2 THEN -- right side = const. character
2434         --need to insert escape character of any apostrophes already in
2435         -- character field
2436 
2437         --first case - string of length one
2438         IF LENGTH(l_operand_constant_character) = 1 THEN
2439           --if the one character is an apostrophe, provide escape
2440           -- character, then add single quotes
2441           IF l_operand_constant_character = '''' THEN
2442             l_new_constant_character  := '''''';
2443           END IF;
2444 
2445           l_new_constant_character  := '''' || l_operand_constant_character || '''';
2446         -- second case - length > 2 - treat any single quote which is not
2447         -- the first or last character as an apostrophe, and ecape the
2448         -- character
2449         ELSIF LENGTH(l_operand_constant_character) > 2 THEN
2450           --    get the string minus the first and last characters
2451           --    (we take care of first and last characters later)
2452           l_new_constant_character  := SUBSTR(l_operand_constant_character, 2, LENGTH(l_operand_constant_character) - 2);
2453           --    replace all apostrophes with two apostrophes
2454           l_new_constant_character  := REPLACE(l_new_constant_character, '''', '''''');
2455           --    recontstruct the original string
2456           l_new_constant_character  :=
2457                          SUBSTR(l_operand_constant_character, 1, 1)
2458                          || l_new_constant_character
2459                          || SUBSTR( l_operand_constant_character , -1 , 1 );
2460         -- third case - Length 2 - treat any single quote like a single
2461         -- quote.  we deal with quotes at the beginning and end of the string
2462         -- below.
2463         ELSE
2464           l_new_constant_character  := l_operand_constant_character;
2465         END IF;
2466 
2467         IF LENGTH(l_new_constant_character) > 1 THEN
2468           --check to see if string already has single quotes around it
2469           --if not, add the quotes.
2470           --this process checks both sides. if there is an initial quote but not
2471           -- a trailing quote, only the trailing quote is added.
2472           IF (SUBSTR(l_new_constant_character, 1, 1) <> '''') THEN
2473             l_new_constant_character  := '''' || l_new_constant_character;
2474           END IF;
2475 
2476           IF (SUBSTR(l_new_constant_character, -1, 1) <> '''') THEN
2477             l_new_constant_character  := l_new_constant_character || '''';
2478           END IF;
2479         END IF;
2480 
2481         g_rule_where  := g_rule_where || l_new_constant_character || l_bracket_close || g_line_feed;
2482       ELSIF l_operand_type_code = 3 THEN -- right side = const. date
2483         --l_identifier := inv_sql_binding_pvt.InitBindVar(l_operand_constant_date);
2484         --Bug #2611142 - Add quotes before and after l_operand_constant_date
2485         g_rule_where  := g_rule_where
2486                        || ''''
2487                        || l_operand_constant_date
2488                        || ''''
2489                        || ' '
2490                        || l_operand_expression
2491                        || l_bracket_close
2492                        || g_line_feed;
2493       ELSIF l_operand_type_code = 4 THEN -- right side = parameter
2494         IF l_parent_parameter_type_code = 1 THEN -- table.column
2495           g_rule_where  :=
2496                 g_rule_where || l_parent_table_alias
2497                              || '.'
2498                              || l_parent_column_name
2499                              || l_operand_expression
2500                              || l_bracket_close
2501                              || g_line_feed;
2502         ELSIF l_parent_parameter_type_code = 2 THEN -- expression
2503           g_rule_where  := g_rule_where
2504                           || l_parent_expression
2505                           || l_operand_expression
2506                           || l_bracket_close
2507                           || g_line_feed;
2508         ELSE
2509           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2510             fnd_message.set_name('WMS', 'WMS_BAD_PARENT_PARA_TYPE');
2511             fnd_message.set_token('PARENT_PARAMETER_TYPE_CODE', l_parent_parameter_type_code);
2512             log_error_msg(l_api_name, 'bad_parent_param_type_right_rest');
2513             fnd_msg_pub.ADD;
2514           END IF;
2515 
2516           RAISE fnd_api.g_exc_error;
2517         END IF;
2518       ELSIF l_operand_type_code = 5 THEN -- right side = expression
2519         --changed by jcearley on 12/8/99 - automatically put expression
2520         -- in parentheses - prevents syntax error during rule generation
2521         g_rule_where  := g_rule_where
2522                        || '(' || l_operand_expression || ')'
2523                        || l_bracket_close
2524                        || g_line_feed;
2525       ELSIF l_operand_type_code = 6 THEN -- right side = flex value set
2526         IF l_validation_type = 'F' THEN -- > validation type 'table'
2527           IF (l_id_column_name IS NULL) THEN
2528             l_flex_column_name  := l_value_column_name;
2529           ELSE
2530             l_flex_column_name  := l_id_column_name;
2531           END IF;
2532 
2533           g_rule_where  :=    g_rule_where
2534                            || '( select '
2535                            || l_flex_column_name
2536                            || ' from '
2537                            || l_application_table_name
2538                            || ' '
2539                            || l_additional_where_clause
2540                            || ')'
2541                            || l_bracket_close
2542                            || g_line_feed;
2543         ELSIF l_validation_type = 'I' THEN -- > validation type 'independent'
2544           --l_identifier := inv_sql_binding_pvt.initbindvar
2545            -- (l_operand_flex_value_set_id);
2546           g_rule_where  :=    g_rule_where
2547                            || '( select FLEX_VALUE from '
2548                            || 'FND_FLEX_VALUES_VL where FLEX_VALUE_SET_ID = '
2549                            || l_operand_flex_value_set_id
2550                            || ' and ENABLED_FLAG = ''Y'' and sysdate between nvl('
2551                            || 'START_DATE_ACTIVE,sysdate-1) and nvl('
2552                            || 'END_DATE_ACTIVE,sysdate+1) )'
2553                            || l_bracket_close
2554                            || g_line_feed;
2555         ELSE
2556           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2557             fnd_message.set_name('WMS', 'WMS_BAD_REF_FLEXVSET_DATA');
2558             fnd_message.set_token('DATATYPE', l_validation_type);
2559             log_error_msg(l_api_name, 'bad_ref_flexvset_data');
2560             fnd_msg_pub.ADD;
2561           END IF;
2562 
2563           RAISE fnd_api.g_exc_error;
2564         END IF;
2565       ELSIF l_operand_type_code = 7 THEN -- right side = nothing
2566         g_rule_where  := g_rule_where || l_bracket_close || g_line_feed;
2567       ELSE
2568         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2569           fnd_message.set_name('WMS', 'WMS_BAD_OPERAND_TYPE_CODE');
2570           fnd_message.set_token('OPERAND_TYPE_CODE', l_operand_type_code);
2571           fnd_msg_pub.ADD;
2572         END IF;
2573 
2574         RAISE fnd_api.g_exc_error;
2575       END IF;
2576     END LOOP;
2577 
2578     CLOSE RESTRICT;
2579     --
2580     log_statement(l_api_name, 'end_restrictions', 'end restrictions loop');
2581 
2582     -- Insert bracket after adding the additional restriction clauses
2583     IF l_restriction_exist = TRUE THEN
2584       g_rule_where  := g_rule_where || ')' || g_line_feed;
2585     END IF;
2586 
2587     --
2588 
2589     l_order_by_string  := NULL;
2590     log_statement(l_api_name, 'alloc_mode', 'alloc_mode: ' || p_allocation_mode_id);
2591     log_statement(l_api_name, 'start_sort_crit', 'start sort crit loop');
2592     -- Add sort criteria
2593     OPEN sortcrit;
2594 
2595     --
2596     -- Loop through all sort criteria, adding them to Order By clause
2597     WHILE TRUE LOOP
2598       FETCH sortcrit INTO l_parameter_type_code
2599                         , l_column_name
2600                         , l_expression
2601                         , l_data_type_code
2602                         , l_table_alias
2603                         , l_parent_data_type_code
2604                         , l_asc_desc
2605                         , l_rule_id
2606                         , l_sequence_number;
2607       EXIT WHEN sortcrit%NOTFOUND;
2608       --
2609       log_statement(l_api_name, 'seq_number_sort', 'seq_number sort:' || l_sequence_number);
2610       -- find out, if data type conversion is needed
2611       inv_sql_binding_pvt.getconversionstring(l_parent_data_type_code
2612                                             , l_data_type_code
2613                                             , l_left_part_conv_fct
2614                                             , l_right_part_conv_fct);
2615 
2616       -- initialize  order by clause
2617       IF g_rule_order IS NOT NULL THEN
2618         g_rule_order  := g_rule_order || ',';
2619       END IF;
2620 
2621       --
2622       -- add sort criterion to order by clause
2623       IF l_parameter_type_code = 1 THEN -- table.column
2624         g_rule_order  :=    g_rule_order
2625                          || l_left_part_conv_fct
2626                          || l_table_alias
2627                          || '.'
2628                          || l_column_name
2629                          || l_right_part_conv_fct
2630                          || ' '
2631                          || l_asc_desc
2632                          || g_line_feed;
2633 
2634         --added support for Picking by UOM
2635         --build the order_by_string for the select stmt;
2636         --this string is a concatenation of all the columns in the
2637         -- order by clause.
2638         -- order by string only matters for picking - set to NULL
2639         -- if not picking
2640         -- Needed in Apply procedure.
2641         IF (p_type_code = 2) THEN --pick
2642           IF (l_order_by_string IS NULL) THEN
2643             l_order_by_string  := l_left_part_conv_fct
2644                                 || l_table_alias || '.' || l_column_name
2645                                 || l_right_part_conv_fct;
2646           ELSE
2647             -- need to hard code in '||' so string is concatenated at
2648             -- run time
2649             l_order_by_string  :=
2650                             l_order_by_string
2651                             || '||'
2652                             || l_left_part_conv_fct
2653                             || l_table_alias || '.' || l_column_name
2654                             || l_right_part_conv_fct;
2655           END IF;
2656 
2657           -- include sort criteria in the group by clause, so that
2658                 --  we can preserve the sort order.  Used only when
2659                 --  detailing serial controlled items but not detailing serial
2660                 --  numbers.
2661           g_rule_group_by  := g_rule_group_by || ',' || l_table_alias || '.' || l_column_name;
2662         END IF;
2663       ELSIF l_parameter_type_code = 2 THEN -- expression
2664         g_rule_order  := g_rule_order
2665                        || l_left_part_conv_fct
2666                        || l_expression
2667                        || l_right_part_conv_fct
2668                        || ' '
2669                        || l_asc_desc
2670                        || g_line_feed;
2671 
2672         --build the order_by_string for the select stmt
2673         IF (p_type_code = 2) THEN --pick
2674           IF (l_order_by_string IS NULL) THEN
2675             l_order_by_string  := l_left_part_conv_fct || l_expression || l_right_part_conv_fct;
2676           ELSE
2677             l_order_by_string  := l_order_by_string
2678                                    || '||'
2679                                    || l_left_part_conv_fct
2680                                    || l_expression
2681                                    || l_right_part_conv_fct;
2682           END IF;
2683 
2684           g_rule_group_by  := g_rule_group_by || ',' || l_expression;
2685         END IF;
2686       ELSE
2687         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2688           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2689           fnd_message.set_token('OPERAND_TYPE_CODE', l_parameter_type_code);
2690           log_error_msg(l_api_name, 'bad_param_type_code_sort');
2691           fnd_msg_pub.ADD;
2692         END IF;
2693 
2694         RAISE fnd_api.g_exc_error;
2695       END IF;
2696     END LOOP;
2697 
2698     CLOSE sortcrit;
2699     log_statement(l_api_name, 'end_sort_crit', 'end sort crit loop');
2700 
2701     --Pick UOM and Rule Consistencies are supported only for picking rules
2702     IF (p_type_code = 2) THEN
2703       l_consist_string  := NULL;
2704       --Get consistencies from cursor;
2705       -- These consistencies are concatenated together to form one
2706       --  string. This string is added to the select and order by for the
2707       --  rule sql, and are used in the Apply function.
2708       OPEN consistencies;
2709 
2710       LOOP
2711         FETCH consistencies INTO l_parameter_type_code, l_column_name, l_expression, l_table_alias;
2712         EXIT WHEN consistencies%NOTFOUND;
2713 
2714         -- if parameter is a db column
2715         IF l_parameter_type_code = 1 THEN
2716           IF l_consist_string IS NULL THEN
2717             l_consist_string  := l_table_alias || '.' || l_column_name;
2718           ELSE
2719             --parameter is expression
2720             l_consist_string  := l_consist_string
2721                                 || '||'
2722                                 || l_table_alias || '.' || l_column_name;
2723           END IF;
2724 
2725           -- include consistencies in the group by clause, so that
2726                 --  we can preserve them.  Used only when
2727                 --  detailing serial controlled items but not detailing serial
2728                 --  numbers.
2729           g_rule_group_by  := g_rule_group_by
2730                              || ','
2731                              || l_table_alias || '.' || l_column_name
2732                              || g_line_feed;
2733         -- if parameter is an expression
2734         ELSIF l_parameter_type_code = 2 THEN
2735           IF l_consist_string IS NULL THEN
2736             l_consist_string  := l_expression;
2737           ELSE
2738             l_consist_string  := l_consist_string || '||' || l_expression;
2739           END IF;
2740 
2741           g_rule_group_by  := g_rule_group_by || ',' || l_expression || g_line_feed;
2742         ELSE
2743           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2744           fnd_message.set_token('OPERAND_TYPE_CODE', l_parameter_type_code);
2745           log_error_msg(l_api_name, 'bad_param_type_code_consist');
2746           fnd_msg_pub.ADD;
2747           RAISE fnd_api.g_exc_error;
2748         END IF;
2749       END LOOP;
2750 
2751       --add consist_string to the select clause
2752       -- Used in Apply procedure
2753       IF l_consist_string IS NOT NULL THEN
2754         IF g_rule_order IS NULL THEN
2755           g_rule_order  := l_consist_string || g_line_feed;
2756         ELSE
2757           g_rule_order  := g_rule_order || ',' || l_consist_string || g_line_feed;
2758         END IF;
2759 
2760         /* No longer added consist_string to order_by_string
2761           IF l_order_by_string IS NULL THEN
2762              l_order_by_string := l_consist_string;
2763     ELSE
2764              l_order_by_string:=l_order_by_string || '||' || l_consist_string;
2765           END IF;
2766         */
2767         g_rule_select         := g_rule_select
2768                                 || ','
2769                                 || l_consist_string
2770                                 || ' consist_string'
2771                                 || g_line_feed;
2772         g_rule_select_serial  := g_rule_select_serial
2773                                 || ','
2774                                 || l_consist_string
2775                                 || ' consist_string'
2776                                 || g_line_feed;
2777         g_rule_group_by       := g_rule_group_by
2778                                 || ','
2779                                 || l_consist_string
2780                                 || g_line_feed;
2781       -- if no consistencies, don't add anything to order by
2782       ELSE
2783         g_rule_select         := g_rule_select || ',NULL consist_string' || g_line_feed;
2784         g_rule_select_serial  := g_rule_select_serial || ',NULL consist_string' || g_line_feed;
2785       END IF;
2786 
2787       --Add conversion_rate to sort criteria
2788       --if efficient pick flag is set, add conversion rate to front of order by;
2789       --otherwise, add to end of order by
2790       -- Bug#6802143: Serial Number is added in the order by and group by clause for Picking.
2791       IF (g_rule_order IS NULL) THEN
2792         -- conversion rate is only order by
2793         g_rule_order  := g_rule_order
2794 	                  || g_base_table_alias
2795                           || '.SERIAL_NUMBER asc'
2796                           || ','
2797                           || g_base_table_alias
2798                           || '.CONVERSION_RATE desc'
2799                           || g_line_feed;
2800       ELSIF (p_allocation_mode_id IN (g_alloc_pick_uom, g_alloc_strict_pick_uom)) THEN
2801         g_rule_order  := g_base_table_alias
2802                           || '.CONVERSION_RATE desc'
2803                           || g_line_feed
2804                           || ','
2805 			  || g_base_table_alias
2806                           || '.SERIAL_NUMBER asc'
2807                           || ','
2808                           || g_rule_order;
2809       ELSE
2810         g_rule_order  := g_rule_order
2811                           || ','
2812 			  || g_base_table_alias
2813                           || '.SERIAL_NUMBER asc'
2814                           || ','
2815                           || g_base_table_alias
2816                           || '.CONVERSION_RATE desc'
2817                           || g_line_feed;
2818       END IF;
2819 
2820       g_rule_group_by   := g_rule_group_by
2821                           || ','
2822 			  || g_base_table_alias
2823                           || '.SERIAL_NUMBER'
2824                           || ','
2825                           || g_base_table_alias
2826                           || '.CONVERSION_RATE'
2827                           || g_line_feed;
2828 
2829       -- Add the order_by_string to the select and group by clauses.
2830       -- This string is used in the Apply procedure.
2831       IF (l_order_by_string IS NOT NULL) THEN
2832         g_rule_select         := g_rule_select
2833                                 || ','
2834                                 || l_order_by_string
2835                                 || ' order_by_string'
2836                                 || g_line_feed;
2837         g_rule_select_serial  := g_rule_select_serial
2838                                 || ','
2839                                 || l_order_by_string
2840                                 || ' order_by_string'
2841                                 || g_line_feed;
2842         g_rule_group_by       := g_rule_group_by || ',' || l_order_by_string || g_line_feed;
2843       ELSE
2844         g_rule_select         := g_rule_select || ',NULL order_by_string' || g_line_feed;
2845         g_rule_select_serial  := g_rule_select_serial || ',NULL order_by_string' || g_line_feed;
2846       END IF;
2847     ELSE --order by and consist string only useful in picking
2848       --3/13/02 added for PJM support
2849       -- Add project and task to sort criteria
2850       IF p_type_code = 1 THEN
2851         IF (g_rule_order IS NULL) THEN
2852           -- project and task  are only order by
2853           g_rule_order  :=
2854                      g_rule_order  || g_base_table_alias
2855                                    || '.PROJECT_ID' || g_line_feed
2856                                    || ',' || g_base_table_alias
2857                                    || '.TASK_ID' || g_line_feed;
2858         ELSE
2859           --bug 2983185 - g_rule_order was getting concatenated twice
2860           g_rule_order  :=    g_rule_order
2861                            || ','
2862                            || g_base_table_alias
2863                            || '.PROJECT_ID'
2864                            || g_line_feed
2865                            || ','
2866                            || g_base_table_alias
2867                            || '.TASK_ID'
2868                            || g_line_feed;
2869         END IF;
2870       END IF;
2871 
2872       g_rule_select         := g_rule_select || ',NULL consist_string' || g_line_feed;
2873       g_rule_select_serial  := g_rule_select_serial || ',NULL consist_string' || g_line_feed;
2874       g_rule_select         := g_rule_select || ',NULL order_by_string' || g_line_feed;
2875       g_rule_select_serial  := g_rule_select_serial || ',NULL order_by_string' || g_line_feed;
2876     END IF;
2877 
2878     --
2879     -- Save the pointers, which mark the end of the rule sourced bind variables
2880     --inv_sql_binding_pvt.SaveBindPointers;
2881     --
2882     log_procedure(l_api_name, 'end', 'End BuildRuleSql');
2883   -- end of debugging section
2884   EXCEPTION
2885     WHEN fnd_api.g_exc_error THEN
2886       x_return_status  := fnd_api.g_ret_sts_error;
2887       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
2888       --
2889       log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
2890     --
2891     WHEN fnd_api.g_exc_unexpected_error THEN
2892       x_return_status  := fnd_api.g_ret_sts_unexp_error;
2893       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
2894       --
2895       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
2896 
2897     WHEN OTHERS THEN
2898       IF objects%ISOPEN THEN
2899         CLOSE objects;
2900       END IF;
2901 
2902       IF conditions%ISOPEN THEN
2903         CLOSE conditions;
2904       END IF;
2905 
2906       IF qtyfnct%ISOPEN THEN
2907         CLOSE qtyfnct;
2908       END IF;
2909 
2910       IF RESTRICT%ISOPEN THEN
2911         CLOSE RESTRICT;
2912       END IF;
2913 
2914       IF sortcrit%ISOPEN THEN
2915         CLOSE sortcrit;
2916       END IF;
2917 
2918       x_return_status  := fnd_api.g_ret_sts_unexp_error;
2919 
2920       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2921         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
2922       END IF;
2923 
2924       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
2925       --
2926       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
2927   --
2928   END buildrulesql;
2929 
2930   --
2931   -- Name        : BuildInputSQL
2932   -- Function    : Adds the SQL to the where clause to handle
2933   --     input parameters
2934   -- Notes       : privat procedure for internal use only
2935   --
2936   PROCEDURE buildinputsql(
2937     x_return_status OUT NOCOPY    VARCHAR2
2938   , x_msg_count     OUT NOCOPY    NUMBER
2939   , x_msg_data      OUT NOCOPY    VARCHAR2
2940   , p_type_code     IN            NUMBER
2941   ) IS
2942     -- variables needed for dynamic SQL
2943     l_identifier VARCHAR2(10);
2944     l_api_name   VARCHAR2(30) := 'BuildIputSQL';
2945     l_is_mat_status_used  NUMBER := NVL(FND_PROFILE.VALUE('INV_MATERIAL_STATUS'), 2);
2946   BEGIN
2947     -- Initialize API return status to success
2948     x_return_status  := fnd_api.g_ret_sts_success;
2949 
2950     log_procedure(l_api_name, 'start', 'Start BuildInputSql');
2951     -- end of debugging section
2952     --
2953     --
2954     -- Add type code independent input parameters to where clause
2955     -- Notes: For picking, the sql statement already bound organization_id
2956     -- and inventory_item_id in BuildBaseSQL, so here it is redundant but
2957     -- no harm anyway
2958     g_input_where    := g_base_table_alias || '.ORGANIZATION_ID = ' || 'g_organization_id' || g_line_feed;
2959     g_input_where    := g_input_where || 'and ' || g_base_table_alias || '.INVENTORY_ITEM_ID = ' || 'g_inventory_item_id' || g_line_feed;
2960 
2961     -- the move order line can specify the subinventory, locator, revision,
2962     -- and/or lot number to use for the pick or put away. To allow for a
2963     -- generic sql cursor regardless of input values, we use the decode statments
2964     -- in the where clause.
2965     -- When Rule.Apply is called, it will look at these four input values. For
2966     -- all the input values which are Null, the Apply function will set those
2967     -- values to -9999 (or -99 for Revision). Then inside the cursor in the
2968     -- stored rule function, these decode statements make a check on the value
2969     -- of the inputs.  If the inputs = -9999 or -99 (i.e. Null), the decode
2970     -- statements create a line which always evaluate to true: a=a or 1=1.
2971     -- If the input has a non -9999 value, then that value is compared to the
2972     -- appropriate column.
2973 
2974     -- 2/21/02 - We no longer add subinventory code and locator id to the
2975     -- where clause here. for putaway.
2976     --The decode statements prevent the subinventory/locator indices from
2977     -- being used.  Instead, we add subinventory and locator to the where clause
2978     -- in GenerateRulePackage for cursors that are called only when those
2979     -- values are passed.
2980     IF (p_type_code = 2) THEN --picking only
2981       g_input_where  :=    g_input_where
2982                         || ' and '
2983                         || 'decode(g_subinventory_code, ''-9999'', ''a'', '
2984                         || g_base_table_alias
2985                         || '.SUBINVENTORY_CODE)'
2986                         || ' = '
2987                         || 'decode(g_subinventory_code, ''-9999'', ''a'', g_subinventory_code)'
2988                         || g_line_feed;
2989       --bug #1252345
2990       --if subinventory is null, we have to make sure we don't pick from
2991       --  non-reservable sub
2992       -- # 6917190
2993       -- 7280339 added check for status_id is null
2994       g_input_where  :=    g_input_where
2995                         || ' and '
2996                         || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
2997 			|| ' AND exists(select 1 from mtl_material_statuses where status_id = '
2998 			|| g_base_table_alias
2999 			|| '.STATUS_ID'
3000 			|| ' AND RESERVABLE_TYPE = 1)) OR '
3001 			|| '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3002                         || ' or '
3003 			|| g_base_table_alias
3004 			|| '.STATUS_ID IS NULL)'
3005 			|| ' and '
3006 			|| 'decode(g_subinventory_code, ''-9999'', '
3007                         || g_base_table_alias
3008                         || '.RESERVABLE_TYPE, 1)'
3009                         || ' = 1))'
3010                         || g_line_feed;
3011       g_input_where  :=    g_input_where
3012                         || ' and '
3013                         || 'decode(g_locator_id, -9999, 1, '
3014                         || g_base_table_alias
3015                         || '.locator_id)'
3016                         || ' = '
3017                         || 'decode(g_locator_id,-9999, 1, g_locator_id)'
3018                         || g_line_feed;
3019       -- Bug 6719290, 6917190
3020       IF l_is_mat_status_used = 1 THEN
3021          g_input_where  :=    g_input_where
3022                           || ' and '
3023 			  || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
3024 			  || ' AND exists(select 1 from mtl_material_statuses where status_id = '
3025 			  || g_base_table_alias
3026 			  || '.STATUS_ID'
3027 			  || ' AND RESERVABLE_TYPE = 1)) OR '
3028 			  || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3029 			  || 'or '
3030 			  || g_base_table_alias
3031 			  || '.STATUS_ID IS NULL)'
3032 			  || ' and '
3033                           || 'decode(g_locator_id, -9999, '
3034                           || g_base_table_alias
3035                           || '.locreservable, 1)'
3036                           || ' = 1))'
3037                           || g_line_feed;
3038       END IF ;
3039 
3040     END IF;
3041 
3042      IF (p_type_code = 2) THEN
3043         g_input_where  :=    g_input_where
3044                           || ' and '
3045                           || 'decode(g_revision, ''-99'', ''a'', '
3046                           || g_base_table_alias
3047                           || '.REVISION)'
3048                           || ' = '
3049                           || 'decode(g_revision, ''-99'', ''a'', g_revision)'
3050                           || g_line_feed;
3051         g_input_where  :=    g_input_where
3052                           || ' and '
3053                           || 'decode(g_lot_number, ''-9999'', ''a'', '
3054                           || g_base_table_alias
3055                           || '.LOT_NUMBER)'
3056                           || ' = '
3057                           || 'decode(g_lot_number, ''-9999'', ''a'', g_lot_number)'
3058                           || g_line_feed;
3059        -- Bug 6719290, 6917190
3060       IF l_is_mat_status_used = 1 THEN
3061          g_input_where  :=    g_input_where
3062                             || ' and '
3063 			    || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
3064 			    || ' AND exists(select 1 from mtl_material_statuses where status_id = '
3065 			    || g_base_table_alias
3066 			    || '.STATUS_ID'
3067 			    || ' AND RESERVABLE_TYPE = 1)) OR '
3068 			    || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3069 			    || 'or '
3070                             || g_base_table_alias
3071                             || '.STATUS_ID IS NULL)'
3072 			    || ' and '
3073                             || 'decode(g_lot_number, ''-9999'', '
3074                             || g_base_table_alias
3075                             || '.lotreservable, 1)'
3076                             || ' = 1))'
3077                             || g_line_feed;
3078       END IF ;
3079 
3080         g_input_where  :=    g_input_where
3081                           || ' and '
3082                           || 'decode(g_lpn_id, -9999, 1, '
3083                           || g_base_table_alias
3084                           || '.lpn_id)'
3085                           || ' = '
3086                           || 'decode(g_lpn_id, -9999, 1, g_lpn_id)'
3087                           || g_line_feed;
3088         --cost group doesn't affect finding put away locations,
3089         -- so only check input for pick
3090         g_input_where  :=    g_input_where
3091                           || ' and '
3092                           || 'decode(g_cost_group_id, -9999, 1, '
3093                           || g_base_table_alias
3094                           || '.cost_group_id)'
3095                           || ' = '
3096                           || 'decode(g_cost_group_id, -9999, 1, g_cost_group_id)'
3097                           || g_line_feed;
3098         -- Adding project_id and task_id to support PJM
3099         g_input_where  :=    g_input_where
3100                           || ' and '
3101                           || '(decode(g_project_id, -9999, -1, '
3102                           || g_base_table_alias
3103                           || '.project_id)'
3104                           || ' = '
3105                           || 'decode(g_project_id, -9999, -1, g_project_id)'
3106                           || ' OR '
3107                           || '( g_project_id = -7777 '
3108                           || ' and '
3109                           || g_base_table_alias
3110                           || '.project_id IS NULL)) '
3111                           || g_line_feed;
3112         -- If Allow Cross Project Pick is set to NO then task must be exactly equal even if NULL
3113         g_input_where  :=    g_input_where
3114                           || ' and '
3115                           || '(g_project_id = -9999'
3116                           || ' OR '
3117                           || 'nvl('
3118                           || g_base_table_alias
3119                           || '.task_id, -9999)'
3120                           || ' = '
3121                           || 'g_task_id'
3122                           || ' OR '
3123                           || '(g_task_id = -7777'
3124                           || ' and '
3125                           || g_base_table_alias
3126                           || '.task_id IS NULL))'
3127                           || g_line_feed;
3128     END IF;
3129 
3130     IF (p_type_code = 1) THEN
3131       -- Adding project_id and task_id to support PJM
3132       g_input_where  :=    g_input_where
3133                         || ' and ('
3134                         || 'g_project_id = '
3135                         || g_base_table_alias
3136                         || '.project_id OR '
3137                         || g_base_table_alias
3138                         || '.project_id IS NULL)'
3139                         || g_line_feed;
3140       g_input_where  :=    g_input_where
3141                         || ' and ('
3142                         || 'g_task_id = '
3143                         || g_base_table_alias
3144                         || '.task_id OR '
3145                         || g_base_table_alias
3146                         || '.task_id IS NULL)'
3147                         || g_line_feed;
3148     END IF;
3149 
3150     -- always join to the input table
3151     g_input_where    :=
3152                       g_input_where || ' and ' || g_input_table_alias || '.PP_TRANSACTION_TEMP_ID = ' || 'g_pp_transaction_temp_id' || g_line_feed;
3153 
3154     -- end of debugging section
3155     log_procedure(l_api_name, 'end', 'End BuildInputSql');
3156   --
3157   EXCEPTION
3158     WHEN OTHERS THEN
3159       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3160 
3161       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3162         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3163       END IF;
3164 
3165       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3166       --
3167       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3168   --
3169   END buildinputsql;
3170 
3171   FUNCTION isruledebugon(p_simulation_mode IN NUMBER)
3172     RETURN BOOLEAN IS
3173     l_return_value BOOLEAN;
3174     l_debug NUMBER;
3175   BEGIN
3176    IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3177       g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3178    END IF;
3179     l_debug := g_debug;
3180     IF p_simulation_mode <> wms_engine_pvt.g_no_simulation THEN
3181       l_return_value  := TRUE;
3182     ELSIF  p_simulation_mode = wms_engine_pvt.g_no_simulation THEN
3183       if l_debug = 1 THEN
3184          l_return_value  := TRUE;
3185       ELSE
3186          l_return_value  := FALSE;
3187       END IF;
3188     ELSE
3189       null;
3190       --l_return_value  := fnd_log.test(log_level => fnd_log.level_unexpected, module => 'wms.plsql.' || g_pkg_name || '.' || 'Apply.test');
3191     END IF;
3192 
3193     IF l_return_value THEN
3194       if l_debug = 1 THEN
3195        log_statement('IsRuleDebugOn', 'true', 'Debug is on');
3196       END IF;
3197     ELSE
3198       IF l_debug = 1 THEN
3199          log_statement('IsRuleDebugOn', 'false', 'Debug is off');
3200       END IF;
3201     END IF;
3202 
3203     RETURN l_return_value;
3204   END isruledebugon;
3205 
3206   --
3207   -- Name        : FetchCursor
3208   -- Function    : Fetches one record at a time from the Rule's
3209   --     SQL statement, using the rule API
3210   -- Pre-reqs    : cursor has to be parsed and executed already.
3211   -- Notes       : private procedure for internal use only
3212   --
3213   PROCEDURE fetchcursor(
3214     x_return_status       OUT NOCOPY    VARCHAR2
3215   , x_msg_count           OUT NOCOPY    NUMBER
3216   , x_msg_data            OUT NOCOPY    VARCHAR2
3217   , p_cursor              IN            wms_rule_pvt.cv_pick_type
3218   , p_rule_id             IN            NUMBER
3219   , x_revision            OUT NOCOPY    VARCHAR2
3220   , x_lot_number          OUT NOCOPY    VARCHAR2
3221   , x_lot_expiration_date OUT NOCOPY    DATE
3222   , x_subinventory_code   OUT NOCOPY    VARCHAR2
3223   , x_locator_id          OUT NOCOPY    NUMBER
3224   , x_cost_group_id       OUT NOCOPY    NUMBER
3225   , x_uom_code            OUT NOCOPY    VARCHAR2
3226   , x_lpn_id              OUT NOCOPY    NUMBER
3227   , x_serial_number       OUT NOCOPY    VARCHAR2
3228   , x_possible_quantity   OUT NOCOPY    NUMBER
3229   , x_sec_possible_quantity  OUT NOCOPY NUMBER
3230   , x_grade_code             OUT NOCOPY VARCHAR2
3231   , x_consist_string      OUT NOCOPY    VARCHAR2
3232   , x_order_by_string     OUT NOCOPY    VARCHAR2
3233   , x_rows                OUT NOCOPY    NUMBER
3234   ) IS
3235     invalid_pkg_state  exception;
3236     Pragma Exception_Init(invalid_pkg_state, -6508);
3237 
3238     l_list_pkg     VARCHAR2(30);
3239 
3240     l_api_name     VARCHAR2(30)  := 'FetchCursor';
3241     l_rows         NUMBER;
3242     l_func_sql     VARCHAR(1000);
3243     l_cursor       NUMBER;
3244     l_dummy        NUMBER;
3245     l_package_name VARCHAR2(128);
3246     l_ctr          NUMBER        := 0;
3247 
3248     l_debug        NUMBER;
3249 
3250   BEGIN
3251     -- Initialize API return status to success
3252     x_return_status  := fnd_api.g_ret_sts_success;
3253     --get package name based on rule id
3254     getpackagename(p_rule_id, l_package_name);
3255     --- calling the static fetch cursor. The name of the rule package will be
3256     --- determined based on the rule_id
3257     --- If the ctr is 1 then there is no subscript ,
3258     --- if ctr = 2 then subscript = 1
3259     --- and if ctr = 3 then subscript = 2, this script is added to the package
3260     --- name.
3261 
3262 
3263     l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
3264     l_list_pkg   :=  'wms_rule_pick_pkg' || l_ctr ;
3265 
3266     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3267       g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3268     END IF;
3269     l_debug := g_debug;
3270 
3271     IF l_debug = 1  THEN
3272        log_procedure(l_api_name, 'start', 'Start FetchCursor');
3273     END IF;
3274 
3275     IF (l_ctr = 1) THEN
3276 
3277       wms_rule_pick_pkg1.execute_fetch_rule(
3278         p_cursor
3279       , p_rule_id
3280       , x_revision
3281       , x_lot_number
3282       , x_lot_expiration_date
3283       , x_subinventory_code
3284       , x_locator_id
3285       , x_cost_group_id
3286       , x_uom_code
3287       , x_lpn_id
3288       , x_serial_number
3289       , x_possible_quantity
3290       , x_sec_possible_quantity
3291       , x_grade_code
3292       , x_consist_string
3293       , x_order_by_string
3294       , x_rows
3295       );
3296     ELSIF (l_ctr = 2) THEN
3297 
3298       wms_rule_pick_pkg2.execute_fetch_rule(
3299         p_cursor
3300       , p_rule_id
3301       , x_revision
3302       , x_lot_number
3303       , x_lot_expiration_date
3304       , x_subinventory_code
3305       , x_locator_id
3306       , x_cost_group_id
3307       , x_uom_code
3308       , x_lpn_id
3309       , x_serial_number
3310       , x_possible_quantity
3311       , x_sec_possible_quantity
3312       , x_grade_code
3313       , x_consist_string
3314       , x_order_by_string
3315       , x_rows
3316       );
3317     ELSIF (l_ctr = 3) THEN
3318       wms_rule_pick_pkg3.execute_fetch_rule(
3319         p_cursor
3320       , p_rule_id
3321       , x_revision
3322       , x_lot_number
3323       , x_lot_expiration_date
3324       , x_subinventory_code
3325       , x_locator_id
3326       , x_cost_group_id
3327       , x_uom_code
3328       , x_lpn_id
3329       , x_serial_number
3330       , x_possible_quantity
3331       , x_sec_possible_quantity
3332       , x_grade_code
3333       , x_consist_string
3334       , x_order_by_string
3335       , x_rows
3336       );
3337     END IF;
3338 
3339     l_rows           := x_rows;
3340 
3341     IF l_rows = 0 THEN --no row found
3342       x_revision             := NULL;
3343       x_lot_number           := NULL;
3344       x_lot_expiration_date  := NULL;
3345       x_subinventory_code    := NULL;
3346       x_locator_id           := NULL;
3347       x_cost_group_id        := NULL;
3348       x_uom_code             := NULL;
3349       x_lpn_id               := NULL;
3350       x_serial_number        := NULL;
3351       x_possible_quantity    := 0;
3352       x_consist_string       := NULL;
3353       x_order_by_string      := NULL;
3354 
3355 
3356       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PICK_NO_ROWS'  ;
3357 
3358       IF l_debug = 1 THEN
3359          log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || p_rule_id);
3360 	 log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
3361        END IF;
3362 
3363     END IF;
3364 
3365     x_rows := l_rows;
3366     --
3367 
3368     IF l_debug = 1 THEN
3369          log_procedure(l_api_name, 'end', 'End FetchCursor');
3370     END IF;
3371   --
3372   EXCEPTION
3373     WHEN INVALID_PKG_STATE THEN
3374       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3375 
3376       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3377       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3378       fnd_message.set_token('RULE_NAME', l_package_name);
3379       fnd_msg_pub.ADD;
3380       IF l_debug = 1 THEN
3381          log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
3382                             || l_list_pkg || ' / ' || l_package_name);
3383       END IF;
3384       RAISE fnd_api.g_exc_unexpected_error;
3385 
3386     WHEN OTHERS THEN
3387       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3388 
3389       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3390         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3391       END IF;
3392 
3393       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3394       IF l_debug = 1 THEN
3395          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3396       END IF;
3397       RAISE fnd_api.g_exc_unexpected_error;
3398   END fetchcursor;
3399 
3400   --
3401   -- Name        : FetchPutAway
3402   -- Function    : Fetches one record at a time from the Rule's
3403   --     SQL statement, using the rule API. Called from putaway
3404   -- Pre-reqs    : cursor has to be parsed and executed already.
3405   -- Notes       : private procedure for internal use only
3406   --
3407   PROCEDURE fetchputaway(
3408     x_return_status     OUT NOCOPY    VARCHAR2
3409   , x_msg_count         OUT NOCOPY    NUMBER
3410   , x_msg_data          OUT NOCOPY    VARCHAR2
3411   , p_cursor            IN            wms_rule_pvt.cv_put_type
3412   , p_rule_id           IN            NUMBER
3413   , x_subinventory_code OUT NOCOPY    VARCHAR2
3414   , x_locator_id        OUT NOCOPY    NUMBER
3415   , x_project_id        OUT NOCOPY    NUMBER
3416   , x_task_id           OUT NOCOPY    NUMBER
3417   , x_rows              OUT NOCOPY    NUMBER
3418   ) IS
3419     invalid_pkg_state  exception;
3420     Pragma Exception_Init(invalid_pkg_state, -6508);
3421 
3422     l_list_pkg     VARCHAR2(30);
3423 
3424     l_api_name     VARCHAR2(30)  := 'FetchPutaway';
3425     l_rows         NUMBER;
3426     l_func_sql     VARCHAR(1000);
3427     l_cursor       NUMBER;
3428     l_dummy        NUMBER;
3429     l_package_name VARCHAR2(128);
3430     l_ctr          NUMBER        := 0;
3431 
3432     l_debug        NUMBER;
3433 
3434 
3435   BEGIN
3436     -- Initialize API return status to success
3437     x_return_status  := fnd_api.g_ret_sts_success;
3438 
3439    IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3440       g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3441    END IF;
3442    l_debug := g_debug;
3443 
3444    IF l_debug = 1 THEN
3445       log_procedure(l_api_name, 'start', 'Start FetchPutaway');
3446       log_procedure(l_api_name, 'start', 'Putaway rule id '||p_rule_id);
3447    END IF;
3448 
3449     --get package name based on rule id
3450     getpackagename(p_rule_id, l_package_name);
3451     l_ctr            := wms_rule_pvt.g_rule_list_put_ctr;
3452     l_list_pkg :=  'wms_rule_put_pkg' || l_ctr ;
3453 
3454     IF (l_ctr = 1) THEN
3455       wms_rule_put_pkg1.execute_fetch_rule
3456                     (p_cursor
3457                     , p_rule_id
3458                     , x_subinventory_code
3459                     , x_locator_id
3460                     , x_project_id
3461                     , x_task_id
3462                     , x_rows);
3463     ELSIF (l_ctr = 2) THEN
3464       wms_rule_put_pkg2.execute_fetch_rule
3465                     (p_cursor
3466                     , p_rule_id
3467                     , x_subinventory_code
3468                     , x_locator_id
3469                     , x_project_id
3470                     , x_task_id
3471                     , x_rows);
3472     ELSIF (l_ctr = 3) THEN
3473       wms_rule_put_pkg3.execute_fetch_rule
3474                     (p_cursor
3475                     , p_rule_id
3476                     , x_subinventory_code
3477                     , x_locator_id
3478                     , x_project_id
3479                     , x_task_id
3480                     , x_rows);
3481     END IF;
3482 
3483     --------
3484     --l_rows           := x_rows;
3485     IF l_debug = 1 THEN
3486        log_event(l_api_name, '*************************', '');
3487        log_event(l_api_name, 'x_subinventory_code', x_subinventory_code);
3488        log_event(l_api_name, 'x_locator_id', x_locator_id);
3489      END IF;
3490 
3491 
3492     IF  l_rows  = 0 THEN --no row found
3493       x_subinventory_code  := NULL;
3494       x_locator_id         := NULL;
3495       x_project_id         := NULL;
3496       x_task_id            := NULL;
3497 
3498       -- Bug # 3185073
3499       --WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
3500 
3501       IF l_debug = 1 THEN
3502          log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || p_rule_id);
3503       END IF;
3504 
3505       IF ( WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE = 'WMS_PICK_NO_ROWS' or
3506            WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE = NULL) then
3507 
3508            WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
3509       END IF;
3510 
3511        IF l_debug = 1 THEN
3512           log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
3513        END IF;
3514 
3515     END IF;
3516     --x_rows           := l_rows;
3517           IF l_debug = 1 THEN
3518              log_statement(l_api_name, 'put_sub',
3519                 'Subinventory: ' || x_subinventory_code);
3520              log_statement(l_api_name, 'put_loc',
3521                 'Locator: ' || x_locator_id);
3522              log_statement(l_api_name, 'put_proj',
3523                 'Project: ' || x_project_id);
3524              log_statement(l_api_name, 'put_task',
3525                 'Task: ' || x_task_id);
3526              log_statement(l_api_name, 'rows',
3527                 'Rows Returned: ' || x_rows);
3528           END IF;
3529 
3530     IF l_debug = 1 THEN
3531        log_procedure(l_api_name, 'end', 'End FetchPutaway');
3532     END IF;
3533   --
3534   EXCEPTION
3535     WHEN INVALID_PKG_STATE THEN
3536       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3537       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3538       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3539       fnd_message.set_token('RULE_NAME', l_package_name);
3540       fnd_msg_pub.ADD;
3541 
3542       IF l_debug = 1 THEN
3543          log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
3544                             || l_list_pkg || ' / ' || l_package_name);
3545       END IF;
3546       RAISE fnd_api.g_exc_unexpected_error;
3547     WHEN OTHERS THEN
3548       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3549 
3550       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3551         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3552       END IF;
3553 
3554       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3555       IF l_debug = 1 THEN
3556          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3557       END IF;
3558       RAISE fnd_api.g_exc_unexpected_error;
3559   END fetchputaway;
3560 
3561   ------------
3562   ---
3563   ---  Procedures to handle the static calls to open, fetch and close cursor
3564   ---  based on the Rule_id. The name of the API_call is decided based on the the
3565   ---  flag retrived from the table.
3566   ---
3567   --- For Pick rules
3568 
3569   PROCEDURE pick_open_rule(
3570     p_cursor                 IN OUT NOCOPY wms_rule_pvt.cv_pick_type
3571   , p_rule_id                IN            NUMBER
3572   , p_organization_id        IN            NUMBER
3573   , p_inventory_item_id      IN            NUMBER
3574   , p_transaction_type_id    IN            NUMBER
3575   , p_revision               IN            VARCHAR2
3576   , p_lot_number             IN            VARCHAR2
3577   , p_subinventory_code      IN            VARCHAR2
3578   , p_locator_id             IN            NUMBER
3579   , p_cost_group_id          IN            NUMBER
3580   , p_pp_transaction_temp_id IN            NUMBER
3581   , p_serial_controlled      IN            NUMBER
3582   , p_detail_serial          IN            NUMBER
3583   , p_detail_any_serial      IN            NUMBER
3584   , p_from_serial_number     IN            VARCHAR2
3585   , p_to_serial_number       IN            VARCHAR2
3586   , p_unit_number            IN            VARCHAR2
3587   , p_lpn_id                 IN            NUMBER
3588   , p_project_id             IN            NUMBER
3589   , p_task_id                IN            NUMBER
3590   , x_result                 OUT NOCOPY    NUMBER
3591   ) IS
3592 
3593     invalid_pkg_state  exception;
3594     Pragma Exception_Init(invalid_pkg_state, -6508);
3595     l_msg_data      VARCHAR2(240);
3596     l_msg_count     NUMBER;
3597     l_api_name      VARCHAR2(30);
3598 
3599     l_list_pkg     VARCHAR2(30);
3600     l_package_name VARCHAR2(128);
3601     l_ctr NUMBER := 0;
3602 
3603     l_debug        NUMBER;
3604 
3605   BEGIN
3606 
3607     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3608        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3609     END IF;
3610     l_debug := g_debug;
3611 
3612     IF wms_rule_pvt.g_rule_list_pick_ctr IS NULL THEN
3613        wms_rule_pvt.g_rule_list_pick_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('PICK');
3614     END IF;
3615     l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
3616 
3617     l_list_pkg :=  'wms_rule_pick_pkg' || l_ctr ;
3618     getpackagename(p_rule_id, l_package_name);
3619 
3620     IF (l_ctr = 1) THEN
3621 
3622          IF l_debug = 1 THEN
3623             log_statement(l_api_name, ' wms_rule_pick_pkg1.execute_open_rule', l_ctr);
3624          END IF;
3625       wms_rule_pick_pkg1.execute_open_rule(
3626         p_cursor
3627       , p_rule_id
3628       , p_organization_id
3629       , p_inventory_item_id
3630       , p_transaction_type_id
3631       , p_revision
3632       , p_lot_number
3633       , p_subinventory_code
3634       , p_locator_id
3635       , p_cost_group_id
3636       , p_pp_transaction_temp_id
3637       , p_serial_controlled
3638       , p_detail_serial
3639       , p_detail_any_serial
3640       , p_from_serial_number
3641       , p_to_serial_number
3642       , p_unit_number
3643       , p_lpn_id
3644       , p_project_id
3645       , p_task_id
3646       , x_result
3647       );
3648     ELSIF (l_ctr = 2) THEN
3649 
3650         IF l_debug = 1 THEN
3651            log_statement(l_api_name, ' wms_rule_pick_pkg2.execute_open_rule', l_ctr);
3652         END IF;
3653 
3654       wms_rule_pick_pkg2.execute_open_rule(
3655         p_cursor
3656       , p_rule_id
3657       , p_organization_id
3658       , p_inventory_item_id
3659       , p_transaction_type_id
3660       , p_revision
3661       , p_lot_number
3662       , p_subinventory_code
3663       , p_locator_id
3664       , p_cost_group_id
3665       , p_pp_transaction_temp_id
3666       , p_serial_controlled
3667       , p_detail_serial
3668       , p_detail_any_serial
3669       , p_from_serial_number
3670       , p_to_serial_number
3671       , p_unit_number
3672       , p_lpn_id
3673       , p_project_id
3674       , p_task_id
3675       , x_result
3676       );
3677     ELSIF (l_ctr = 3) THEN
3678        IF l_debug = 1 THEN
3679           log_statement(l_api_name, ' wms_rule_pick_pkg3.execute_open_rule', l_ctr);
3680        END IF;
3681 
3682       wms_rule_pick_pkg3.execute_open_rule(
3683         p_cursor
3684       , p_rule_id
3685       , p_organization_id
3686       , p_inventory_item_id
3687       , p_transaction_type_id
3688       , p_revision
3689       , p_lot_number
3690       , p_subinventory_code
3691       , p_locator_id
3692       , p_cost_group_id
3693       , p_pp_transaction_temp_id
3694       , p_serial_controlled
3695       , p_detail_serial
3696       , p_detail_any_serial
3697       , p_from_serial_number
3698       , p_to_serial_number
3699       , p_unit_number
3700       , p_lpn_id
3701       , p_project_id
3702       , p_task_id
3703       , x_result
3704       );
3705     END IF;
3706 
3707   EXCEPTION
3708     WHEN INVALID_PKG_STATE THEN
3709       x_result := 0;
3710       wms_rule_pvt.g_rule_list_pick_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('PICK');
3711 
3712       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3713       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3714       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3715       fnd_message.set_token('RULE_NAME', l_package_name);
3716       fnd_msg_pub.ADD;
3717 
3718       IF l_debug = 1 THEN
3719          log_error(l_api_name, 'execute_open_rule', 'Invalid Package, Contact your DBA - '
3720                             || l_list_pkg || ' / ' || l_package_name);
3721 
3722       END IF;
3723   END pick_open_rule;
3724 
3725   ---
3726   ---  Procedure Fetchcursor() is modified to handle static call to fetch a row from the
3727   ---  opened picking cursor
3728 
3729   ----------------
3730 
3731   PROCEDURE put_open_rule(
3732     p_cursor                 IN OUT NOCOPY wms_rule_pvt.cv_put_type
3733   , p_rule_id                IN            NUMBER
3734   , p_organization_id        IN            NUMBER
3735   , p_inventory_item_id      IN            NUMBER
3736   , p_transaction_type_id    IN            NUMBER
3737   , p_subinventory_code      IN            VARCHAR2
3738   , p_locator_id             IN            NUMBER
3739   , p_pp_transaction_temp_id IN            NUMBER
3740   , p_restrict_subs_code     IN            NUMBER
3741   , p_restrict_locs_code     IN            NUMBER
3742   , p_project_id             IN            NUMBER
3743   , p_task_id                IN            NUMBER
3744   , x_result                 OUT NOCOPY    NUMBER
3745   ) IS
3746 
3747     invalid_pkg_state  exception;
3748     Pragma Exception_Init(invalid_pkg_state, -6508);
3749     l_msg_data      VARCHAR2(240);
3750     l_msg_count     NUMBER;
3751     l_api_name      VARCHAR2(30);
3752 
3753     l_list_pkg     VARCHAR2(30);
3754     l_package_name VARCHAR2(128);
3755     l_ctr NUMBER := 0;
3756 
3757     l_debug       NUMBER;
3758 
3759   BEGIN
3760 
3761     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3762            g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3763     END IF;
3764     l_debug := g_debug;
3765 
3766     if wms_rule_pvt.g_rule_list_put_ctr is null then
3767        wms_rule_pvt.g_rule_list_put_ctr  :=  wms_rule_gen_pkgs.get_count_no_lock('PUTAWAY');
3768     end if;
3769     l_ctr := wms_rule_pvt.g_rule_list_put_ctr;
3770 
3771     l_list_pkg :=  'wms_rule_put_pkg' || l_ctr ;
3772     getpackagename(p_rule_id, l_package_name);
3773 
3774     IF (l_ctr = 1) THEN
3775       wms_rule_put_pkg1.execute_open_rule(
3776         p_cursor
3777       , p_rule_id
3778       , p_organization_id
3779       , p_inventory_item_id
3780       , p_transaction_type_id
3781       , p_subinventory_code
3782       , p_locator_id
3783       , p_pp_transaction_temp_id
3784       , p_restrict_subs_code
3785       , p_restrict_locs_code
3786       , p_project_id
3787       , p_task_id
3788       , x_result
3789       );
3790     ELSIF (l_ctr = 2) THEN
3791       wms_rule_put_pkg2.execute_open_rule(
3792         p_cursor
3793       , p_rule_id
3794       , p_organization_id
3795       , p_inventory_item_id
3796       , p_transaction_type_id
3797       , p_subinventory_code
3798       , p_locator_id
3799       , p_pp_transaction_temp_id
3800       , p_restrict_subs_code
3801       , p_restrict_locs_code
3802       , p_project_id
3803       , p_task_id
3804       , x_result
3805       );
3806     ELSIF (l_ctr = 3) THEN
3807       wms_rule_put_pkg3.execute_open_rule(
3808         p_cursor
3809       , p_rule_id
3810       , p_organization_id
3811       , p_inventory_item_id
3812       , p_transaction_type_id
3813       , p_subinventory_code
3814       , p_locator_id
3815       , p_pp_transaction_temp_id
3816       , p_restrict_subs_code
3817       , p_restrict_locs_code
3818       , p_project_id
3819       , p_task_id
3820       , x_result
3821       );
3822     END IF;
3823 
3824   EXCEPTION
3825     WHEN INVALID_PKG_STATE THEN
3826       x_result := 0;
3827       wms_rule_pvt.g_rule_list_put_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('PUTAWAY');
3828 
3829       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3830       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3831       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3832       fnd_message.set_token('RULE_NAME', l_package_name);
3833       fnd_msg_pub.ADD;
3834 
3835       IF l_debug = 1 THEN
3836          log_error(l_api_name, 'execute_open_rule', 'Invalid Package, Contact your DBA - '
3837                             || l_list_pkg || ' / ' || l_package_name);
3838       END IF;
3839   END put_open_rule;
3840 
3841   -----------------
3842   ---  Procedure FetchPutaway() is modified to handle static call to fetch a row from the
3843   ---  opened Putaway cursor
3844 
3845   PROCEDURE execute_op_rule(p_rule_id IN NUMBER, p_task_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
3846 
3847     invalid_pkg_state  exception;
3848     Pragma Exception_Init(invalid_pkg_state, -6508);
3849     l_msg_data      VARCHAR2(240);
3850     l_msg_count     NUMBER;
3851     l_api_name      VARCHAR2(30);
3852     l_list_pkg      VARCHAR2(30);
3853     l_package_name  VARCHAR2(128);
3854     l_ctr 	    NUMBER := 0;
3855 
3856   BEGIN
3857     if wms_rule_pvt.g_rule_list_op_ctr is null then
3858        wms_rule_pvt.g_rule_list_op_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('OPERATION_PLAN');
3859     end if;
3860     l_ctr := wms_rule_pvt.g_rule_list_op_ctr;
3861 
3862     l_list_pkg :=  'wms_rule_op_pkg' || l_ctr ;
3863     getpackagename(p_rule_id, l_package_name);
3864 
3865     IF (l_ctr = 1) THEN
3866       wms_rule_op_pkg1.execute_op_rule(p_rule_id, p_task_id, x_return_status);
3867     ELSIF (l_ctr = 2) THEN
3868       wms_rule_op_pkg2.execute_op_rule(p_rule_id, p_task_id, x_return_status);
3869     ELSIF (l_ctr = 3) THEN
3870       wms_rule_op_pkg3.execute_op_rule(p_rule_id, p_task_id, x_return_status);
3871     END IF;
3872     IF x_return_status  IS NULL THEN
3873            x_return_status := 1;
3874     END IF;
3875   EXCEPTION
3876     WHEN INVALID_PKG_STATE THEN
3877        --x_return_status := 0;
3878        x_return_status := -1 ;
3879       wms_rule_pvt.g_rule_list_op_ctr :=   wms_rule_gen_pkgs.get_count_no_lock('OPERATION_PLAN');
3880       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3881       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3882       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3883       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3884       fnd_message.set_token('RULE_NAME', l_package_name);
3885       fnd_msg_pub.ADD;
3886       /*log_error(l_api_name, 'execute_op_rule', 'Invalid Package, Contact your DBA - '
3887                             || l_list_pkg || ' / ' || l_package_name); */
3888   END execute_op_rule;
3889 
3890   ----- Open cursor and fetch cursor for task rules
3891 
3892   PROCEDURE execute_task_rule(p_rule_id IN NUMBER, p_task_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
3893 
3894     invalid_pkg_state  exception;
3895     Pragma Exception_Init(invalid_pkg_state, -6508);
3896     l_msg_data      VARCHAR2(240);
3897     l_msg_count     NUMBER;
3898     l_api_name      VARCHAR2(30);
3899 
3900     l_list_pkg     VARCHAR2(30);
3901     l_package_name VARCHAR2(128);
3902 
3903     l_ctr NUMBER := 0;
3904 
3905 
3906   BEGIN
3907      if wms_rule_pvt.g_rule_list_task_ctr is null then
3908         wms_rule_pvt.g_rule_list_task_ctr :=   wms_rule_gen_pkgs.get_count_no_lock('TASK');
3909      end if;
3910      l_ctr := wms_rule_pvt.g_rule_list_task_ctr;
3911 
3912     l_list_pkg :=  'wms_rule_task_pkg' || l_ctr ;
3913     getpackagename(p_rule_id, l_package_name);
3914 
3915     IF (l_ctr = 1) THEN
3916       wms_rule_task_pkg1.execute_task_rule(p_rule_id, p_task_id, x_return_status);
3917     ELSIF (l_ctr = 2) THEN
3918       wms_rule_task_pkg2.execute_task_rule(p_rule_id, p_task_id, x_return_status);
3919     ELSIF (l_ctr = 3) THEN
3920       wms_rule_task_pkg3.execute_task_rule(p_rule_id, p_task_id, x_return_status);
3921     END IF;
3922     IF x_return_status  IS NULL THEN
3923        x_return_status := 1;
3924     END IF;
3925   EXCEPTION
3926     WHEN INVALID_PKG_STATE THEN
3927       --x_return_status := 0;
3928       x_return_status := -1 ;
3929       wms_rule_pvt.g_rule_list_task_ctr :=   wms_rule_gen_pkgs.get_count_no_lock('TASK');
3930       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3931       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3932       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3933       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3934       fnd_message.set_token('RULE_NAME', l_package_name);
3935       fnd_msg_pub.ADD;
3936       /*log_error(l_api_name, 'execute_task_rule', 'Invalid Package, Contact your DBA - '
3937                             || l_list_pkg || ' / ' || l_package_name); */
3938 
3939   END execute_task_rule;
3940 
3941   ---
3942 
3943   ----- Open cursor and fetch cursor for task rules
3944 
3945   PROCEDURE execute_label_rule(p_rule_id IN NUMBER, p_label_request_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
3946 
3947     invalid_pkg_state  exception;
3948     Pragma Exception_Init(invalid_pkg_state, -6508);
3949     l_msg_data      VARCHAR2(240);
3950     l_msg_count     NUMBER;
3951     l_api_name      VARCHAR2(30);
3952 
3953     l_list_pkg     VARCHAR2(30);
3954     l_package_name VARCHAR2(128);
3955     l_ctr NUMBER := 0;
3956 
3957   BEGIN
3958 
3959     if wms_rule_pvt.g_rule_list_label_ctr is null then
3960        wms_rule_pvt.g_rule_list_label_ctr := wms_rule_gen_pkgs.get_count_no_lock('LABEL');
3961     end if;
3962     l_ctr := wms_rule_pvt.g_rule_list_label_ctr;
3963 
3964     l_list_pkg :=  'wms_rule_label_pkg' || l_ctr ;
3965     getpackagename(p_rule_id, l_package_name);
3966 
3967     IF (l_ctr = 1) THEN
3968       wms_rule_label_pkg1.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
3969     ELSIF (l_ctr = 2) THEN
3970       wms_rule_label_pkg2.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
3971     ELSIF (l_ctr = 3) THEN
3972       wms_rule_label_pkg3.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
3973     END IF;
3974 
3975     IF x_return_status  IS NULL THEN
3976            x_return_status := 1;
3977     END IF;
3978   EXCEPTION
3979     WHEN INVALID_PKG_STATE THEN
3980       --x_return_status := 0;
3981       x_return_status := -1 ;
3982       wms_rule_pvt.g_rule_list_label_ctr := wms_rule_gen_pkgs.get_count_no_lock('LABEL');
3983       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3984       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3985       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3986       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3987       fnd_message.set_token('RULE_NAME', l_package_name);
3988       fnd_msg_pub.ADD;
3989       /*log_error(l_api_name, 'execute_label_rule', 'Invalid Package, Contact your DBA - '
3990                             || l_list_pkg || ' / ' || l_package_name); */
3991 
3992   END execute_label_rule;
3993 
3994   ---  Procedure to Close Pick rule Cursor --
3995   ---
3996 
3997   PROCEDURE close_pick_rule(p_rule_id IN NUMBER, p_cursor IN OUT NOCOPY wms_rule_pvt.cv_pick_type) IS
3998 
3999     invalid_pkg_state  exception;
4000     Pragma Exception_Init(invalid_pkg_state, -6508);
4001     l_msg_data      VARCHAR2(240);
4002     l_msg_count     NUMBER;
4003     l_api_name      VARCHAR2(30);
4004 
4005     l_list_pkg     VARCHAR2(30);
4006     l_package_name VARCHAR2(128);
4007 
4008     l_ctr NUMBER := 0;
4009 
4010   BEGIN
4011 
4012     l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
4013     l_list_pkg :=  'wms_rule_pick_pkg' || l_ctr ;
4014     getpackagename(p_rule_id, l_package_name);
4015 
4016     IF (l_ctr = 1) THEN
4017       wms_rule_pick_pkg1.execute_close_rule(p_rule_id, p_cursor);
4018     ELSIF (l_ctr = 2) THEN
4019       wms_rule_pick_pkg2.execute_close_rule(p_rule_id, p_cursor);
4020     ELSIF (l_ctr = 3) THEN
4021       wms_rule_pick_pkg3.execute_close_rule(p_rule_id, p_cursor);
4022     END IF;
4023 
4024   EXCEPTION
4025     WHEN INVALID_PKG_STATE THEN
4026     /* -- WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4027       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4028       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4029       fnd_message.set_token('RULE_NAME', l_package_name);
4030       fnd_msg_pub.ADD;
4031       log_error(l_api_name, 'execute_close_rule', 'Invalid Package, Contact your DBA - '
4032                             || l_list_pkg || ' / ' || l_package_name); */
4033        RAISE fnd_api.g_exc_unexpected_error;
4034   END close_pick_rule;
4035 
4036   -- Procedure to close Putaway rule Cursor ---
4037   --
4038   PROCEDURE close_put_rule(p_rule_id IN NUMBER, p_cursor IN OUT NOCOPY wms_rule_pvt.cv_put_type) IS
4039 
4040     invalid_pkg_state  exception;
4041     Pragma Exception_Init(invalid_pkg_state, -6508);
4042     l_msg_data      VARCHAR2(240);
4043     l_msg_count     NUMBER;
4044     l_api_name      VARCHAR2(30);
4045     l_list_pkg     VARCHAR2(30);
4046     l_package_name VARCHAR2(128);
4047     l_ctr NUMBER := 0;
4048   BEGIN
4049     l_ctr := wms_rule_pvt.g_rule_list_put_ctr;
4050     l_list_pkg :=  'wms_rule_put_pkg' || l_ctr ;
4051     getpackagename(p_rule_id, l_package_name);
4052 
4053     IF (l_ctr = 1) THEN
4054       wms_rule_put_pkg1.execute_close_rule(p_rule_id, p_cursor);
4055     ELSIF (l_ctr = 2) THEN
4056       wms_rule_put_pkg2.execute_close_rule(p_rule_id, p_cursor);
4057     ELSIF (l_ctr = 3) THEN
4058       wms_rule_put_pkg3.execute_close_rule(p_rule_id, p_cursor);
4059     END IF;
4060 
4061   EXCEPTION
4062     WHEN INVALID_PKG_STATE THEN
4063      /*WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4064       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4065       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4066       fnd_message.set_token('RULE_NAME', l_package_name);
4067       fnd_msg_pub.ADD;
4068       log_error(l_api_name, 'execute_close_rule', 'Invalid Package, Contact your DBA - '
4069                             || l_list_pkg || ' / ' || l_package_name);*/
4070       RAISE fnd_api.g_exc_unexpected_error;
4071   END close_put_rule;
4072 
4073   --------------
4074   --
4075   -- Name        : Rollback_Capacity_Update
4076   -- Function    : Used in Apply for Put Away rules.
4077   --     In Apply, the update_loc_suggested_capacity procedure gets
4078   --     called to update the capacity for a locator.  This
4079   --     procedure is an autonomous transaction, so it issues
4080   --     a commit.  If some sort of error occurs in Apply, we need to
4081   --     undo those changes.  We call revert_loc_suggested_capacity
4082   --     to decrement the suggested capacity field.  The procedure
4083   --     is also a autonomous transaction
4084   -- Pre-reqs    : cursor has to be parsed and executed already.
4085   -- Notes       : private procedure for internal use only
4086   --
4087   PROCEDURE rollback_capacity_update(
4088     x_return_status     OUT NOCOPY    VARCHAR2
4089   , x_msg_count         OUT NOCOPY    NUMBER
4090   , x_msg_data          OUT NOCOPY    VARCHAR2
4091   , p_organization_id   IN            NUMBER
4092   , p_inventory_item_id IN            NUMBER
4093   ) IS
4094     l_return_status VARCHAR2(1);
4095     l_msg_data      VARCHAR2(240);
4096     l_msg_count     NUMBER;
4097     l_no_error      BOOLEAN;
4098     l_api_name      VARCHAR2(30)  := 'rollback_capacity_update';
4099 
4100     l_debug         NUMBER;
4101 
4102     -- gets all of the put away suggestions already created;
4103     -- The locator capacity would have been updated for each of these
4104     -- records
4105     -- type_code 1 = put away; line_type_code 2 = output
4106     CURSOR l_output_lines IS
4107       SELECT   to_locator_id
4108              , SUM(primary_quantity) quantity
4109           FROM wms_transactions_temp
4110          WHERE type_code = 1
4111            AND line_type_code = 2
4112       GROUP BY to_locator_id;
4113   BEGIN
4114     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
4115         g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
4116     END IF;
4117     l_debug := g_debug;
4118 
4119     If l_debug  = 1 THEN
4120        log_procedure(l_api_name, 'start', 'Start rollback_capacity_update');
4121     END IF;
4122 
4123     l_return_status  := fnd_api.g_ret_sts_success;
4124     l_no_error       := TRUE;
4125 
4126     FOR l_line IN l_output_lines LOOP
4127       -- We don't track capacity at Subinventory level, so no need
4128       -- to update if locator_id is null
4129       IF l_line.to_locator_id IS NOT NULL THEN
4130 
4131         IF l_debug = 1 THEN
4132            log_statement(l_api_name, 'calling_revert', 'Calling inv_loc_wms_utils.revert_loc_suggested_capacity');
4133            log_statement(l_api_name, 'revert_org', 'Org: ' || p_organization_id);
4134            log_statement(l_api_name, 'revert_item', 'Item: ' || p_inventory_item_id);
4135            log_statement(l_api_name, 'revert_loc', 'Loc: ' || l_line.to_locator_id);
4136            log_statement(l_api_name, 'revert_qty', 'Qty: ' || l_line.quantity);
4137         END IF;
4138         inv_loc_wms_utils.revert_loc_suggested_capacity(
4139           x_return_status              => l_return_status
4140         , x_msg_count                  => l_msg_count
4141         , x_msg_data                   => l_msg_data
4142         , p_organization_id            => p_organization_id
4143         , p_inventory_location_id      => l_line.to_locator_id
4144         , p_inventory_item_id          => p_inventory_item_id
4145         , p_primary_uom_flag           => 'Y'
4146         , p_transaction_uom_code       => NULL
4147         , p_quantity                   => l_line.quantity
4148         );
4149 
4150         --return only the first error message
4151         IF  l_no_error
4152             AND l_return_status <> fnd_api.g_ret_sts_success THEN
4153           x_return_status  := l_return_status;
4154           x_msg_count      := l_msg_count;
4155           x_msg_data       := l_msg_data;
4156           l_no_error       := FALSE;
4157 
4158           IF l_debug = 1 THEN
4159              log_statement(l_api_name, 'first_error', 'Error in inv_loc_wms_utils.revert_loc_suggested_capacity');
4160           END IF;
4161        END IF;
4162      END IF;
4163     END LOOP;
4164     IF l_debug = 1 THEN
4165        log_procedure(l_api_name, 'end', 'End rollback_capacity_update');
4166     END IF;
4167 
4168    EXCEPTION
4169     WHEN OTHERS THEN
4170       x_return_status  := fnd_api.g_ret_sts_unexp_error;
4171 
4172       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
4173         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
4174       END IF;
4175 
4176       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4177 
4178       IF l_debug = 1 THEN
4179          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
4180       END IF;
4181    END rollback_capacity_update;
4182 
4183   -- Bug# 4099907 -- Modifying the fix done in the Bug 3609380
4184   -- Pass the value for transfer_to_sub incase of Subinventory transfer
4185   -- allocations (i.e. with transaction action as 2)
4186   -- Private function
4187   FUNCTION chk_for_passing_xfer_sub
4188                (   p_transaction_temp_id   IN  NUMBER
4189                  , p_to_subinventory_code  IN  VARCHAR2
4190                )
4191   RETURN VARCHAR2
4192   IS
4193    l_to_subinventory_code     MTL_SECONDARY_INVENTORIES.SECONDARY_INVENTORY_NAME%TYPE := NULL ;
4194    l_transaction_action_id    NUMBER := 0 ;
4195    l_debug                    NUMBER := g_debug ;
4196    l_api_name                 VARCHAR2(30) := 'chk_for_passing_xfer_sub';
4197    l_transaction_type_id      NUMBER := 0 ;
4198 
4199   BEGIN
4200 
4201     IF inv_cache.set_mol_rec(p_transaction_temp_id) THEN
4202      l_transaction_type_id  := inv_cache.mol_rec.transaction_type_id;
4203     END IF;
4204 
4205     IF l_transaction_type_id <> 0 THEN
4206      IF inv_cache.set_mtt_rec(l_transaction_type_id) THEN
4207        l_transaction_action_id := inv_cache.mtt_rec.transaction_action_id;
4208      END IF;
4209     END IF;
4210 
4211     IF l_transaction_action_id = 2 THEN
4212       l_to_subinventory_code := p_to_subinventory_code;
4213     END IF;
4214 
4215     IF l_debug = 1  THEN
4216       log_statement(l_api_name, 'l_transaction_action_id', 'l_transaction_action_id : ' || l_transaction_action_id );
4217       log_statement(l_api_name, 'l_to_subinventory_code', 'l_to_subinventory_code: ' || l_to_subinventory_code);
4218     END IF;
4219 
4220     RETURN l_to_subinventory_code ;
4221 
4222   END chk_for_passing_xfer_sub ;
4223   -- End of function definition for fixing Bug 4099907
4224 
4225   PROCEDURE validate_and_insert(
4226     x_return_status          OUT NOCOPY    VARCHAR2
4227   , x_msg_count              OUT NOCOPY    NUMBER
4228   , x_msg_data               OUT NOCOPY    VARCHAR2
4229   , p_record_id              IN            NUMBER
4230   , p_needed_quantity        IN            NUMBER
4231   , p_use_pick_uom           IN            BOOLEAN
4232   , p_organization_id        IN            NUMBER
4233   , p_inventory_item_id      IN            NUMBER
4234   , p_to_subinventory_code   IN            VARCHAR2
4235   , p_to_locator_id          IN            NUMBER
4236   , p_to_cost_group_id       IN            NUMBER
4237   , p_primary_uom            IN            VARCHAR2
4238   , p_transaction_uom        IN            VARCHAR2
4239   , p_transaction_temp_id    IN            NUMBER
4240   , p_type_code              IN            NUMBER
4241   , p_rule_id                IN            NUMBER
4242   , p_reservation_id         IN            NUMBER
4243   , p_tree_id                IN            NUMBER
4244   , p_debug_on               IN            BOOLEAN
4245   , p_needed_sec_quantity    IN            NUMBER                        -- new
4246   , p_secondary_uom          IN            VARCHAR2                      -- new
4247   , p_grade_code             IN            VARCHAR2                      -- new
4248   , x_inserted_record        OUT NOCOPY    BOOLEAN
4249   , x_allocated_quantity     OUT NOCOPY    NUMBER
4250   , x_remaining_quantity     OUT NOCOPY    NUMBER
4251   , x_sec_allocated_quantity OUT NOCOPY    NUMBER                         -- new
4252   , x_sec_remaining_quantity OUT NOCOPY    NUMBER                         -- new
4253   ) IS
4254     l_api_name                  VARCHAR2(30) := 'validate_and_insert';
4255     l_qoh                       NUMBER;
4256     l_rqoh                      NUMBER;
4257     l_qr                        NUMBER;
4258     l_qs                        NUMBER;
4259     l_att                       NUMBER;
4260     l_atr                       NUMBER;
4261     l_allocation_quantity       NUMBER;
4262     l_sqoh                      NUMBER;
4263     l_srqoh                     NUMBER;
4264     l_sqr                       NUMBER;
4265     l_sqs                       NUMBER;
4266     l_satt                      NUMBER;
4267     l_satr                      NUMBER;
4268     l_sallocation_quantity      NUMBER;
4269     l_orig_allocation_quantity  NUMBER;
4270     l_sorig_allocation_quantity NUMBER;
4271     l_found                     BOOLEAN;
4272     l_possible_uom_qty          NUMBER;
4273     l_possible_trx_qty          NUMBER;
4274     l_sec_possible_trx_qty      NUMBER;
4275     l_serial_index              NUMBER;
4276     l_lot_divisible_flag        VARCHAR2(1);
4277     l_lot_control_code          NUMBER;
4278     l_to_locator_id             NUMBER;
4279     l_dual_uom_ctl              NUMBER;
4280     l_detailed_rsv_exist        NUMBER;
4281     l_dummy_qty                 NUMBER;
4282 
4283     l_debug                   NUMBER;
4284     l_indiv_lot_allowed       VARCHAR2(1);
4285 
4286     CURSOR C_item_info IS
4287       SELECT lot_divisible_flag
4288           ,  lot_control_code
4289           ,  dual_uom_control
4290         FROM mtl_system_items
4291        WHERE organization_id = p_organization_id
4292          AND inventory_item_id = p_inventory_item_id;
4293 
4294     Cursor c_detailed_reservation IS
4295       Select  1
4296          ,  secondary_reservation_quantity
4297       From mtl_reservations
4298       Where reservation_id = p_reservation_id
4299        and  lot_number = g_locs(p_record_id).lot_number;
4300   BEGIN
4301     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
4302        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
4303     END IF;
4304     l_debug := g_debug;
4305 
4306     x_return_status             := fnd_api.g_ret_sts_success;
4307     l_allocation_quantity       := p_needed_quantity;
4308     l_sallocation_quantity      := p_needed_sec_quantity;
4309     l_to_locator_id             := p_to_locator_id;
4310     /*
4311 
4312     Open C_item_info;
4313     Fetch C_item_info
4314     Into l_lot_divisible_flag
4315       ,  l_lot_control_code
4316       ,  l_dual_uom_ctl
4317       ;
4318     Close C_item_info;
4319     */
4320      -- [ Added the following code and commented the above item cursor
4321      l_lot_divisible_flag  	:= inv_cache.item_rec.lot_divisible_flag;
4322      l_lot_control_code    	:= inv_cache.item_rec.lot_control_code;
4323      l_dual_uom_ctl             := inv_cache.item_rec.dual_uom_control;
4324      -- ]
4325     /* lot specific conversion  3986955*/
4326     IF l_dual_uom_ctl > 1 and nvl(g_locs(p_record_id).lot_number,'-9999') <> '-9999' THEN
4327       /* bug 5441849, if detailed reservation exist, meaning that user has made the
4328        * correct 2nd qty either by system defaults on the lot
4329        * or manually changed it with the appropriate value, this value on the reservation
4330        * should be carried over to the allocation
4331        */
4332       l_detailed_rsv_exist := 0;
4333       Open c_detailed_reservation ;
4334       Fetch c_detailed_reservation
4335        Into l_detailed_rsv_exist
4336           , l_dummy_qty;
4337       Close c_detailed_reservation;
4338       if l_detailed_rsv_exist = 1 Then
4339          l_sallocation_quantity     := l_dummy_qty;
4340       else
4341          l_sallocation_quantity     := inv_convert.inv_um_convert(
4342                               Item_id          => p_inventory_item_id
4343                             , Lot_number       => g_locs(p_record_id).lot_number
4344                             , Organization_id  => p_organization_id
4345                             , Precision        => null
4346                             , From_quantity    => l_allocation_quantity
4347                             , From_unit        => p_primary_uom
4348                             , To_unit          => p_secondary_uom
4349                             , from_name        => NULL
4350                             , to_name          => NULL
4351                              );
4352       End if;
4353     End If;
4354 
4355     IF l_dual_uom_ctl = 1 THEN
4356       l_sallocation_quantity     := null;
4357     END IF;
4358 
4359     IF l_debug = 1 THEN
4360        log_procedure(l_api_name, 'validate and insert', 'Start Validate_And_Insert');
4361        log_statement(l_api_name, 'validate and insert', 'lot_divisible_flag : ' || l_lot_divisible_flag);
4362        log_statement(l_api_name, 'validate and insert', 'needed quantity: ' || p_needed_quantity);
4363        log_statement(l_api_name, 'validate and insert', 'sec_needed quantity: ' || p_needed_sec_quantity);
4364        log_statement(l_api_name, 'validate and insert', 'p_record_id: ' || p_record_id);
4365     END IF;
4366     /* bug 3972784, remove locator_id if no locator control */
4367     IF (  wms_engine_pvt.g_org_loc_control in (1,4)                   -- no loc ctl org level
4368          AND ( wms_engine_pvt.g_sub_loc_control = 1                  -- no loc ctl sub level
4369             OR (wms_engine_pvt.g_sub_loc_control = 5
4370                    AND wms_engine_pvt.g_item_loc_control = 1           -- no loc ctl item level
4371                )
4372              )
4373        )
4374     THEN
4375         l_to_locator_id := null;
4376         log_statement(l_api_name, 'non locator controled',' Non locator controled');
4377     END IF;
4378     IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1  AND  g_locs(p_record_id).quantity  <= l_allocation_quantity  THEN -- lot ctl and indivisible
4379         l_allocation_quantity   := g_locs(p_record_id).quantity;
4380         l_sallocation_quantity  := g_locs(p_record_id).secondary_quantity;
4381 
4382     ELSE
4383       IF l_allocation_quantity > g_locs(p_record_id).quantity THEN
4384         l_allocation_quantity  := g_locs(p_record_id).quantity;
4385         l_sallocation_quantity  := g_locs(p_record_id).secondary_quantity;
4386 
4387       END IF;
4388     END IF;
4389     -- BUG 3609380 :  Removing p_to_subinevntory_code.
4390     --query quantity tree
4391     IF l_debug = 1  THEN
4392        log_statement(l_api_name, 'p_revision', g_locs(p_record_id).revision);
4393        log_statement(l_api_name, 'p_lot_number', g_locs(p_record_id).lot_number);
4394        log_statement(l_api_name, 'p_subinventory', g_locs(p_record_id).subinventory_code);
4395        log_statement(l_api_name, 'record_quantity', 'record quantity: ' || l_allocation_quantity);
4396        log_statement(l_api_name, 'sec_record_quantity', 'sec_record quantity: ' || l_sallocation_quantity);
4397        log_statement(l_api_name, 'query_tree', 'Calling Query Tree');
4398        log_statement(l_api_name, 'tree_id', 'tree_id: ' || p_tree_id);
4399 
4400     END IF;
4401 
4402      inv_quantity_tree_pvt.query_tree
4403            (
4404                 p_api_version_number         =>   g_qty_tree_api_version
4405               , p_init_msg_lst               =>   fnd_api.g_false -- p_init_msg_lst
4406               , x_return_status              =>   x_return_status
4407               , x_msg_count                  =>   x_msg_count
4408               , x_msg_data                   =>   x_msg_data
4409               , p_tree_id                    =>   p_tree_id
4410               , p_revision                   =>   g_locs(p_record_id).revision
4411               , p_lot_number                 =>   g_locs(p_record_id).lot_number
4412               , p_subinventory_code          =>   g_locs(p_record_id).subinventory_code
4413               , p_locator_id                 =>   g_locs(p_record_id).locator_id
4414               , x_qoh                        =>   l_qoh
4415               , x_sqoh                       =>   l_sqoh
4416               , x_rqoh                       =>   l_rqoh
4417               , x_srqoh                      =>   l_srqoh
4418               , x_qr                         =>   l_qr
4419               , x_sqr                        =>   l_sqr
4420               , x_qs                         =>   l_qs
4421               , x_sqs                        =>   l_sqs
4422               , x_att                        =>   l_att
4423               , x_satt                       =>   l_satt
4424               , x_atr                        =>   l_atr
4425               , x_satr                       =>   l_satr
4426               , p_transfer_subinventory_code =>   chk_for_passing_xfer_sub ( TO_NUMBER(p_transaction_temp_id) , p_to_subinventory_code)  -- Bug # 4099907
4427               , p_cost_group_id              =>   g_locs(p_record_id).cost_group_id
4428               , p_lpn_id                     =>   g_locs(p_record_id).lpn_id
4429            );
4430       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
4431         IF l_debug = 1 THEN
4432          log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
4433         END IF;
4434         RAISE fnd_api.g_exc_unexpected_error;
4435       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
4436         IF l_debug = 1 THEN
4437          log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
4438         END IF;
4439         RAISE fnd_api.g_exc_error;
4440       END IF;
4441 
4442       IF l_debug = 1 THEN
4443          log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
4444          log_statement(l_api_name, 'satt_qty', 'Secondary Available quantity = ' || l_satt);
4445          log_statement(l_api_name, 'grade_code', 'grade_code = ' || p_grade_code);
4446       END IF;
4447       -- [ LOT_INDIV
4448       -- Checking ,
4449       -- a. If the pre suggestion record fetched from the rule is greater than the max qty allowed
4450       --    after adjusting the for upper tolerance .
4451       -- b. If ATT qty is equal to ON hand Qty to that of the pre suggestions record qty.
4452       --    It may be different due to partial reservations.
4453       -- The pre suggestions record will be skipped, if any of the above condition is false
4454       -- and fetch the next rec
4455       -- ]
4456       IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1 AND g_locs(p_record_id).quantity  <= l_allocation_quantity  THEN  -- lot ctl and indivisible
4457 
4458          IF  ((l_att = g_locs(p_record_id).quantity)  and ( l_qoh = l_att)) THEN
4459 	       l_indiv_lot_allowed := 'Y';
4460          Else
4461 	    l_indiv_lot_allowed := 'N';
4462 	    IF l_debug = 1 THEN
4463 	       log_statement(l_api_name, '', 'All the material is not available for this rec.');
4464 	    END IF;
4465          End if;
4466       Else
4467 	 l_indiv_lot_allowed := 'N' ;
4468       END IF;
4469 
4470     --update record quantity
4471    IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1  THEN  -- lot ctl and indivisible
4472        IF  l_indiv_lot_allowed = 'Y' THEN
4473            g_locs(p_record_id).quantity  := l_att;
4474            g_locs(p_record_id).secondary_quantity  := l_satt;
4475            g_locs(p_record_id).grade_code  := p_grade_code;
4476            --update possible allocate quantity
4477            l_allocation_quantity  := l_att;
4478            l_sallocation_quantity  := l_satt;
4479         ELSE
4480            l_allocation_quantity   := 0;
4481            l_sallocation_quantity  := 0;
4482         END IF;
4483         IF l_debug = 1 THEN
4484            log_statement(l_api_name, 'Lot Indiv', ' lot IS NOT divisible -- indivsible' );
4485            log_statement(l_api_name, 'Lot Indiv', 'New possible qty: ' || l_allocation_quantity);
4486         END IF;
4487     ELSE
4488         IF l_att < g_locs(p_record_id).quantity THEN
4489            g_locs(p_record_id).quantity  := l_att;
4490            g_locs(p_record_id).secondary_quantity  := l_satt;
4491            g_locs(p_record_id).grade_code  := p_grade_code;
4492         END IF;
4493         --update possible allocate quantity
4494         IF l_att < l_allocation_quantity THEN
4495            l_allocation_quantity  := l_att;
4496            l_sallocation_quantity  := l_satt;
4497         END IF;
4498     END IF;
4499     IF l_debug = 1 THEN
4500         log_statement(l_api_name, 'tree_qty', 'ATT < possible quantity.  New possible qty: ' || g_locs(p_record_id).quantity);
4501     END IF;
4502 
4503 
4504     --if no available quantity, return
4505     IF l_allocation_quantity <= 0 THEN
4506       --if reading from table, go to next record
4507       IF l_debug = 1 THEN
4508          log_event(l_api_name, 'zero_tree_qty', 'Available quantity ' || 'returned from quantity tree is zero');
4509       END IF;
4510       IF p_debug_on THEN
4511         g_trace_recs(p_record_id).att_qty                  := l_att;
4512         g_trace_recs(p_record_id).secondary_att_qty        := l_satt;
4513         g_trace_recs(p_record_id).att_qty_flag             := 'N';
4514       END IF;
4515       x_allocated_quantity  := 0;
4516       x_remaining_quantity  := 0;
4517       x_inserted_record     := FALSE;
4518       RETURN;
4519     END IF;
4520 
4521     IF p_debug_on THEN
4522       g_trace_recs(p_record_id).att_qty                  := l_att;
4523       g_trace_recs(p_record_id).secondary_att_qty        := l_satt;
4524       g_trace_recs(p_record_id).att_qty_flag             := 'Y';
4525     END IF;
4526 
4527     --check to see if serial number has already been used
4528     IF (g_locs(p_record_id).serial_number IS NOT NULL
4529         And g_locs(p_record_id).serial_number <> FND_API.G_MISS_CHAR)
4530     THEN
4531       IF l_debug = 1 THEN
4532          log_statement(l_api_name, 'search_sn', 'Calling Search Serial Numbers');
4533       END IF;
4534 
4535       inv_detail_util_pvt.search_serial_numbers(
4536         p_organization_id            => p_organization_id
4537       , p_inventory_item_id          => p_inventory_item_id
4538       , p_serial_number              => g_locs(p_record_id).serial_number
4539       , x_found                      => l_found
4540       , x_return_status              => x_return_status
4541       , x_msg_count                  => x_msg_count
4542       , x_msg_data                   => x_msg_data
4543       );
4544 
4545       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
4546         IF l_debug = 1 THEN
4547            log_statement(l_api_name, 'uerr_search_sn', 'Unexpected error in search_serial_numbers');
4548         END IF;
4549         RAISE fnd_api.g_exc_unexpected_error;
4550       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
4551         IF l_debug = 1 THEN
4552            log_statement(l_api_name, 'err_search_sn', 'Error in search_serial_numbers');
4553         END IF;
4554         RAISE fnd_api.g_exc_error;
4555       END IF;
4556 
4557       IF l_found THEN
4558         IF p_debug_on THEN
4559           g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
4560         END IF;
4561         IF l_debug = 1 THEN
4562            log_event(l_api_name, 'sn_used', 'Serial Number has been used');
4563         END IF;
4564         g_locs(p_record_id).quantity  := 0;
4565         x_allocated_quantity          := 0;
4566         x_remaining_quantity          := 0;
4567         x_inserted_record             := FALSE;
4568         RETURN;
4569       END IF;
4570 
4571       IF p_debug_on THEN
4572         g_trace_recs(p_record_id).serial_number_used_flag  := 'Y';
4573       END IF;
4574     END IF;
4575 
4576     --If we are factoring in Pick UOM, convert quantity into Pick UOM.
4577     --Then, find the the largest non-decimal quantity in Pick UOM.  Convert
4578     --back to primary UOM
4579     -- if Uom code is null, than use primary uom
4580     -- if pick uom = primary uom, skip conversions
4581 
4582     l_orig_allocation_quantity  := l_allocation_quantity;
4583     l_sorig_allocation_quantity := l_sallocation_quantity;
4584 
4585     IF  p_use_pick_uom
4586         AND g_locs(p_record_id).uom_code IS NOT NULL
4587         AND g_locs(p_record_id).uom_code <> p_primary_uom THEN
4588 
4589       IF l_debug = 1 THEN
4590          log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
4591       END IF;
4592       --convert from primary uom to pick uom
4593       l_possible_uom_qty  := inv_convert.inv_um_convert(
4594                                p_inventory_item_id
4595                              , NULL
4596                              , l_allocation_quantity
4597                              , p_primary_uom
4598                              , g_locs(p_record_id).uom_code
4599                              , NULL
4600                              , NULL
4601                              );
4602 
4603       --if no conversion defined or some error in conversion,
4604       --inv_um_convert returns -99999.  In this case, don't carry
4605       --out any more conversion functions.  possible quantity
4606       --remains unchanged
4607       IF (l_possible_uom_qty <> -99999) THEN
4608         --don't want to pick fractional amounts of pick uom
4609         l_possible_uom_qty     := FLOOR(l_possible_uom_qty);
4610 
4611         IF l_debug = 1 THEN
4612            log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
4613         END IF;
4614         --convert back to primary uom
4615         l_allocation_quantity  := inv_convert.inv_um_convert(
4616                                     p_inventory_item_id
4617                                   , NULL
4618                                   , l_possible_uom_qty
4619                                   , g_locs(p_record_id).uom_code
4620                                   , p_primary_uom
4621                                   , NULL
4622                                   , NULL
4623                                   );
4624         IF l_debug = 1 THEN
4625            log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: ' || l_allocation_quantity);
4626         END IF;
4627       END IF;
4628     END IF;
4629 
4630     --populate remaining quantity
4631     x_remaining_quantity        := l_orig_allocation_quantity - l_allocation_quantity;
4632     x_sec_remaining_quantity    := l_sorig_allocation_quantity - l_sallocation_quantity;
4633     IF l_debug = 1 THEN
4634        log_statement(l_api_name, 'rem_qty', 'remaining_quantity : ' || x_remaining_quantity);
4635     END IF;
4636 
4637     IF l_allocation_quantity <= 0 THEN
4638       IF l_debug = 1 THEN
4639          log_statement(l_api_name, 'no_alloc_qty', 'Quantity remaining to allocate.  Exiting.');
4640       END IF;
4641       x_allocated_quantity      := 0;
4642       x_sec_allocated_quantity  := 0;
4643       x_inserted_record         := FALSE;
4644       RETURN;
4645     END IF;
4646 
4647     --Lock Serial number, so that no other detailing process
4648     -- can use it.
4649     IF (g_locs(p_record_id).serial_number IS NOT NULL
4650         And g_locs(p_record_id).serial_number <> FND_API.G_MISS_CHAR)
4651     THEN
4652       l_found  := inv_detail_util_pvt.lock_serial_number(p_inventory_item_id, g_locs(p_record_id).serial_number);
4653 
4654       IF l_found = FALSE THEN
4655         IF l_debug = 1 THEN
4656            log_statement(l_api_name, 'lock_sn', 'Could not lock Serial Number. Exiting.');
4657         END IF;
4658 
4659         IF p_debug_on THEN
4660           g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
4661         END IF;
4662 
4663         x_remaining_quantity  := g_locs(p_record_id).quantity;
4664         x_allocated_quantity  := 0;
4665         x_sec_remaining_quantity  := null;
4666         x_sec_allocated_quantity  := null;
4667         x_inserted_record     := FALSE;
4668         RETURN;
4669       END IF;
4670 
4671       -- add serial number to pl/sql table of detailed serials
4672       inv_detail_util_pvt.add_serial_number(p_inventory_item_id, p_organization_id, g_locs(p_record_id).serial_number, l_serial_index);
4673     END IF;
4674 
4675     -- Update quantity tree for this suggested quantity
4676     IF l_debug = 1 THEN
4677        log_statement(l_api_name, 'update_tree', 'Updating qty tree');
4678     END IF;
4679 
4680     inv_quantity_tree_pvt.update_quantities
4681            (
4682                 p_api_version_number         => g_qty_tree_api_version
4683               , p_init_msg_lst               => fnd_api.g_false
4684               , x_return_status              => x_return_status
4685               , x_msg_count                  => x_msg_count
4686               , x_msg_data                   => x_msg_data
4687               , p_tree_id                    => p_tree_id
4688               , p_revision                   => g_locs(p_record_id).revision
4689               , p_lot_number                 => g_locs(p_record_id).lot_number
4690               , p_subinventory_code          => g_locs(p_record_id).subinventory_code
4691               , p_locator_id                 => g_locs(p_record_id).locator_id
4692               , p_primary_quantity           => l_allocation_quantity
4693               , p_secondary_quantity         => l_sallocation_quantity                             -- INVCONV
4694               , p_quantity_type              => inv_quantity_tree_pvt.g_qs_txn
4695               , x_qoh                        => l_qoh
4696               , x_rqoh                       => l_rqoh
4697               , x_qr                         => l_qr
4698               , x_qs                         => l_qs
4699               , x_att                        => l_att
4700               , x_atr                        => l_atr
4701               , x_sqoh                       => l_sqoh                                             -- INVCONV
4702               , x_srqoh                      => l_srqoh                                            -- INVCONV
4703               , x_sqr                        => l_sqr                                              -- INVCONV
4704               , x_sqs                        => l_sqs                                              -- INVCONV
4705               , x_satt                       => l_satt                                             -- INVCONV
4706               , x_satr                       => l_satr                                             -- INVCONV
4707               , p_transfer_subinventory_code => p_to_subinventory_code
4708               , p_cost_group_id              => g_locs(p_record_id).cost_group_id
4709               , p_lpn_id                     => g_locs(p_record_id).lpn_id
4710            );
4711 
4712     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
4713       IF l_debug = 1 THEN
4714          log_statement(l_api_name, 'uerr_update_qty', 'Unexpected error in inv_quantity_tree_pvt.update_quantities');
4715       END IF;
4716 
4717       RAISE fnd_api.g_exc_unexpected_error;
4718     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
4719        IF l_debug = 1 THEN
4720          log_statement(l_api_name, 'err_update_qty', 'Error in inv_quantity_tree_pvt.update_quantities');
4721       END IF;
4722       RAISE fnd_api.g_exc_error;
4723     END IF;
4724 
4725     --If quantity remaining to allocate is greater than 0, update the
4726     --quantity tree and insert the record into WTT
4727     IF p_transaction_uom = p_primary_uom THEN
4728       l_possible_trx_qty  := l_allocation_quantity;
4729     ELSE
4730       l_possible_trx_qty  :=
4731                  inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_allocation_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
4732     END IF;
4733     l_sec_possible_trx_qty  := l_sallocation_quantity;
4734 
4735     IF l_debug = 1 THEN
4736        log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Trx Qty: ' || l_possible_trx_qty);
4737        log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Sec Trx Qty: ' || l_sec_possible_trx_qty);
4738     END IF;
4739     -- insert temporary suggestion
4740     INSERT INTO wms_transactions_temp
4741                 (
4742                 pp_transaction_temp_id
4743               , transaction_temp_id
4744               , type_code
4745               , line_type_code
4746               , transaction_quantity
4747               , primary_quantity
4748               , secondary_quantity
4749               , grade_code
4750               , revision
4751               , lot_number
4752               , lot_expiration_date
4753               , from_subinventory_code
4754               , from_locator_id
4755               , rule_id
4756               , reservation_id
4757               , serial_number
4758               , to_subinventory_code
4759               , to_locator_id
4760               , from_cost_group_id
4761               , to_cost_group_id
4762               , lpn_id
4763                 )
4764          VALUES (
4765                 wms_transactions_temp_s.NEXTVAL
4766               , p_transaction_temp_id
4767               , p_type_code
4768               , 2 -- line type code is output
4769               , l_possible_trx_qty
4770               , l_allocation_quantity
4771               , l_sallocation_quantity
4772               , g_locs(p_record_id).grade_code
4773               , g_locs(p_record_id).revision
4774               , g_locs(p_record_id).lot_number
4775               , g_locs(p_record_id).lot_expiration_date
4776               , g_locs(p_record_id).subinventory_code
4777               , g_locs(p_record_id).locator_id
4778               , p_rule_id
4779               , p_reservation_id
4780               , g_locs(p_record_id).serial_number
4781               , p_to_subinventory_code
4782               , l_to_locator_id
4783               , g_locs(p_record_id).cost_group_id
4784               , p_to_cost_group_id
4785               , g_locs(p_record_id).lpn_id
4786                 );
4787     IF l_debug = 1 THEN
4788        log_statement(l_api_name, 'finish_insert_wtt', 'Finished inserting wtt recs.');
4789        log_statement(l_api_name, 'alloc_qty', 'Alloc qty: ' || l_allocation_quantity);
4790        log_statement(l_api_name, 'sec_alloc_qty', 'sec_Alloc qty: ' || l_sallocation_quantity);
4791     END IF;
4792 
4793     IF p_debug_on THEN
4794       g_trace_recs(p_record_id).suggested_qty  := l_allocation_quantity;
4795       g_trace_recs(p_record_id).secondary_suggested_qty  := l_sallocation_quantity;
4796     END IF;
4797 
4798     x_inserted_record           := TRUE;
4799     x_allocated_quantity        := l_allocation_quantity;
4800     x_sec_allocated_quantity    := l_sallocation_quantity;
4801     IF l_debug = 1 THEN
4802        log_statement(l_api_name, 'alloc_qty', 'Allocated quantity: ' || x_allocated_quantity);
4803        log_statement(l_api_name, 'sec_alloc_qty', 'sec_Allocated quantity: ' || x_sec_allocated_quantity);
4804        log_procedure(l_api_name, 'end', 'End Validate_and_Insert');
4805     END IF;
4806 
4807   EXCEPTION
4808     WHEN fnd_api.g_exc_error THEN
4809       x_return_status  := fnd_api.g_ret_sts_error;
4810       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4811       --
4812       IF l_debug = 1 THEN
4813          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
4814       END IF;
4815 
4816     WHEN fnd_api.g_exc_unexpected_error THEN
4817       x_return_status  := fnd_api.g_ret_sts_unexp_error;
4818       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4819       IF l_debug = 1 THEN
4820          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
4821       END IF;
4822 
4823     WHEN OTHERS THEN
4824       x_return_status  := fnd_api.g_ret_sts_unexp_error;
4825 
4826       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
4827         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
4828       END IF;
4829 
4830       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4831       IF l_debug = 1 THEN
4832          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
4833       END IF;
4834 
4835   END validate_and_insert;
4836   --- Added the following procedure for bug #4006426
4837 
4838   -- This procedure is used to get the quantity available to transact
4839   -- for a sub-transfer from a non-reservable subinventory.
4840   -- It assumed that pending transactions only exist at locator and lpn level
4841   -- The quantity is calculated with onhand quantity from
4842   -- MTL_ONHAND_QUANTITIES_DETAIL and pending transactions from
4843   -- MTL_MATERIAL_TRANSACTIONS_TEMP
4844   -- First get onhand and pending transactions at LPN level
4845   -- If LPN level availability > 0 then get pending transactions at Locator level
4846   -- return onhand less pending transactions
4847   -- NOTES :-
4848   -- 1) The quantities calculated do not include suggestions
4849   -- 2) Transfer SUB and locator are not needed in this query as this should be used
4850   --    only to get availability in a locator controlled SUB.
4851   -- 3) LOT expiration dates are not considered as this is to be used only for inventory moves
4852 
4853  PROCEDURE  GET_AVAIL_QTY_FOR_XFER
4854  (   p_organization_id        IN  NUMBER
4855     ,  p_inventory_item_id    IN  NUMBER
4856     ,  p_revision             IN  VARCHAR2
4857     ,  p_lot_number           IN  VARCHAR2
4858     ,  p_subinventory_code    IN  VARCHAR2
4859     ,  p_locator_id           IN  NUMBER
4860     ,  p_lpn_id               IN  NUMBER
4861     ,  x_qoh                  OUT NOCOPY NUMBER
4862     ,  x_att                  OUT NOCOPY NUMBER
4863     ,  x_return_status        OUT NOCOPY VARCHAR2
4864     ,  x_msg_count            OUT NOCOPY NUMBER
4865     ,  x_msg_data             OUT NOCOPY VARCHAR2
4866  )
4867  AS
4868  l_qoh     NUMBER;
4869  l_att     NUMBER;
4870  l_lpn_qoh   NUMBER;
4871  l_lpn_att   NUMBER;
4872  l_loc_qoh   NUMBER;
4873  l_loc_att   NUMBER;
4874  l_moq_qty   NUMBER;
4875  l_mmtt_qty_src  NUMBER;
4876  l_mmtt_qty_dest  NUMBER;
4877 
4878  l_debug  NUMBER := 1;
4879 
4880  BEGIN
4881 
4882    IF(l_debug=1) THEN
4883       inv_log_util.trace('Inside :GET_AVAIL_QTY_FOR_XFER '  , 'Start', 9);
4884       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_organization_id :'||p_organization_id, 9);
4885       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_inventory_item_id :'||p_inventory_item_id, 9);
4886       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_revision :'||p_revision, 9);
4887       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_subinventory_code :'||p_subinventory_code, 9);
4888       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_lot_number :'||p_lot_number, 9);
4889        inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_lpn_id :'||p_lpn_id, 9);
4890   END IF;
4891 
4892    IF p_lpn_id IS NOT NULL THEN
4893      -- LPN level
4894        SELECT SUM(moq.primary_transaction_quantity)
4895        INTO   l_moq_qty
4896        FROM   mtl_onhand_quantities_detail moq
4897        WHERE  moq.organization_id = p_organization_id
4898        AND    moq.inventory_item_id = p_inventory_item_id
4899        AND    nvl(moq.revision,'@@') = nvl(p_revision,'@@')
4900        AND    moq.subinventory_code = p_subinventory_code
4901        AND    decode(p_lot_number,null,'@@',moq.lot_number) = nvl(p_lot_number,'@@')
4902        AND    moq.locator_id = p_locator_id
4903        AND    moq.lpn_id = p_lpn_id;
4904 
4905        IF(l_debug=1) THEN
4906          inv_log_util.trace('Total MOQ quantity LPN Level: ' || to_char(l_moq_qty), 'GET_AVAIL_QTY_FOR_XFER', 9);
4907        END IF;
4908 
4909        SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
4910                  Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
4911                        Sign(mmtt.primary_quantity)))
4912                * round(Abs(mmtt.primary_quantity),5))
4913        INTO   l_mmtt_qty_src
4914        FROM   mtl_material_transactions_temp mmtt
4915        WHERE  mmtt.organization_id = p_organization_id
4916        AND    mmtt.inventory_item_id = p_inventory_item_id
4917        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
4918        AND    mmtt.subinventory_code = p_subinventory_code
4919        AND    mmtt.locator_id = p_locator_id
4920        AND    NVL(mmtt.content_lpn_id,mmtt.transfer_lpn_id) = p_lpn_id
4921        AND    mmtt.posting_flag = 'Y'
4922        AND    mmtt.subinventory_code IS NOT NULL
4923        AND (Nvl(mmtt.transaction_status,0) <> 2 OR
4924                Nvl(mmtt.transaction_status,0) = 2 AND
4925                mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
4926               )
4927        AND    mmtt.transaction_action_id NOT IN (5,6,24,30);
4928 
4929        IF(l_debug=1) THEN
4930            inv_log_util.trace('Total MMTT Trx quantity Source Org Sub : ' || to_char(l_mmtt_qty_src), 'GET_AVAIL_QTY_FOR_XFER', 9);
4931        END IF;
4932 
4933        SELECT SUM(Abs(mmtt.primary_quantity))
4934        INTO   l_mmtt_qty_dest
4935        FROM   mtl_material_transactions_temp mmtt
4936        WHERE  decode(mmtt.transaction_action_id,3,
4937                mmtt.transfer_organization,mmtt.organization_id) = p_organization_id
4938        AND    mmtt.inventory_item_id = p_inventory_item_id
4939        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
4940        AND    mmtt.transfer_subinventory = p_subinventory_code
4941        AND    mmtt.transfer_to_location = p_locator_id
4942        AND    NVL(mmtt.content_lpn_id,mmtt.transfer_lpn_id) = p_lpn_id
4943        AND    mmtt.posting_flag = 'Y'
4944        AND    Nvl(mmtt.transaction_status,0) <> 2
4945        AND    mmtt.transaction_action_id  in (2,28,3)
4946        AND    mmtt.wip_supply_type IS NULL;
4947 
4948        IF(l_debug=1) THEN
4949            inv_log_util.trace('Total MMTT Trx quantity Dest Org Sub : ' || to_char(l_mmtt_qty_dest), 'GET_AVAIL_QTY_FOR_XFER', 9);
4950        END IF;
4951 
4952        l_lpn_qoh :=  nvl(l_moq_qty,0);
4953        l_lpn_att :=  nvl(l_moq_qty,0) + nvl(l_mmtt_qty_src,0) + nvl(l_mmtt_qty_dest,0);
4954 
4955     END IF;
4956 
4957     -- Only check onhand and pending at locator level if there is availability at LPN
4958     -- or no lpn passed in
4959     IF (nvl(l_lpn_att,0) > 0)  OR (p_lpn_id IS NULL) THEN
4960 
4961        SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
4962                  Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
4963                        Sign(mmtt.primary_quantity)))
4964                * round(Abs(mmtt.primary_quantity),5))
4965        INTO   l_mmtt_qty_src
4966        FROM   mtl_material_transactions_temp mmtt
4967        WHERE  mmtt.organization_id = p_organization_id
4968        AND    mmtt.inventory_item_id = p_inventory_item_id
4969        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
4970        AND    mmtt.subinventory_code = p_subinventory_code
4971        AND    mmtt.locator_id = p_locator_id
4972        AND    mmtt.posting_flag = 'Y'
4973        AND    mmtt.subinventory_code IS NOT NULL
4974        AND (Nvl(mmtt.transaction_status,0) <> 2 OR
4975                Nvl(mmtt.transaction_status,0) = 2 AND
4976                mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
4977               )
4978        AND    mmtt.transaction_action_id NOT IN (5,6,24,30);
4979 
4980        IF(l_debug=1) THEN
4981            inv_log_util.trace('Total MMTT Trx quantity Source Org Sub : ' || to_char(l_mmtt_qty_src), 'GET_AVAIL_QTY_FOR_XFER', 9);
4982        END IF;
4983 
4984        SELECT SUM(moq.primary_transaction_quantity)
4985        INTO   l_moq_qty
4986        FROM   mtl_onhand_quantities_detail moq
4987        WHERE  moq.organization_id = p_organization_id
4988        AND    moq.inventory_item_id = p_inventory_item_id
4989        AND    nvl(moq.revision,'@@') = nvl(p_revision,'@@')
4990        AND    moq.subinventory_code = p_subinventory_code
4991        AND    decode(p_lot_number,null,'@@',moq.lot_number) = nvl(p_lot_number,'@@')
4992        AND    moq.locator_id = p_locator_id;
4993 
4994        IF(l_debug=1) THEN
4995          inv_log_util.trace('Total MOQ quantity LPN Level: ' || to_char(l_moq_qty), 'GET_AVAIL_QTY_FOR_XFER', 9);
4996        END IF;
4997 
4998        SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
4999                  Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
5000                        Sign(mmtt.primary_quantity)))
5001                * round(Abs(mmtt.primary_quantity),5))
5002        INTO   l_mmtt_qty_src
5003        FROM   mtl_material_transactions_temp mmtt
5004        WHERE  mmtt.organization_id = p_organization_id
5005        AND    mmtt.inventory_item_id = p_inventory_item_id
5006        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
5007        AND    mmtt.subinventory_code = p_subinventory_code
5008        AND    mmtt.locator_id = p_locator_id
5009        AND    mmtt.posting_flag = 'Y'
5010        AND    mmtt.subinventory_code IS NOT NULL
5011        AND (Nvl(mmtt.transaction_status,0) <> 2 OR
5012                Nvl(mmtt.transaction_status,0) = 2 AND
5013                mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
5014               )
5015        AND    mmtt.transaction_action_id NOT IN (5,6,24,30);
5016        l_loc_qoh :=  nvl(l_moq_qty,0);
5017        l_loc_att :=  nvl(l_moq_qty,0) + nvl(l_mmtt_qty_src,0) + nvl(l_mmtt_qty_dest,0);
5018     END IF;
5019 
5020 
5021     -- Quantity available for transfer is the minimum of availability at LPN and locator levels
5022     IF p_lpn_id IS NULL THEN
5023         x_qoh := l_loc_qoh;
5024         x_att := l_loc_att;
5025     ELSE
5026       x_qoh := l_lpn_qoh;
5027       IF nvl(l_lpn_att,0) > nvl(l_loc_att,0) THEN
5028          x_att := l_loc_att;
5029       ELSE
5030          x_att := l_lpn_att;
5031       END IF;
5032     END IF;
5033 
5034     IF(l_debug=1) THEN
5035         inv_log_util.trace('Total quantity on-hand: ' || to_char(l_qoh), 'GET_AVAIL_QTY_FOR_XFER', 9);
5036     END IF;
5037  END GET_AVAIL_QTY_FOR_XFER;
5038 
5039 
5040   ---
5041    PROCEDURE ValidNinsert(
5042         x_return_status        OUT NOCOPY    VARCHAR2
5043       , x_msg_count            OUT NOCOPY    NUMBER
5044       , x_msg_data             OUT NOCOPY    VARCHAR2
5045       , p_record_id            IN            NUMBER
5046       , p_needed_quantity      IN            NUMBER
5047       , p_use_pick_uom         IN            BOOLEAN
5048       , p_organization_id      IN            NUMBER
5049       , p_inventory_item_id    IN            NUMBER
5050       , p_to_subinventory_code IN            VARCHAR2
5051       , p_to_locator_id        IN            NUMBER
5052       , p_to_cost_group_id     IN            NUMBER
5053       , p_primary_uom          IN            VARCHAR2
5054       , p_transaction_uom      IN            VARCHAR2
5055       , p_transaction_temp_id  IN            NUMBER
5056       , p_type_code            IN            NUMBER
5057       , p_rule_id              IN            NUMBER
5058       , p_reservation_id       IN            NUMBER
5059       , p_tree_id              IN            NUMBER
5060       , p_debug_on             IN            BOOLEAN
5061       , x_inserted_record      OUT NOCOPY    BOOLEAN
5062       , x_allocated_quantity   OUT NOCOPY    NUMBER
5063       , x_remaining_quantity   OUT NOCOPY    NUMBER
5064       ) IS
5065         l_api_name                 VARCHAR2(30) := 'validate_N_insert';
5066         l_att                      NUMBER;
5067         l_qoh                      NUMBER;
5068         l_allocation_quantity      NUMBER;
5069         l_orig_allocation_quantity NUMBER;
5070         l_found                    BOOLEAN;
5071         l_possible_uom_qty         NUMBER;
5072         l_possible_trx_qty         NUMBER;
5073         l_serial_index             NUMBER;
5074 
5075         l_debug                   NUMBER;
5076 
5077       BEGIN
5078         IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
5079            g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
5080         END IF;
5081         l_debug := g_debug;
5082 
5083         x_return_status             := fnd_api.g_ret_sts_success;
5084         l_allocation_quantity       := p_needed_quantity;
5085 
5086         IF l_debug = 1 THEN
5087            log_procedure(l_api_name, 'start', 'Start Validate_N_Insert');
5088            log_statement(l_api_name, 'needed_quantity', 'needed quantity: ' || p_needed_quantity);
5089            log_statement(l_api_name, 'rec_id', 'p_record_id: ' || p_record_id);
5090         END IF;
5091 
5092          IF l_allocation_quantity > g_locs(p_record_id).quantity THEN
5093           l_allocation_quantity  := g_locs(p_record_id).quantity;
5094           log_statement(l_api_name, 'record_quantity', 'record quantity: ' || l_allocation_quantity);
5095         END IF;
5096 
5097        GET_AVAIL_QTY_FOR_XFER(
5098                 p_organization_id     	=> p_organization_id
5099 	     ,  p_inventory_item_id   	=> p_inventory_item_id
5100 	     ,  p_revision 		=> g_locs(p_record_id).revision
5101 	     ,  p_lot_number  		=> g_locs(p_record_id).lot_number
5102 	     ,  p_subinventory_code  	=> g_locs(p_record_id).subinventory_code
5103 	     ,  p_locator_id   		=> g_locs(p_record_id).locator_id
5104 	     ,  p_lpn_id     		=> g_locs(p_record_id).lpn_id
5105 	     ,  x_qoh         		=> l_qoh
5106 	     ,  x_att  			=> l_att
5107 	     ,  x_return_status         => x_return_status
5108 	     ,  x_msg_count             => x_msg_count
5109     	     ,  x_msg_data              => x_msg_data   );
5110 
5111 
5112         IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5113 	      IF l_debug = 1 THEN
5114 	         log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
5115 	      END IF;
5116 	      RAISE fnd_api.g_exc_unexpected_error;
5117 	    ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5118 	      IF l_debug = 1 THEN
5119 	         log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
5120 	      END IF;
5121 	      RAISE fnd_api.g_exc_error;
5122         END IF;
5123 
5124         IF l_debug = 1 THEN
5125           log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
5126         END IF;
5127         --update record quantity
5128         IF l_att < g_locs(p_record_id).quantity THEN
5129           g_locs(p_record_id).quantity  := l_att;
5130         END IF;
5131 
5132         --update possible allocate quantity
5133         IF l_att < l_allocation_quantity THEN
5134           l_allocation_quantity  := l_att;
5135           IF l_debug = 1 THEN
5136              log_statement(l_api_name, 'tAvailable_qty', 'ATT < possible quantity.  New possible qty: ' || g_locs(p_record_id).quantity);
5137           END IF;
5138         END IF;
5139 
5140         --if no available quantity, return
5141         IF l_allocation_quantity <= 0 THEN
5142           --if reading from table, go to next record
5143           IF l_debug = 1 THEN
5144              log_event(l_api_name, 'zero_tree_qty', 'Available quantity ' || 'returned from quantity tree is zero');
5145           END IF;
5146 
5147           IF p_debug_on THEN
5148             g_trace_recs(p_record_id).att_qty       := l_att;
5149             g_trace_recs(p_record_id).att_qty_flag  := 'N';
5150           END IF;
5151 
5152           x_allocated_quantity  := 0;
5153           x_remaining_quantity  := 0;
5154           x_inserted_record     := FALSE;
5155           RETURN;
5156         END IF;
5157 
5158         IF p_debug_on THEN
5159           g_trace_recs(p_record_id).att_qty       := l_att;
5160           g_trace_recs(p_record_id).att_qty_flag  := 'Y';
5161         END IF;
5162 
5163         --check to see if serial number has already been used
5164         IF g_locs(p_record_id).serial_number IS NOT NULL THEN
5165           IF l_debug = 1 THEN
5166              log_statement(l_api_name, 'search_sn', 'Calling Search Serial Numbers');
5167           END IF;
5168 
5169           inv_detail_util_pvt.search_serial_numbers(
5170             p_organization_id            => p_organization_id
5171           , p_inventory_item_id          => p_inventory_item_id
5172           , p_serial_number              => g_locs(p_record_id).serial_number
5173           , x_found                      => l_found
5174           , x_return_status              => x_return_status
5175           , x_msg_count                  => x_msg_count
5176           , x_msg_data                   => x_msg_data
5177           );
5178 
5179           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5180             IF l_debug = 1 THEN
5181                log_statement(l_api_name, 'uerr_search_sn', 'Unexpected error in search_serial_numbers');
5182             END IF;
5183             RAISE fnd_api.g_exc_unexpected_error;
5184           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5185             IF l_debug = 1 THEN
5186                log_statement(l_api_name, 'err_search_sn', 'Error in search_serial_numbers');
5187             END IF;
5188             RAISE fnd_api.g_exc_error;
5189           END IF;
5190 
5191           IF l_found THEN
5192             IF p_debug_on THEN
5193               g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
5194             END IF;
5195             IF l_debug = 1 THEN
5196                log_event(l_api_name, 'sn_used', 'Serial Number has been used');
5197             END IF;
5198             g_locs(p_record_id).quantity  := 0;
5199             x_allocated_quantity          := 0;
5200             x_remaining_quantity          := 0;
5201             x_inserted_record             := FALSE;
5202             RETURN;
5203           END IF;
5204 
5205           IF p_debug_on THEN
5206             g_trace_recs(p_record_id).serial_number_used_flag  := 'Y';
5207           END IF;
5208         END IF;
5209 
5210         --If we are factoring in Pick UOM, convert quantity into Pick UOM.
5211         --Then, find the the largest non-decimal quantity in Pick UOM.  Convert
5212         --back to primary UOM
5213         -- if Uom code is null, than use primary uom
5214         -- if pick uom = primary uom, skip conversions
5215 
5216         l_orig_allocation_quantity  := l_allocation_quantity;
5217 
5218         IF  p_use_pick_uom
5219             AND g_locs(p_record_id).uom_code IS NOT NULL
5220             AND g_locs(p_record_id).uom_code <> p_primary_uom THEN
5221 
5222           IF l_debug = 1 THEN
5223              log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
5224           END IF;
5225           --convert from primary uom to pick uom
5226           l_possible_uom_qty  := inv_convert.inv_um_convert(
5227                                    p_inventory_item_id
5228                                  , NULL
5229                                  , l_allocation_quantity
5230                                  , p_primary_uom
5231                                  , g_locs(p_record_id).uom_code
5232                                  , NULL
5233                                  , NULL
5234                                  );
5235 
5236           --if no conversion defined or some error in conversion,
5237           --inv_um_convert returns -99999.  In this case, don't carry
5238           --out any more conversion functions.  possible quantity
5239           --remains unchanged
5240           IF (l_possible_uom_qty <> -99999) THEN
5241             --don't want to pick fractional amounts of pick uom
5242             l_possible_uom_qty     := FLOOR(l_possible_uom_qty);
5243 
5244             IF l_debug = 1 THEN
5245                log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
5246             END IF;
5247             --convert back to primary uom
5248             l_allocation_quantity  := inv_convert.inv_um_convert(
5249                                         p_inventory_item_id
5250                                       , NULL
5251                                       , l_possible_uom_qty
5252                                       , g_locs(p_record_id).uom_code
5253                                       , p_primary_uom
5254                                       , NULL
5255                                       , NULL
5256                                       );
5257             IF l_debug = 1 THEN
5258                log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: ' || l_allocation_quantity);
5259             END IF;
5260           END IF;
5261         END IF;
5262 
5263         --populate remaining quantity
5264         x_remaining_quantity        := l_orig_allocation_quantity - l_allocation_quantity;
5265         IF l_debug = 1 THEN
5266            log_statement(l_api_name, 'rem_qty', 'remaining_quantity : ' || x_remaining_quantity);
5267         END IF;
5268 
5269         IF l_allocation_quantity <= 0 THEN
5270           IF l_debug = 1 THEN
5271              log_statement(l_api_name, 'no_alloc_qty', 'Quantity remaining to allocate.  Exiting.');
5272           END IF;
5273           x_allocated_quantity  := 0;
5274           x_inserted_record     := FALSE;
5275           RETURN;
5276         END IF;
5277 
5278         --Lock Serial number, so that no other detailing process
5279         -- can use it.
5280         IF g_locs(p_record_id).serial_number IS NOT NULL THEN
5281           l_found  := inv_detail_util_pvt.lock_serial_number(p_inventory_item_id, g_locs(p_record_id).serial_number);
5282 
5283           IF l_found = FALSE THEN
5284             IF l_debug = 1 THEN
5285                log_statement(l_api_name, 'lock_sn', 'Could not lock Serial Number. Exiting.');
5286             END IF;
5287 
5288             IF p_debug_on THEN
5289               g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
5290             END IF;
5291 
5292             x_remaining_quantity  := g_locs(p_record_id).quantity;
5293             x_allocated_quantity  := 0;
5294             x_inserted_record     := FALSE;
5295             RETURN;
5296           END IF;
5297 
5298           -- add serial number to pl/sql table of detailed serials
5299           inv_detail_util_pvt.add_serial_number(p_inventory_item_id, p_organization_id, g_locs(p_record_id).serial_number, l_serial_index);
5300         END IF;
5301 
5302         --If quantity remaining to allocate is greater than 0, update the
5303         --quantity tree and insert the record into WTT
5304         IF p_transaction_uom = p_primary_uom THEN
5305           l_possible_trx_qty  := l_allocation_quantity;
5306         ELSE
5307           l_possible_trx_qty  :=
5308                      inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_allocation_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
5309         END IF;
5310         IF l_debug = 1 THEN
5311            log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Trx Qty: ' || l_possible_trx_qty);
5312         END IF;
5313         -- insert temporary suggestion
5314         INSERT INTO wms_transactions_temp
5315                     (
5316                     pp_transaction_temp_id
5317                   , transaction_temp_id
5318                   , type_code
5319                   , line_type_code
5320                   , transaction_quantity
5321                   , primary_quantity
5322                   , revision
5323                   , lot_number
5324                   , lot_expiration_date
5325                   , from_subinventory_code
5326                   , from_locator_id
5327                   , rule_id
5328                   , reservation_id
5329                   , serial_number
5330                   , to_subinventory_code
5331                   , to_locator_id
5332                   , from_cost_group_id
5333                   , to_cost_group_id
5334                   , lpn_id
5335                     )
5336              VALUES (
5337                     wms_transactions_temp_s.NEXTVAL
5338                   , p_transaction_temp_id
5339                   , p_type_code
5340                   , 2 -- line type code is output
5341                   , l_possible_trx_qty
5342                   , l_allocation_quantity
5343                   , g_locs(p_record_id).revision
5344                   , g_locs(p_record_id).lot_number
5345                   , g_locs(p_record_id).lot_expiration_date
5346                   , g_locs(p_record_id).subinventory_code
5347                   , g_locs(p_record_id).locator_id
5348                   , p_rule_id
5349                   , p_reservation_id
5350                   , g_locs(p_record_id).serial_number
5351                   , p_to_subinventory_code
5352                   , p_to_locator_id
5353                   , g_locs(p_record_id).cost_group_id
5354                   , p_to_cost_group_id
5355                   , g_locs(p_record_id).lpn_id
5356                     );
5357         IF l_debug = 1 THEN
5358            log_statement(l_api_name, 'finish_insert_wtt', 'Finished inserting wtt recs.');
5359            log_statement(l_api_name, 'alloc_qty', 'Alloc qty: ' || l_allocation_quantity);
5360         END IF;
5361 
5362         IF p_debug_on THEN
5363           g_trace_recs(p_record_id).suggested_qty  := l_allocation_quantity;
5364         END IF;
5365 
5366         x_inserted_record           := TRUE;
5367         x_allocated_quantity        := l_allocation_quantity;
5368         IF l_debug = 1 THEN
5369            log_statement(l_api_name, 'alloc_qty', 'Allocated quantity: ' || x_allocated_quantity);
5370            log_procedure(l_api_name, 'end', 'End Validate_and_Insert');
5371         END IF;
5372 
5373       EXCEPTION
5374         WHEN fnd_api.g_exc_error THEN
5375           x_return_status  := fnd_api.g_ret_sts_error;
5376           fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5377           --
5378           IF l_debug = 1 THEN
5379              log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
5380           END IF;
5381 
5382         WHEN fnd_api.g_exc_unexpected_error THEN
5383           x_return_status  := fnd_api.g_ret_sts_unexp_error;
5384           fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5385           IF l_debug = 1 THEN
5386              log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
5387           END IF;
5388 
5389         WHEN OTHERS THEN
5390           x_return_status  := fnd_api.g_ret_sts_unexp_error;
5391 
5392           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
5393             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
5394           END IF;
5395 
5396           fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5397           IF l_debug = 1 THEN
5398              log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
5399           END IF;
5400 
5401   END ValidNinsert;
5402 
5403   -- End of bug #4006426 ---
5404 
5405 
5406   PROCEDURE rollback_consist_allocations(
5407     x_return_status OUT NOCOPY    VARCHAR2
5408   , x_msg_count     OUT NOCOPY    NUMBER
5409   , x_msg_data      OUT NOCOPY    VARCHAR2
5410   , p_group_id      IN            NUMBER
5411   , p_tree_id       IN            NUMBER
5412   , p_type_code     IN            NUMBER
5413   , p_first_uom_rec IN            NUMBER
5414   , p_last_uom_rec  IN            NUMBER
5415   , p_prev_rec      IN            NUMBER
5416   , p_next_rec      IN            NUMBER
5417   , p_debug_on      IN            BOOLEAN
5418   ) IS
5419     l_api_name    VARCHAR2(30) := 'rollback_consist_allocations';
5420     l_current_loc NUMBER;
5421     l_next_rec    NUMBER;
5422 
5423     l_debug       NUMBER;
5424   BEGIN
5425     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
5426        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
5427      END IF;
5428     l_debug := g_debug;
5429 
5430     IF l_debug = 1 THEN
5431        log_procedure(l_api_name, 'Start', 'Start Rollback_Consist_Allocations');
5432        -- rollback the changes we've made
5433        log_statement(l_api_name, 'consist_not_enough_qty', 'Not enough quantity in this consistency group. ' || 'Rolling back suggestions');
5434        log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
5435     END IF;
5436     inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
5437 
5438     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5439       IF l_debug = 1 THEN
5440          log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
5441       END IF;
5442       RAISE fnd_api.g_exc_unexpected_error;
5443     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5444       IF l_debug = 1  THEN
5445          log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
5446       END IF;
5447       RAISE fnd_api.g_exc_error;
5448     END IF;
5449 
5450     --put pick UOM records back into the list;
5451     --we need to put this records between after the last
5452     --record that has the current order by string, since
5453     --these recs have the same order by string.  The last rec
5454     --with the same order by string is stored in l_prev_rec,
5455     --and the first rec with the next order by string is l_loc_id
5456     --We only do this is the pick uom list is populated
5457     IF l_debug = 1 THEN
5458        log_statement(l_api_name, 'p_first_uom_rec', 'first_uom_rec: ' || p_first_uom_rec);
5459        log_statement(l_api_name, 'p_next_rec', 'next_rec: ' || p_next_rec);
5460        log_statement(l_api_name, 'p_prev_rec', 'prev_rec: ' || p_prev_rec);
5461     END IF;
5462     IF p_first_uom_rec <> 0 THEN
5463       IF p_next_rec IS NULL THEN
5464         l_next_rec  := p_prev_rec;
5465 
5466         LOOP
5467           EXIT WHEN NVL(l_next_rec, 0) = 0;
5468           EXIT WHEN g_locs(l_next_rec).order_by_string <> g_locs(p_prev_rec).order_by_string;
5469           l_next_rec  := g_locs(l_next_rec).next_rec;
5470         END LOOP;
5471       ELSE
5472         l_next_rec  := p_next_rec;
5473       END IF;
5474 
5475       IF p_prev_rec = 0 THEN
5476         g_consists(p_group_id).first_rec  := p_first_uom_rec;
5477       ELSE
5478         g_locs(p_prev_rec).next_rec  := p_first_uom_rec;
5479       END IF;
5480 
5481       g_locs(p_last_uom_rec).next_rec  := l_next_rec;
5482     END IF;
5483 
5484     --loop through trace recs, updating recs for this consist
5485     -- group to change consist_string_flag from Y to N
5486     -- and to set suggested quantity back to 0
5487     IF p_debug_on THEN
5488 
5489       l_current_loc  := g_consists(p_group_id).first_rec;
5490       IF l_debug = 1 THEN
5491          log_statement(l_api_name, 'trace', 'Updating trace records');
5492          log_statement(l_api_name, 'first_loc', 'First rec to update: ' || l_current_loc);
5493       END IF ;
5494 
5495       --loop through each record in this consist group
5496       LOOP
5497         EXIT WHEN NVL(l_current_loc, 0) = 0;
5498         --update the trace records
5499         g_trace_recs(l_current_loc).consist_string_flag  := 'N';
5500         g_trace_recs(l_current_loc).suggested_qty        := 0;
5501         l_current_loc                                    := g_locs(l_current_loc).next_rec;
5502         IF l_debug = 1 THEN
5503            log_statement(l_api_name, 'current_loc', 'Current rec: ' || l_current_loc);
5504         END IF ;
5505       END LOOP;
5506     END IF;
5507 
5508     DELETE FROM wms_transactions_temp
5509           WHERE line_type_code = 2
5510             AND type_code = p_type_code;
5511     IF l_debug = 1 THEN
5512        log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
5513        log_procedure(l_api_name, 'End', 'End Rollback_Consist_Allocations');
5514     END IF;
5515   EXCEPTION
5516     WHEN fnd_api.g_exc_error THEN
5517       x_return_status  := fnd_api.g_ret_sts_error;
5518       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5519       IF l_debug = 1 THEN
5520          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
5521       END IF;
5522 
5523     WHEN fnd_api.g_exc_unexpected_error THEN
5524       x_return_status  := fnd_api.g_ret_sts_unexp_error;
5525       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5526       IF l_debug = 1 THEN
5527          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
5528       END IF;
5529 
5530     WHEN OTHERS THEN
5531       x_return_status  := fnd_api.g_ret_sts_unexp_error;
5532 
5533       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
5534         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
5535       END IF;
5536 
5537       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5538       IF l_debug = 1 THEN
5539          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
5540       END IF;
5541 
5542   END rollback_consist_allocations;
5543 
5544   PROCEDURE allocate_consist_group(
5545     x_return_status        OUT NOCOPY    VARCHAR2
5546   , x_msg_count            OUT NOCOPY    NUMBER
5547   , x_msg_data             OUT NOCOPY    VARCHAR2
5548   , p_group_id             IN            NUMBER
5549   , p_needed_quantity      IN            NUMBER
5550   , p_use_pick_uom         IN            BOOLEAN
5551   , p_organization_id      IN            NUMBER
5552   , p_inventory_item_id    IN            NUMBER
5553   , p_to_subinventory_code IN            VARCHAR2
5554   , p_to_locator_id        IN            NUMBER
5555   , p_to_cost_group_id     IN            NUMBER
5556   , p_primary_uom          IN            VARCHAR2
5557   , p_transaction_uom      IN            VARCHAR2
5558   , p_transaction_temp_id  IN            NUMBER
5559   , p_type_code            IN            NUMBER
5560   , p_rule_id              IN            NUMBER
5561   , p_reservation_id       IN            NUMBER
5562   , p_tree_id              IN            NUMBER
5563   , p_debug_on             IN            BOOLEAN
5564   , p_needed_sec_quantity  IN            NUMBER                        -- new
5565   , p_secondary_uom        IN            VARCHAR2                      -- new
5566   , p_grade_code           IN            VARCHAR2                      -- new
5567   , p_lot_divisible_flag   IN            VARCHAR2                      -- new
5568   , x_success              OUT NOCOPY    BOOLEAN
5569   ) IS
5570     l_api_name                 VARCHAR2(30)   := 'allocate_consist_group';
5571     l_loc_id                   NUMBER;
5572     l_current_order_by_string  VARCHAR2(1000) := NULL;
5573     l_first_rec_uom            NUMBER         := 0;
5574     l_last_rec_uom             NUMBER         := 0;
5575     l_last_rec_cur_uom         NUMBER         := 0;
5576     l_uom_loc_id               NUMBER;
5577     l_needed_quantity          NUMBER;
5578     l_inserted_record          BOOLEAN;
5579     l_allocated_quantity       NUMBER;
5580     l_remaining_quantity       NUMBER;
5581     l_expected_quantity        NUMBER;
5582     l_sec_needed_quantity      NUMBER;                  -- new
5583     l_sec_allocated_quantity   NUMBER;                  -- new
5584     l_sec_remaining_quantity   NUMBER;                  -- new
5585     l_sec_expected_quantity    NUMBER;                  -- new
5586     l_current_loc              NUMBER;
5587     l_prev_rec                 NUMBER         := 0;
5588     l_original_needed_quantity NUMBER;
5589     l_uom_index                NUMBER;
5590 
5591     l_debug                    NUMBER;
5592   BEGIN
5593     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
5594        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
5595     END IF;
5596     l_debug := g_debug;
5597 
5598     IF l_debug = 1 THEN
5599        log_procedure(l_api_name, 'Start', 'Start Allocate_Consist_Group');
5600     END IF;
5601     l_needed_quantity           := p_needed_quantity;
5602     l_original_needed_quantity  := p_needed_quantity;
5603     l_loc_id                    := g_consists(p_group_id).first_rec;
5604     x_success                   := FALSE;
5605 
5606     --for each record in the consistency group
5607     LOOP
5608       EXIT WHEN l_loc_id = 0;
5609 
5610       --Allocation from pick UOM list if this rec's order string is not
5611       -- equal to previous rec's order string and we are using pick UOM
5612       -- and the pick UOM list is not empty
5613       IF  NVL(l_current_order_by_string, '@@@') <> NVL(g_locs(l_loc_id).order_by_string, '@@@')
5614           AND p_use_pick_uom
5615           AND l_first_rec_uom <> 0 THEN
5616         IF l_debug = 1 THEN
5617            log_statement(l_api_name, 'pick_uom', 'Allocating pick UOM records');
5618         END IF;
5619 
5620         l_uom_loc_id  := l_first_rec_uom;
5621 
5622         --for each record in Pick UOM table
5623         LOOP
5624           EXIT WHEN l_uom_loc_id = 0;
5625           l_expected_quantity  := g_locs(l_uom_loc_id).quantity;
5626 
5627           --validate_and_insert will allocation no more than needed quantity
5628           IF l_needed_quantity < l_expected_quantity THEN
5629             l_expected_quantity  := l_needed_quantity;
5630           END IF;
5631           IF l_debug = 1 THEN
5632              log_statement(l_api_name, 'exp_qty', 'Expected Qty: ' || l_expected_quantity);
5633              log_statement(l_api_name, 'val_insert', 'Calling Validate and Insert');
5634           END IF;
5635         --call helper procedure to validate and insert record
5636           validate_and_insert(
5637             x_return_status              => x_return_status
5638           , x_msg_count                  => x_msg_count
5639           , x_msg_data                   => x_msg_data
5640           , p_record_id                  => l_uom_loc_id
5641           , p_needed_quantity            => l_needed_quantity
5642           , p_use_pick_uom               => FALSE
5643           , p_organization_id            => p_organization_id
5644           , p_inventory_item_id          => p_inventory_item_id
5645           , p_to_subinventory_code       => p_to_subinventory_code
5646           , p_to_locator_id              => p_to_locator_id
5647           , p_to_cost_group_id           => p_to_cost_group_id
5648           , p_primary_uom                => p_primary_uom
5649           , p_transaction_uom            => p_transaction_uom
5650           , p_transaction_temp_id        => p_transaction_temp_id
5651           , p_type_code                  => p_type_code
5652           , p_rule_id                    => p_rule_id
5653           , p_reservation_id             => p_reservation_id
5654           , p_tree_id                    => p_tree_id
5655           , p_debug_on                   => p_debug_on
5656           , p_needed_sec_quantity        => l_sec_needed_quantity
5657           , p_secondary_uom              => p_secondary_uom
5658           , p_grade_code                 => p_grade_code
5659           , x_inserted_record            => l_inserted_record
5660           , x_allocated_quantity         => l_allocated_quantity
5661           , x_remaining_quantity         => l_remaining_quantity
5662           , x_sec_allocated_quantity     => l_sec_allocated_quantity
5663           , x_sec_remaining_quantity     => l_sec_remaining_quantity
5664           );
5665 
5666           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5667             IF l_debug = 1 THEN
5668                log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
5669             END IF;
5670             RAISE fnd_api.g_exc_unexpected_error;
5671           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5672             IF l_debug = 1 THEN
5673                log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
5674             END IF;
5675             RAISE fnd_api.g_exc_error;
5676           END IF;
5677 
5678           --If function did not insert full quantity, decrease group qty
5679           IF l_expected_quantity > l_allocated_quantity THEN
5680             IF l_debug = 1 THEN
5681                log_statement(l_api_name, 'did_not_alloc_full', 'Not all of the expected quantity was allocated');
5682             END IF;
5683             g_consists(p_group_id).quantity  := g_consists(p_group_id).quantity - (l_expected_quantity - l_allocated_quantity);
5684             IF l_debug = 1 THEN
5685                log_statement(l_api_name, 'new_group_qty', 'New group quantity: ' || g_consists(p_group_id).quantity);
5686             END IF;
5687             g_locs(l_uom_loc_id).quantity    := l_allocated_quantity;
5688             g_locs(l_uom_loc_id).secondary_quantity    := l_sec_allocated_quantity;
5689 
5690             --If group qty is now less than needed qty, rollback and return
5691             IF g_consists(p_group_id).quantity < l_original_needed_quantity THEN
5692               IF l_debug = 1 THEN
5693               log_statement(
5694                 l_api_name
5695               , 'rollback_consist'
5696               , 'Not enough quantity in consist group. Calling ' || 'rollback consist allocations.'
5697               );
5698 
5699               END IF;
5700 
5701               rollback_consist_allocations(
5702                 x_return_status              => x_return_status
5703               , x_msg_count                  => x_msg_count
5704               , x_msg_data                   => x_msg_data
5705               , p_group_id                   => p_group_id
5706               , p_tree_id                    => p_tree_id
5707               , p_type_code                  => p_type_code
5708               , p_first_uom_rec              => l_first_rec_uom
5709               , p_last_uom_rec               => l_last_rec_uom
5710               , p_prev_rec                   => l_prev_rec
5711               , p_next_rec                   => l_loc_id
5712               , p_debug_on                   => p_debug_on
5713               );
5714 
5715               IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5716                 IF l_debug = 1 THEN
5717                    log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
5718                 END IF;
5719                 RAISE fnd_api.g_exc_unexpected_error;
5720               ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5721                 IF l_debug = 1 THEN
5722                    log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
5723                 END IF;
5724                 RAISE fnd_api.g_exc_error;
5725               END IF;
5726               IF l_debug = 1 THEN
5727                  log_statement(l_api_name, 'after_rollback_consist', 'Rolled back the allocations.  Exiting');
5728               END IF;
5729               x_success  := FALSE;
5730               RETURN;
5731             END IF;
5732           END IF;
5733 
5734           IF p_debug_on THEN
5735             g_trace_recs(l_uom_loc_id).consist_string_flag  := 'Y';
5736           END IF;
5737 
5738           --Decrease remaining qty to be allocated
5739           l_needed_quantity    := l_needed_quantity - l_allocated_quantity;
5740           l_sec_needed_quantity    := l_sec_needed_quantity - l_sec_allocated_quantity;
5741 
5742           --if no qty left to detail, exit pick UOM loop
5743           IF l_needed_quantity <= 0 THEN
5744             IF l_debug = 1 THEN
5745                log_statement(l_api_name, 'no_more_qty', 'Allocated all the needed quantity.  Exiting.');
5746             END IF;
5747             x_success  := TRUE;
5748             RETURN;
5749           END IF;
5750           IF l_debug = 1 THEN
5751              log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
5752           END IF;
5753           l_uom_loc_id         := g_locs(l_uom_loc_id).next_rec;
5754         END LOOP;
5755       END IF;
5756 
5757       l_current_order_by_string  := g_locs(l_loc_id).order_by_string;
5758       -- Call validate_and_insert on current record
5759       -- If group qty is now less than needed qty, rollback and return
5760       -- If remaining qty > 0 and use Pick UOM, add new record to pick uom table
5761       -- decrease remaining qty to be allocated
5762       -- exit when no more qty left to detail
5763       l_expected_quantity        := g_locs(l_loc_id).quantity;
5764 
5765       --validate_and_insert will allocation no more than needed quantity
5766       IF l_needed_quantity < l_expected_quantity THEN
5767         l_expected_quantity  := l_needed_quantity;
5768       END IF;
5769       IF l_debug = 1 THEN
5770       	 log_statement(l_api_name, 'exp_qty', 'Expected Qty: ' || l_expected_quantity);
5771       	 log_statement(l_api_name, 'val_insert', 'Calling Validate and Insert');
5772       END IF;
5773       -- Added the following  restriction - 5258131
5774      IF  (l_needed_quantity >  l_expected_quantity   AND  p_lot_divisible_flag  = 'N')
5775        OR  (NVL(p_lot_divisible_flag, 'Y')  = 'Y')  THEN
5776        validate_and_insert(
5777         x_return_status              => x_return_status
5778       , x_msg_count                  => x_msg_count
5779       , x_msg_data                   => x_msg_data
5780       , p_record_id                  => l_loc_id
5781       , p_needed_quantity            => l_needed_quantity
5782       , p_use_pick_uom               => p_use_pick_uom
5783       , p_organization_id            => p_organization_id
5784       , p_inventory_item_id          => p_inventory_item_id
5785       , p_to_subinventory_code       => p_to_subinventory_code
5786       , p_to_locator_id              => p_to_locator_id
5787       , p_to_cost_group_id           => p_to_cost_group_id
5788       , p_primary_uom                => p_primary_uom
5789       , p_transaction_uom            => p_transaction_uom
5790       , p_transaction_temp_id        => p_transaction_temp_id
5791       , p_type_code                  => p_type_code
5792       , p_rule_id                    => p_rule_id
5793       , p_reservation_id             => p_reservation_id
5794       , p_tree_id                    => p_tree_id
5795       , p_debug_on                   => p_debug_on
5796       , p_needed_sec_quantity        => l_sec_needed_quantity
5797       , p_secondary_uom              => p_secondary_uom
5798       , p_grade_code                 => p_grade_code
5799       , x_inserted_record            => l_inserted_record
5800       , x_allocated_quantity         => l_allocated_quantity
5801       , x_remaining_quantity         => l_remaining_quantity
5802       , x_sec_allocated_quantity     => l_sec_allocated_quantity
5803       , x_sec_remaining_quantity     => l_sec_remaining_quantity
5804       );
5805 
5806        IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5807         IF l_debug = 1 THEN
5808            log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
5809         END IF;
5810         RAISE fnd_api.g_exc_unexpected_error;
5811        ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5812         IF l_debug = 1 THEN
5813            log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
5814         END IF;
5815         RAISE fnd_api.g_exc_error;
5816        END IF;
5817       END IF; -- End of If 5258131
5818       --If function did not insert full quantity, decrease group qty
5819       IF l_expected_quantity > l_allocated_quantity THEN
5820         IF l_debug = 1 THEN
5821            log_statement(l_api_name, 'did_not_alloc_full', 'Not all of the expected quantity was allocated');
5822         END IF;
5823         g_consists(p_group_id).quantity  := g_consists(p_group_id).quantity - (l_expected_quantity - l_allocated_quantity);
5824         IF l_debug = 1 THEN
5825            log_statement(l_api_name, 'new_group_qty', 'New group quantity: ' || g_consists(p_group_id).quantity);
5826         END IF;
5827         g_locs(l_loc_id).quantity        := l_allocated_quantity;
5828         g_locs(l_loc_id).secondary_quantity        := l_sec_allocated_quantity;
5829 
5830         --If group qty is now less than needed qty, rollback and return
5831         IF g_consists(p_group_id).quantity < l_original_needed_quantity THEN
5832           --out of records with cur_consist_string;
5833           -- rollback the changes we've made
5834           IF l_debug = 1 THEN
5835              log_statement(l_api_name, 'rollback_consist', 'Not enough quantity in consist group. Calling ' || 'rollback consist allocations.');
5836           END IF;
5837          rollback_consist_allocations(
5838             x_return_status              => x_return_status
5839           , x_msg_count                  => x_msg_count
5840           , x_msg_data                   => x_msg_data
5841           , p_group_id                   => p_group_id
5842           , p_tree_id                    => p_tree_id
5843           , p_type_code                  => p_type_code
5844           , p_first_uom_rec              => l_first_rec_uom
5845           , p_last_uom_rec               => l_last_rec_uom
5846           , p_prev_rec                   => l_loc_id
5847           , p_next_rec                   => NULL
5848           , p_debug_on                   => p_debug_on
5849           );
5850 
5851           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5852             IF l_debug = 1 THEN
5853                log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
5854             END IF;
5855             RAISE fnd_api.g_exc_unexpected_error;
5856           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5857             IF l_debug = 1 THEN
5858                log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
5859             END IF;
5860             RAISE fnd_api.g_exc_error;
5861           END IF;
5862           IF l_debug = 1 THEN
5863              log_statement(l_api_name, 'after_rollback_consist', 'Rolled back the allocations.  Exiting');
5864           END IF;
5865           x_success  := FALSE;
5866           RETURN;
5867         END IF;
5868       END IF;
5869 
5870       IF p_debug_on THEN
5871         g_trace_recs(l_loc_id).consist_string_flag  := 'Y';
5872       END IF;
5873 
5874       --Decrease remaining qty to be allocated
5875       l_needed_quantity          := l_needed_quantity - l_allocated_quantity;
5876       l_sec_needed_quantity          := l_sec_needed_quantity - l_sec_allocated_quantity;
5877 
5878       --if no qty left to detail, exit loop
5879       IF l_needed_quantity <= 0 THEN
5880         x_success  := TRUE;
5881         IF l_debug = 1 THEN
5882            log_statement(l_api_name, 'no_more_qty', 'Allocated all the needed quantity.  Exiting.');
5883         END IF;
5884         RETURN;
5885       END IF;
5886       IF l_debug = 1 THEN
5887          log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
5888       END IF;
5889       --handle pick UOM
5890       IF  l_remaining_quantity > 0
5891           AND p_use_pick_uom THEN
5892         IF l_debug = 1 THEN
5893            log_statement(l_api_name, 'create_pick_uom', 'Create a pick UOM record.Remaining quantity:' || l_remaining_quantity);
5894         END IF;
5895 
5896         --create new record if necessary
5897         IF l_remaining_quantity < g_locs(l_loc_id).quantity THEN
5898           g_locs_index                   := g_locs_index + 1;
5899           g_locs(g_locs_index)           := g_locs(l_loc_id);
5900           g_locs(g_locs_index).quantity  := l_remaining_quantity;
5901           g_locs(l_loc_id).quantity      := g_locs(l_loc_id).quantity - l_remaining_quantity;
5902           l_uom_index                    := g_locs_index;
5903           l_prev_rec                     := l_loc_id;
5904         ELSE
5905           --if  could not be allocated, remove record from
5906           --current linked list
5907           IF l_prev_rec <> 0 THEN
5908             g_locs(l_prev_rec).next_rec  := g_locs(l_loc_id).next_rec;
5909           ELSE
5910             g_consists(p_group_id).first_rec  := g_locs(l_loc_id).next_rec;
5911           END IF;
5912 
5913           l_uom_index  := l_loc_id;
5914         --if rec is removed from link list, prev_rec does not change
5915         END IF;
5916 
5917         --set pointers
5918         -- new record is first record in table
5919         IF l_first_rec_uom = 0 THEN
5920           l_first_rec_uom               := l_uom_index;
5921           l_last_rec_cur_uom            := l_uom_index;
5922           l_last_rec_uom                := l_uom_index;
5923           g_locs(l_uom_index).next_rec  := 0;
5924           IF l_debug = 1 THEN
5925              log_statement(l_api_name, 'first_rec', 'The saved uom record is the first record in table');
5926           END IF;
5927         -- new record is first record with that uom code
5928         ELSIF g_locs(l_first_rec_uom).uom_code <> g_locs(l_uom_index).uom_code THEN
5929           g_locs(l_uom_index).next_rec  := l_first_rec_uom;
5930           l_first_rec_uom               := l_uom_index;
5931           l_last_rec_cur_uom            := l_uom_index;
5932           IF l_debug = 1 THEN
5933              log_statement(l_api_name, 'first_rec_uom', 'The saved uom record is the first record for uom in table');
5934           END IF;
5935         -- records with this uom code already exist in table
5936         ELSE
5937           g_locs(l_uom_index).next_rec         := g_locs(l_last_rec_cur_uom).next_rec;
5938           g_locs(l_last_rec_cur_uom).next_rec  := l_uom_index;
5939           l_last_rec_cur_uom                   := l_uom_index;
5940 
5941           IF g_locs(l_uom_index).next_rec = 0 THEN
5942             l_last_rec_uom  := l_uom_index;
5943           END IF;
5944           IF l_debug = 1 THEN
5945              log_statement(l_api_name, 'not_first_rec_uom', 'The saved record is not first record for uom in table');
5946           END IF;
5947         END IF;
5948         IF l_debug = 1 THEN
5949            log_statement(l_api_name, 'saving_loc', 'Storing record in uom table');
5950         END IF;
5951 
5952         IF p_debug_on THEN
5953           --determine if we created a new record or not
5954           IF l_uom_index = g_locs_index THEN
5955             g_trace_recs(g_locs_index)                := g_trace_recs(l_loc_id);
5956             g_trace_recs(l_loc_id).quantity           := g_trace_recs(l_loc_id).quantity - l_remaining_quantity;
5957             g_trace_recs(g_locs_index).quantity       := l_remaining_quantity;
5958             g_trace_recs(l_loc_id).pick_uom_flag      := 'P';
5959             g_trace_recs(g_locs_index).pick_uom_flag  := 'N';
5960           ELSE
5961             g_trace_recs(l_loc_id).pick_uom_flag  := 'N';
5962           END IF;
5963         END IF;
5964       ELSE
5965         l_prev_rec  := l_loc_id;
5966       END IF;
5967 
5968       l_loc_id                   := g_locs(l_loc_id).next_rec;
5969     END LOOP;
5970 
5971     IF l_needed_quantity <= 0 THEN
5972       x_success  := TRUE;
5973     ELSE
5974       --some sort of error occurred in our calculations;
5975       --we thought that there was enough material in the consistency
5976       --group, but we've allocated all the location records, but we have
5977       --not fulfilled all of the needed quantity;
5978       --Rollback the changes.
5979       IF l_debug = 1 THEN
5980       log_statement(
5981         l_api_name
5982       , 'rollback_consist'
5983       ,    'Quantity value on consist group was wrong.  There is not enough '
5984         || 'quantity to allocate in this consist group.. Calling '
5985         || 'rollback consist allocations.'
5986       );
5987       END IF;
5988       rollback_consist_allocations(
5989         x_return_status              => x_return_status
5990       , x_msg_count                  => x_msg_count
5991       , x_msg_data                   => x_msg_data
5992       , p_group_id                   => p_group_id
5993       , p_tree_id                    => p_tree_id
5994       , p_type_code                  => p_type_code
5995       , p_first_uom_rec              => 0
5996       , p_last_uom_rec               => 0
5997       , p_prev_rec                   => 0
5998       , p_next_rec                   => 0
5999       , p_debug_on                   => p_debug_on
6000       );
6001 
6002       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6003         IF l_debug = 1 THEN
6004            log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
6005         END IF;
6006         RAISE fnd_api.g_exc_unexpected_error;
6007       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6008         IF l_debug = 1 THEN
6009            log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
6010         END IF;
6011         RAISE fnd_api.g_exc_error;
6012       END IF;
6013 
6014       x_success  := FALSE;
6015     END IF;
6016     IF l_debug = 1 THEN
6017        log_procedure(l_api_name, 'end', 'End Allocate_Consist_Group');
6018     END IF;
6019   EXCEPTION
6020     WHEN fnd_api.g_exc_error THEN
6021       x_return_status  := fnd_api.g_ret_sts_error;
6022       x_success        := FALSE;
6023       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6024       IF l_debug = 1 THEN
6025          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
6026       END IF;
6027 
6028     WHEN fnd_api.g_exc_unexpected_error THEN
6029       x_return_status  := fnd_api.g_ret_sts_unexp_error;
6030       x_success        := FALSE;
6031       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6032       IF l_debug = 1 THEN
6033          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
6034       END IF;
6035     WHEN OTHERS THEN
6036       x_return_status  := fnd_api.g_ret_sts_unexp_error;
6037       x_success        := FALSE;
6038 
6039       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6040         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
6041       END IF;
6042 
6043       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6044       IF l_debug = 1 THEN
6045          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
6046       END IF;
6047 
6048   END allocate_consist_group;
6049 
6050   PROCEDURE insert_consist_record(
6051     x_return_status        OUT NOCOPY    VARCHAR2
6052   , x_msg_count            OUT NOCOPY    NUMBER
6053   , x_msg_data             OUT NOCOPY    VARCHAR2
6054   , p_record_id            IN            NUMBER
6055   , p_needed_quantity      IN            NUMBER
6056   , p_use_pick_uom         IN            BOOLEAN
6057   , p_organization_id      IN            NUMBER
6058   , p_inventory_item_id    IN            NUMBER
6059   , p_to_subinventory_code IN            VARCHAR2
6060   , p_to_locator_id        IN            NUMBER
6061   , p_to_cost_group_id     IN            NUMBER
6062   , p_primary_uom          IN            VARCHAR2
6063   , p_transaction_uom      IN            VARCHAR2
6064   , p_transaction_temp_id  IN            NUMBER
6065   , p_type_code            IN            NUMBER
6066   , p_rule_id              IN            NUMBER
6067   , p_reservation_id       IN            NUMBER
6068   , p_tree_id              IN            NUMBER
6069   , p_debug_on             IN            BOOLEAN
6070   , p_order_by_rank        IN            NUMBER
6071   , p_needed_sec_quantity  IN            NUMBER                        -- new
6072   , p_secondary_uom        IN            VARCHAR2                      -- new
6073   , p_grade_code           IN            VARCHAR2                      -- new
6074   , x_finished             OUT NOCOPY    BOOLEAN
6075   , x_remaining_quantity   OUT NOCOPY    NUMBER
6076   ) IS
6077     l_api_name               VARCHAR2(30) := 'insert_consist_record';
6078     l_cur_group              NUMBER;
6079     l_hash_size              NUMBER;
6080     l_possible_quantity      NUMBER;
6081     l_needed_quantity        NUMBER;
6082     l_possible_uom_qty       NUMBER;
6083     l_sec_possible_quantity  NUMBER;                 -- new
6084     l_sec_needed_quantity    NUMBER;                 -- new
6085     l_sec_possible_uom_qty   NUMBER;                 -- new
6086 
6087     l_debug             NUMBER;
6088 
6089   BEGIN
6090     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
6091        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6092     END IF;
6093     l_debug := g_debug;
6094     IF l_debug = 1 THEN
6095        log_procedure(l_api_name, 'start', 'Start Insert Consist Record');
6096     END IF;
6097 
6098     x_finished       := FALSE;
6099     -- used in get_hash_value.  That procedure works best if
6100     -- hashsize is power of 2
6101     l_hash_size      := POWER(2, 15);
6102     --get hash index for this consist string
6103     IF l_debug = 1 THEN
6104        log_statement(l_api_name, 'get_hash_value', 'Calling get_hash_value');
6105     END IF;
6106     l_cur_group      := DBMS_UTILITY.get_hash_value(NAME => g_locs(p_record_id).consist_string, base => 1, hash_size => l_hash_size);
6107 
6108     --Because the hash function can return the same index for different
6109     -- consist strings, we have to check to see if the group at the index
6110     -- returned above has the same consist string as the current record.
6111     -- If not, look at the next record.  Continue on until we find the
6112     -- correct consist group or determine that the group has not been defined
6113     -- yet
6114     LOOP
6115       EXIT WHEN NOT g_consists.EXISTS(l_cur_group);
6116       EXIT WHEN g_consists(l_cur_group).consist_string = g_locs(p_record_id).consist_string;
6117       l_cur_group  := l_cur_group + 1;
6118     END LOOP;
6119 
6120     --If we need to take Pick UOM into consideration, we need to determine
6121     -- how much of this record is needed
6122     IF p_use_pick_uom THEN
6123       IF l_debug = 1 THEN
6124          log_statement(l_api_name, 'pick_uom', 'Handle Pick UOM');
6125       END IF;
6126 
6127       IF p_needed_quantity < g_locs(p_record_id).quantity THEN
6128         l_possible_quantity  := p_needed_quantity;
6129       ELSE
6130         l_possible_quantity  := g_locs(p_record_id).quantity;
6131       END IF;
6132 
6133       IF g_consists.EXISTS(l_cur_group) THEN
6134         l_needed_quantity  := p_needed_quantity - g_consists(l_cur_group).quantity;
6135         l_sec_needed_quantity  := p_needed_sec_quantity - g_consists(l_cur_group).secondary_quantity;
6136 
6137         IF l_possible_quantity > l_needed_quantity THEN
6138           l_possible_quantity  := l_needed_quantity;
6139         END IF;
6140       END IF;
6141 
6142       IF NVL(g_locs(p_record_id).uom_code, p_primary_uom) <> p_primary_uom THEN
6143         IF l_debug = 1 THEN
6144            log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
6145         END IF;
6146         --convert from primary uom to pick uom
6147         l_possible_uom_qty  := inv_convert.inv_um_convert(
6148                                  p_inventory_item_id
6149                                , NULL
6150                                , l_possible_quantity
6151                                , p_primary_uom
6152                                , g_locs(p_record_id).uom_code
6153                                , NULL
6154                                , NULL
6155                                );
6156 
6157         --if no conversion defined or some error in conversion,
6158         --inv_um_convert returns -99999.  In this case, don't carry
6159         --out any more conversion functions.  possible quantity
6160         --remains unchanged
6161         IF (l_possible_uom_qty <> -99999) THEN
6162           --don't want to pick fractional amounts of pick uom
6163           l_possible_uom_qty   := FLOOR(l_possible_uom_qty);
6164           IF l_debug = 1 THEN
6165              log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
6166           END IF;
6167           --convert back to primary uom
6168           l_possible_quantity  := inv_convert.inv_um_convert(
6169                                     p_inventory_item_id
6170                                   , NULL
6171                                   , l_possible_uom_qty
6172                                   , g_locs(p_record_id).uom_code
6173                                   , p_primary_uom
6174                                   , NULL
6175                                   , NULL
6176                                   );
6177           IF l_debug = 1 THEN
6178              log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: ' || l_possible_quantity);
6179           END IF;
6180         END IF;
6181       END IF;
6182 
6183       x_remaining_quantity  := g_locs(p_record_id).quantity - l_possible_quantity;
6184     --don't update the g_loc.quantity here.  It'll get updated in Apply.
6185     ELSE
6186       x_remaining_quantity  := 0;
6187       l_possible_quantity   := g_locs(p_record_id).quantity;
6188     END IF;
6189 
6190     IF l_possible_quantity <= 0 THEN
6191       x_finished  := FALSE;
6192       RETURN;
6193     END IF;
6194 
6195     --If group does exist
6196     IF g_consists.EXISTS(l_cur_group) THEN
6197       IF l_debug = 1 THEN
6198          log_statement(l_api_name, 'group_exists', 'The consist group already exists');
6199       END IF;
6200       --set pointer values
6201       --Bug#4361016.Addedthe below IF Block to make sure that no node has next_rec
6202       --pointer pointing to itself because this causes infinite loop.
6203       IF (g_consists(l_cur_group).last_rec = p_record_id) THEN
6204         g_locs(g_consists(l_cur_group).last_rec).next_rec  := 0;
6205       ELSE
6206         g_locs(g_consists(l_cur_group).last_rec).next_rec  := p_record_id;
6207       END IF;
6208       g_consists(l_cur_group).last_rec                   := p_record_id;
6209       --increase group quantity
6210       g_consists(l_cur_group).quantity                   := g_consists(l_cur_group).quantity + l_possible_quantity;
6211     --If group does not exist
6212     ELSE
6213       IF l_debug =1 THEN
6214          log_statement(l_api_name, 'new_group', 'Creating a new consist group');
6215       END IF;
6216       --create new group
6217       g_consists(l_cur_group).consist_string  := g_locs(p_record_id).consist_string;
6218       g_consists(l_cur_group).first_rec       := p_record_id;
6219       g_consists(l_cur_group).last_rec        := p_record_id;
6220       g_consists(l_cur_group).next_group      := 0;
6221       g_consists(l_cur_group).quantity        := l_possible_quantity;
6222       g_consists(l_cur_group).order_by_rank   := p_order_by_rank;
6223 
6224       IF g_first_consist_group = 0 THEN
6225         g_first_consist_group  := l_cur_group;
6226       ELSE
6227         g_consists(g_last_consist_group).next_group  := l_cur_group;
6228       END IF;
6229 
6230       g_last_consist_group                    := l_cur_group;
6231     END IF;
6232 
6233     --If group quantity >= needed qty and the consist group in the first
6234     --  set of records by sort criteria
6235     IF  g_consists(l_cur_group).quantity >= p_needed_quantity
6236         AND g_consists(l_cur_group).order_by_rank = g_first_order_by_rank THEN
6237       IF l_debug = 1 THEN
6238          log_statement(l_api_name, 'alloc_group', 'The consist group has enough quantity to allocation. ' || 'Calling allocate_consist_group.');
6239       END IF;
6240      --call allocate_consist_group
6241       allocate_consist_group(
6242         x_return_status              => x_return_status
6243       , x_msg_count                  => x_msg_count
6244       , x_msg_data                   => x_msg_data
6245       , p_group_id                   => l_cur_group
6246       , p_needed_quantity            => p_needed_quantity
6247       , p_use_pick_uom               => p_use_pick_uom
6248       , p_organization_id            => p_organization_id
6249       , p_inventory_item_id          => p_inventory_item_id
6250       , p_to_subinventory_code       => p_to_subinventory_code
6251       , p_to_locator_id              => p_to_locator_id
6252       , p_to_cost_group_id           => p_to_cost_group_id
6253       , p_primary_uom                => p_primary_uom
6254       , p_transaction_uom            => p_transaction_uom
6255       , p_transaction_temp_id        => p_transaction_temp_id
6256       , p_type_code                  => p_type_code
6257       , p_rule_id                    => p_rule_id
6258       , p_reservation_id             => p_reservation_id
6259       , p_tree_id                    => p_tree_id
6260       , p_debug_on                   => p_debug_on
6261       , p_needed_sec_quantity        => l_sec_needed_quantity
6262       , p_secondary_uom              => p_secondary_uom
6263       , p_grade_code                 => p_grade_code
6264       , p_lot_divisible_flag         => inv_cache.item_rec.lot_divisible_flag
6265       , x_success                    => x_finished
6266       );
6267 
6268       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6269         IF l_debug = 1 THEN
6270            log_error(l_api_name, 'uerr_alloc_consist_group', 'Unexpected error in allocate_consist_group');
6271         END IF;
6272         RAISE fnd_api.g_exc_unexpected_error;
6273       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6274         IF l_debug = 1 THEN
6275            log_error(l_api_name, 'err_alloc_consist_group', 'Error in allocate_consist_group');
6276         END IF;
6277         RAISE fnd_api.g_exc_error;
6278       END IF;
6279     END IF;
6280 
6281     x_return_status  := fnd_api.g_ret_sts_success;
6282     IF l_debug = 1 THEN
6283        log_procedure(l_api_name, 'end', 'End Insert_Consist_Record');
6284     END IF;
6285   EXCEPTION
6286     WHEN fnd_api.g_exc_error THEN
6287       x_return_status  := fnd_api.g_ret_sts_error;
6288       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6289       IF l_debug = 1 THEN
6290          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
6291       END IF;
6292      --
6293     WHEN fnd_api.g_exc_unexpected_error THEN
6294       x_return_status  := fnd_api.g_ret_sts_unexp_error;
6295       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6296       IF l_debug = 1 THEN
6297          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
6298       END IF;
6299 
6300     WHEN OTHERS THEN
6301       x_return_status  := fnd_api.g_ret_sts_unexp_error;
6302 
6303       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6304         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
6305       END IF;
6306 
6307       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6308       IF l_debug = 1 THEN
6309          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
6310       END IF;
6311 
6312   END insert_consist_record;
6313 
6314   PROCEDURE invalidate_lpn_group(p_lpn_id IN NUMBER) IS
6315     l_api_name   VARCHAR2(30) := 'invalidate_lpn_group';
6316     l_prev_group NUMBER;
6317     l_next_group NUMBER;
6318     l_debug      NUMBER;
6319   BEGIN
6320     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
6321        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6322     END IF;
6323     l_debug := g_debug;
6324     IF l_debug = 1 THEN
6325        log_procedure(l_api_name, 'start', 'Start Invalidate_Lpn_Group');
6326        log_statement(l_api_name, 'lpn', 'Invalidating LPN: ' || p_lpn_id);
6327     END IF;
6328     g_lpns(p_lpn_id).total_quantity  := -1;
6329     l_prev_group                     := g_lpns(p_lpn_id).prev_group;
6330     l_next_group                     := g_lpns(p_lpn_id).next_group;
6331     IF l_debug = 1 THEN
6332        log_statement(l_api_name, 'prev', 'Prev LPN: ' || l_prev_group);
6333        log_statement(l_api_name, 'next', 'Next LPN: ' || l_next_group);
6334     END IF;
6335 
6336     IF l_prev_group <> 0 THEN
6337       g_lpns(l_prev_group).next_group  := l_next_group;
6338     END IF;
6339 
6340     IF l_next_group <> 0 THEN
6341       g_lpns(l_next_group).prev_group  := l_prev_group;
6342     END IF;
6343 
6344     IF p_lpn_id = g_first_lpn_group THEN
6345       g_first_lpn_group  := l_next_group;
6346 
6347       IF g_first_lpn_group = 0 THEN
6348         g_first_order_by_rank  := NULL;
6349       ELSE
6350         g_first_order_by_rank  := g_lpns(g_first_lpn_group).order_by_rank;
6351       END IF;
6352     END IF;
6353 
6354     IF g_last_lpn_group = p_lpn_id THEN
6355       g_last_lpn_group  := l_next_group;
6356     END IF;
6357     IF l_debug = 1 THEN
6358        log_procedure(l_api_name, 'end', 'End Invalidate_Lpn_Group');
6359     END IF;
6360   END invalidate_lpn_group;
6361 
6362   --bug 2349283 - the INV_Validate function updates the locator table,
6363   --thus locking the table.  The UpdateLocCapacity function called in
6364   --Apply for putaway rules also updates the locator table, but in a
6365   -- different session.  It tries to get a lock on the table, but
6366   --can't.  So, we get a deadlock.  To resolve this, we make this
6367   -- function a autonomous transaction, and issue a commit at the end.
6368   FUNCTION doprojectcheck(
6369     x_return_status  OUT NOCOPY    VARCHAR2
6370   , p_locator_id     IN            NUMBER
6371   , p_project_id     IN            NUMBER
6372   , p_task_id        IN            NUMBER
6373   , x_new_locator_id IN OUT NOCOPY NUMBER
6374   , x_exist_locator_id	OUT NOCOPY NUMBER --Added bug3237702
6375   )
6376     RETURN BOOLEAN IS
6377     PRAGMA AUTONOMOUS_TRANSACTION;
6378     /*l_locator inv_validate.LOCATOR;
6379     l_org     inv_validate.org;
6380     l_sub     inv_validate.sub;*/
6381     success   NUMBER;
6382     retval    BOOLEAN;
6383   BEGIN
6384    x_exist_locator_id := NULL;
6385     -- If the current locator doesn't have the project and task segments
6386     -- populated, then check if another there is a logical locator for this
6387     -- one with the required
6388     -- project and task and return FALSE. If none exists then create one and
6389     -- return TRUE. If the locator has a project and task that is not equal
6390     -- to the required then return FALSE.
6391     /*SELECT *
6392       INTO l_locator
6393       FROM mtl_item_locations
6394      WHERE inventory_location_id = p_locator_id; Commented bug3237702*/
6395      -- Cache for better performance
6396     if nvl(g_locator_id,-9999) <> p_locator_id THEN
6397        SELECT *
6398        INTO g_locator
6399        FROM MTL_ITEM_LOCATIONS
6400        WHERE inventory_location_id = p_locator_id;
6401     end if;
6402    --Added bug3237702 ends
6403 
6404     --bug 2797980 - added NVL to handle case where task is NULL
6405    IF (g_locator.project_id = p_project_id AND
6406       NVL(g_locator.task_id,-1) = NVL(p_task_id,-1)) THEN
6407      x_new_locator_id := p_locator_id;
6408      RETURN TRUE;
6409   ELSE
6410 	IF g_locator.project_id IS NOT NULL THEN
6411            RETURN FALSE;
6412 	END IF;
6413   END IF;
6414 
6415   g_locator.inventory_location_id := null;
6416   g_locator.physical_location_id := p_locator_id;
6417   g_locator.project_id := p_project_id;
6418   g_locator.task_id := p_task_id;
6419   g_locator.segment19 := p_project_id;
6420   g_locator.segment20 := p_task_id;
6421 
6422   -- Cache for better performance
6423   retval := inv_cache.set_org_rec(g_locator.organization_id);
6424 /*
6425   select *
6426   into l_org
6427   from mtl_parameters
6428   where organization_id = l_locator.organization_id;
6429 */
6430   retval := inv_cache.set_tosub_rec(g_locator.organization_id, g_locator.subinventory_code);
6431 /*  select *
6432   into l_sub
6433   from mtl_secondary_inventories
6434   where secondary_inventory_name = l_locator.subinventory_code
6435   and organization_id = l_locator.organization_id;
6436 */
6437   success := INV_Validate.ValidateLocator(
6438                  p_locator => g_locator,
6439                  p_org => inv_cache.org_rec,
6440                  p_sub => inv_cache.tosub_rec,
6441                  p_validation_mode => INV_Validate.EXISTS_OR_CREATE,
6442                  p_value_or_id => 'I');
6443 
6444   COMMIT;
6445 
6446   x_new_locator_id := g_locator.inventory_location_id;
6447   if( success = INV_Validate.T and FND_FLEX_KEYVAL.new_combination) then
6448      return TRUE;
6449   END IF;
6450 
6451   x_exist_locator_id := g_locator.inventory_location_id;
6452   -- Locator with project segments already exists
6453   return FALSE;
6454 END DoProjectCheck;
6455 
6456   --
6457   -- API name    : Apply
6458   -- Type        : Private
6459   -- Function    : Applies a wms rule to the given transaction
6460   --               input parameters and creates recommendations
6461   -- Pre-reqs    : Record in WMS_STRATEGY_MAT_TXN_TMP_V uniquely
6462   --               identified by parameters p_transaction_temp_id and
6463   --               p_type_code ( base table for the view is
6464   --               MTL_MATERIAL_TRANSACTIONS_TEMP );
6465   --               At least one transaction detail record in
6466   --               WMS_TRX_DETAILS_TMP_V identified by line type code = 1
6467   --               and parameters p_transaction_temp_id and p_type_code
6468   --               ( base tables are MTL_MATERIAL_TRANSACTIONS_TEMP and
6469   --               WMS_TRANSACTIONS_TEMP, respectively );
6470   --               Rule record has to exist in WMS_RULES_B uniquely
6471   --               identified by parameter p_rule_id;
6472   --     Package WMS_RULE_(RULEID) must exist;
6473   --               If picking, quantity tree has to exist, created through
6474   --               INV_Quantity_Tree_PVT.Create_Tree and uniquely identified
6475   --               by parameter p_tree_id
6476   -- Parameters  :
6477   --   p_api_version          Standard Input Parameter
6478   --   p_init_msg_list        Standard Input Parameter
6479   --   p_commit               Standard Input Parameter
6480   --   p_validation_level     Standard Input Parameter
6481   --   p_rule_id              Identifier of the rule to apply
6482   --   p_type_code            Type code of the rule
6483   --   p_partial_success_allowed_flag
6484   --            'Y' or 'N'
6485   --   p_transaction_temp_id  Identifier for the record in view
6486   --            wms_strategy_mat_txn_tmp_v that represents
6487   --            the request for detailing
6488   --   p_organization_id      Organization identifier
6489   --   p_inventory_item_id    Inventory item identifier
6490   --   p_transaction_uom      Transaction UOM code
6491   --   p_primary_uom          Primary UOM code
6492   --   p_tree_id              Identifier for the quantity tree
6493   --
6494   -- Output Parameters
6495   --   x_return_status        Standard Output Parameter
6496   --   x_msg_count            Standard Output Parameter
6497   --   x_msg_data             Standard Output Parameter
6498   --   x_finished             whether the rule has found enough quantity to
6499   --                          find a location that completely satisfy
6500   --                          the requested quantity (value is 'Y' or 'N')
6501   --
6502   -- Version
6503   --   Currently version is 1.0
6504   --
6505   -- Notes       : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
6506   --               This API must be called internally by
6507   --               WMS_Strategy_PVT.Apply only !
6508   --APPLY
6509   PROCEDURE apply(
6510     p_api_version                  IN            NUMBER
6511   , p_init_msg_list                IN            VARCHAR2
6512   , p_commit                       IN            VARCHAR2
6513   , p_validation_level             IN            NUMBER
6514   , x_return_status                OUT NOCOPY    VARCHAR2
6515   , x_msg_count                    OUT NOCOPY    NUMBER
6516   , x_msg_data                     OUT NOCOPY    VARCHAR2
6517   , p_rule_id                      IN            NUMBER
6518   , p_type_code                    IN            NUMBER
6519   , p_partial_success_allowed_flag IN            VARCHAR2
6520   , p_transaction_temp_id          IN            NUMBER
6521   , p_organization_id              IN            NUMBER
6522   , p_inventory_item_id            IN            NUMBER
6523   , p_transaction_uom              IN            VARCHAR2
6524   , p_primary_uom                  IN            VARCHAR2
6525   , p_secondary_uom                IN            VARCHAR2                 -- new
6526   , p_grade_code                   IN            VARCHAR2                 -- new
6527   , p_transaction_type_id          IN            NUMBER
6528   , p_tree_id                      IN            NUMBER
6529   , x_finished                     OUT NOCOPY    VARCHAR2
6530   , p_detail_serial                IN            BOOLEAN
6531   , p_from_serial                  IN            VARCHAR2
6532   , p_to_serial                    IN            VARCHAR2
6533   , p_detail_any_serial            IN            NUMBER
6534   , p_unit_volume                  IN            NUMBER
6535   , p_volume_uom_code              IN            VARCHAR2
6536   , p_unit_weight                  IN            NUMBER
6537   , p_weight_uom_code              IN            VARCHAR2
6538   , p_base_uom_code                IN            VARCHAR2
6539   , p_lpn_id                       IN            NUMBER
6540   , p_unit_number                  IN            VARCHAR2
6541   , p_simulation_mode              IN            NUMBER
6542   , p_project_id                   IN            NUMBER
6543   , p_task_id                      IN            NUMBER
6544   ) IS
6545     -- API standard variables
6546     l_api_version   CONSTANT NUMBER                                              := 1.0;
6547     l_api_name      CONSTANT VARCHAR2(30)                                        := 'Apply';
6548     -- variables needed for dynamic SQL
6549     l_cursor                 INTEGER;
6550     l_rows                   INTEGER;
6551     -- rule dynamic SQL input variables
6552     l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE;
6553     l_revision               wms_transactions_temp.revision%TYPE;
6554     l_lot_number             wms_transactions_temp.lot_number%TYPE;
6555     l_lot_expiration_date    wms_transactions_temp.lot_expiration_date%TYPE;
6556     l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
6557     l_to_subinventory_code   wms_transactions_temp.to_subinventory_code%TYPE;
6558     l_subinventory_code      wms_transactions_temp.to_subinventory_code%TYPE;
6559     l_from_locator_id        wms_transactions_temp.from_locator_id%TYPE;
6560     l_to_locator_id          wms_transactions_temp.to_locator_id%TYPE;
6561     l_locator_id             wms_transactions_temp.to_locator_id%TYPE;
6562     l_from_cost_group_id     wms_transactions_temp.from_cost_group_id%TYPE;
6563     l_to_cost_group_id       wms_transactions_temp.to_cost_group_id%TYPE;
6564     l_cost_group_id          wms_transactions_temp.to_cost_group_id%TYPE;
6565     l_lpn_id                 wms_transactions_temp.lpn_id%TYPE;
6566     l_initial_pri_quantity   wms_transactions_temp.primary_quantity%TYPE;
6567     -- rule dynamic SQL output variables
6568     l_orevision              wms_transactions_temp.revision%TYPE;
6569     l_olot_number            wms_transactions_temp.lot_number%TYPE;
6570     l_olot_expiration_date   wms_transactions_temp.lot_expiration_date%TYPE;
6571     l_osubinventory_code     wms_transactions_temp.from_subinventory_code%TYPE;
6572     l_olocator_id            wms_transactions_temp.from_locator_id%TYPE;
6573     l_olocator_id_prev       wms_transactions_temp.from_locator_id%TYPE;
6574     l_olocator_id_new        wms_transactions_temp.from_locator_id%TYPE;
6575     l_ocost_group_id         wms_transactions_temp.from_cost_group_id%TYPE;
6576     l_olpn_id                wms_transactions_temp.lpn_id%TYPE;
6577     l_possible_quantity      wms_transactions_temp.primary_quantity%TYPE;
6578     l_possible_trx_qty       wms_transactions_temp.transaction_quantity%TYPE;
6579     l_sec_possible_quantity  wms_transactions_temp.secondary_quantity%TYPE;
6580     l_sec_possible_trx_qty   wms_transactions_temp.transaction_quantity%TYPE;
6581     l_reservation_id         wms_transactions_temp.reservation_id%TYPE;
6582     -- variables needed for qty tree
6583     l_qoh                    NUMBER;
6584     l_rqoh                   NUMBER;
6585     l_qr                     NUMBER;
6586     l_qs                     NUMBER;
6587     l_att                    NUMBER;
6588     l_atr                    NUMBER;
6589     l_sqoh                   NUMBER;
6590     l_srqoh                  NUMBER;
6591     l_sqr                    NUMBER;
6592     l_sqs                    NUMBER;
6593     l_satt                   NUMBER;
6594     l_satr                   NUMBER;
6595     --
6596     l_rule_func_sql          LONG;
6597     l_rule_result            NUMBER;
6598     l_dummy                  NUMBER;
6599     l_pack_exists            NUMBER;
6600     l_serial_control_code    NUMBER;
6601     l_is_serial_control      NUMBER;
6602     l_package_name           VARCHAR2(128);
6603     l_msg_data               VARCHAR2(240);
6604     l_msg_count              NUMBER;
6605     l_rule_id                NUMBER;
6606     l_unit_number            VARCHAR2(30);
6607     --variables related to pick by UOM
6608     l_uom_code               VARCHAR2(3);
6609     l_order_by_string        VARCHAR2(1000);
6610     l_consist_string         VARCHAR2(1000);
6611     l_cur_order_by_string    VARCHAR2(1000)                                      := '-9999999';
6612     l_default_pick_rule      NUMBER;
6613     l_default_put_rule       NUMBER;
6614     l_allowed                VARCHAR2(1);
6615     l_loc_avail_units        NUMBER;
6616     l_capacity_updated       BOOLEAN;
6617     l_consider_staging_capacity   BOOLEAN; --Added bug3237702
6618     l_return_status          VARCHAR2(1);
6619     l_consist_exists         BOOLEAN;
6620     l_comingle               VARCHAR2(1);
6621     l_serial_number          VARCHAR2(30);
6622     l_detail_serial          NUMBER;
6623     l_found                  BOOLEAN;
6624     l_first_serial           NUMBER;
6625     l_locs_index             NUMBER; --index to v_locs table
6626     l_debug_on               BOOLEAN;
6627     l_uom_index              NUMBER;
6628     l_lpn_controlled_flag    NUMBER;
6629     l_check_cg               BOOLEAN;
6630     l_restrict_subs_code     NUMBER;
6631     l_restrict_locs_code     NUMBER;
6632     l_quantity_function      NUMBER;
6633     v_current_row            t_location_rec;
6634     --added to support allocation mode
6635     l_cur_lpn_group          NUMBER;
6636     l_cur_lpn_rec            NUMBER;
6637     l_inserted_record        BOOLEAN;
6638     l_needed_quantity        NUMBER;
6639     l_expected_quantity      NUMBER;
6640     l_allocated_quantity     NUMBER;
6641     l_remaining_quantity     NUMBER;
6642     l_allocation_mode        NUMBER;
6643     l_sec_needed_quantity    NUMBER;                          -- new
6644     l_sec_expected_quantity  NUMBER;                          -- new
6645     l_sec_allocated_quantity NUMBER;                          -- new
6646     l_sec_remaining_quantity NUMBER;                          -- new
6647     l_grade_code             VARCHAR2(150);                   -- new
6648     l_cur_uom_rec            NUMBER;
6649     l_first_uom_rec          NUMBER;
6650     l_last_uom_rec           NUMBER;
6651     l_finished               BOOLEAN;
6652     l_cur_consist_group      NUMBER;
6653     l_use_pick_uom           BOOLEAN;
6654     l_order_by_rank          NUMBER                                              := 0;
6655     l_cur_rec                NUMBER;
6656     l_prev_rec               NUMBER;
6657     l_next_rec               NUMBER;
6658     l_hash_size              NUMBER;
6659     l_sub_rsv_type	     NUMBER;
6660 
6661     --added to support pjm
6662     l_project_id             NUMBER;
6663     l_oproject_id            NUMBER;
6664     l_task_id                NUMBER;
6665     l_otask_id               NUMBER;
6666     l_input_lpn_id           NUMBER;
6667     --- Initilization of Ref cursors for Pick and putaway rules
6668     -- Added to pass into DoProjectCheck new parameter used in other apply procedure  Bug3237702
6669     l_dummy_loc              NUMBER;
6670     v_pick_cursor            wms_rule_pvt.cv_pick_type;
6671     v_put_cursor             wms_rule_pvt.cv_put_type;
6672     l_debug                  NUMBER;   -- 1 for debug is on , 0 for debug is off
6673     l_progress               VARCHAR2(10);  -- local variable to track program progress,
6674                                             -- especially useful when exception occurs
6675     l_rule_counter           INTEGER;
6676 
6677     ---- Mat Status Check Variables
6678     l_serial_trx_allowed        VARCHAR2(1);
6679     l_sub_loc_lot_trx_allowed   VARCHAR2(1);
6680     l_serial_status_id          NUMBER;
6681 
6682     ---
6683 
6684     l_serial_status   INV_CACHE.ITEM_REC.serial_status_enabled%TYPE;
6685     l_lot_status      INV_CACHE.ITEM_REC.lot_status_enabled%TYPE;
6686 
6687     ---- End Mat Status Var
6688 
6689     l_lot_divisible_flag       VARCHAR2(1);
6690 
6691     l_rule_override_flag       VARCHAR2(1);
6692     l_lot_control_code         NUMBER;
6693     l_revision_control_code    NUMBER;
6694     l_grade_control_flag       VARCHAR2(1);
6695     l_reservation_is_detailed  VARCHAR2(1);
6696     l_sl_rsv_is_detailed       VARCHAR2(1);
6697 
6698     l_return_value             BOOLEAN; -- [ Added ]
6699    ---
6700     l_allocate_serial_flag     VARCHAR2(1);
6701     l_custom_select_serials    INV_DETAIL_UTIL_PVT.g_serial_row_table_rec;
6702     l_custom_serial_index      NUMBER;
6703 
6704     -- [ Lot Indivisible Var
6705     l_indiv_lot_allowed        VARCHAR2(1); -- [ Added ]
6706     l_max_tolerance 	       NUMBER;
6707     l_min_tolerance            NUMBER;
6708 
6709     -- LPN Status Project
6710     l_onhand_status_trx_allowed VARCHAR2(1);
6711     l_default_status_id        NUMBER ;
6712     -- LPN Status Project
6713 
6714     --cursor to get default rule ids from mtl_parameters table
6715     CURSOR l_default_rules IS
6716       SELECT default_wms_picking_rule_id
6717            , default_put_away_rule_id
6718            , rules_override_lot_reservation
6719         FROM mtl_parameters
6720        WHERE organization_id = p_organization_id;
6721 
6722     --cursor used to determine if item is lot controlled
6723     CURSOR l_cur_serial IS
6724       SELECT serial_number_control_code
6725            , NVL(restrict_subinventories_code, 2)
6726            , NVL(restrict_locators_code, 2)
6727            , lot_divisible_flag
6728            , lot_control_code
6729            , revision_qty_control_code
6730            , grade_control_flag
6731         FROM mtl_system_items
6732        WHERE organization_id = p_organization_id
6733          AND inventory_item_id = p_inventory_item_id;
6734 
6735     --cursor used to determine if the rule package exists
6736     CURSOR l_pack_gen IS
6737       SELECT COUNT(object_name)
6738         FROM user_objects
6739        WHERE object_name = l_package_name;
6740 
6741     --cursor used to determine if suggestions should be minimized
6742     -- for this rule.  This flag affects how the Pick UOM functionality
6743     -- works.
6744     CURSOR c_allocation_mode IS
6745       SELECT allocation_mode_id
6746            , qty_function_parameter_id
6747         FROM wms_rules_b
6748        WHERE rule_id = l_rule_id;
6749 
6750     --cursor used to determine if rule has any consistency requirements
6751     CURSOR l_consist IS
6752       SELECT consistency_id
6753         FROM wms_rule_consistencies
6754        WHERE rule_id = l_rule_id;
6755 
6756     --cursor to get lpn controlled flag from subinventory
6757     CURSOR c_subinventory IS
6758       SELECT lpn_controlled_flag, reservable_type
6759         FROM mtl_secondary_inventories
6760        WHERE organization_id = p_organization_id
6761          AND secondary_inventory_name = l_osubinventory_code;
6762 
6763     --cursor to get the total quantity for the LPN
6764     CURSOR c_lpn_quantity IS
6765       SELECT SUM(primary_transaction_quantity)
6766         FROM mtl_onhand_quantities_detail
6767        WHERE lpn_id = v_current_row.lpn_id;
6768 
6769     --Bug 5251221, cursor to get the serials which are allocated for the current rule
6770     CURSOR l_get_serial IS
6771        SELECT serial_number FROM wms_transactions_temp
6772        WHERE rule_id = l_rule_id;
6773 
6774 
6775   BEGIN
6776     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
6777        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6778     END IF;
6779     l_debug := g_debug;
6780     l_progress := 10;
6781 
6782     -- debugging portion
6783     -- can be commented ut for final code
6784     if nvl(inv_cache.is_pickrelease, FALSE) THEN
6785       If (l_debug = 1) then
6786        log_event(l_api_name, 'Check if Pick Release', 'True');
6787       End if;
6788       l_consider_staging_capacity := FALSE;
6789     else
6790       If (l_debug = 1) then
6791        log_event(l_api_name, 'Check if Pick Release', 'False');
6792       End if;
6793       l_consider_staging_capacity := TRUE;
6794     end if;
6795 
6796     IF l_debug = 1 THEN
6797        log_procedure(l_api_name, 'start', 'Start wms_rule_pvt.Apply');
6798        log_event(l_api_name, 'Apply ', 'org_id '||p_organization_id);
6799        log_event(l_api_name, 'Apply ', 'item_id '||p_inventory_item_id);
6800     END IF;
6801     -- end of debugging section
6802     --
6803     -- Standard start of API savepoint
6804     SAVEPOINT applyrulesp;
6805 
6806     -- Standard call to check for call compatibility
6807     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
6808       RAISE fnd_api.g_exc_unexpected_error;
6809     END IF;
6810 
6811     -- Initialize message list if p_init_msg_list is set to TRUE
6812     IF fnd_api.to_boolean(p_init_msg_list) THEN
6813       fnd_msg_pub.initialize;
6814     END IF;
6815 
6816   -- LPN Status Project
6817     if (inv_cache.set_org_rec(p_organization_id)) then
6818        l_default_status_id :=  nvl(inv_cache.org_rec.default_status_id,-1);
6819         IF l_debug = 1 THEN
6820            log_statement(l_api_name, 'Value of l_default_status_id: ', l_default_status_id);
6821        END IF;
6822     end if;
6823    -- LPN Status Project
6824 
6825     --
6826     -- Initialize API return status to success
6827     x_return_status  := fnd_api.g_ret_sts_success;
6828     --
6829     -- Initialize functional return status to completed
6830     x_finished       := fnd_api.g_true;
6831 
6832     --
6833     -- Validate input parameters and pre-requisites, if validation level
6834     -- requires this
6835     IF p_validation_level <> fnd_api.g_valid_level_none THEN
6836       IF p_type_code IS NULL
6837          OR p_type_code = fnd_api.g_miss_num THEN
6838         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6839           fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
6840           fnd_msg_pub.ADD;
6841 
6842           IF l_debug = 1 THEN
6843              log_error_msg(l_api_name, 'type_code_missing');
6844           END IF;
6845 
6846         END IF;
6847 
6848         RAISE fnd_api.g_exc_error;
6849       END IF;
6850 
6851       /* get the org defaults */
6852       IF l_debug = 1 THEN
6853          log_statement(l_api_name,'no_rule','Getting default rule at org level');
6854       END IF;
6855       OPEN l_default_rules;
6856       FETCH l_default_rules
6857       INTO l_default_pick_rule
6858          , l_default_put_rule
6859          , l_rule_override_flag
6860          ;
6861       IF l_default_rules%NOTFOUND THEN
6862          IF l_debug = 1 THEN
6863             log_statement(l_api_name, 'org_not_found', 'Organization not found');
6864          END IF;
6865         l_default_pick_rule  := NULL;
6866         l_default_put_rule   := NULL;
6867       END IF;
6868       CLOSE l_default_rules;
6869 
6870       --changed by jcearley on 11/22/99, b/c a null rule_id is now allowed
6871       --  if rule_id is null, use default rule (0 for put away, 1 for pick)
6872       IF p_rule_id IS NULL
6873          OR p_rule_id = fnd_api.g_miss_num THEN
6874         --query org parameters to get user's default rule
6875         --if default rule not defined, use default seeded rule
6876         IF p_type_code = 1 THEN --put away
6877           l_rule_id  := l_default_put_rule;
6878           IF l_rule_id IS NULL THEN
6879              IF l_debug = 1 THEN
6880                 log_statement(l_api_name, 'no_org_rule_put',
6881                              'Did not find org default put away rule');
6882              END IF;
6883             l_rule_id  := 10;
6884           END IF;
6885         ELSE --pick
6886           l_rule_id  := l_default_pick_rule;
6887           IF l_rule_id IS NULL THEN
6888              IF l_debug = 1 THEN
6889                 log_statement(l_api_name, 'no_org_rule_put',
6890                                 'Did not find org default put away rule');
6891           END IF;
6892             l_rule_id  := 2;
6893           END IF;
6894         END IF;
6895         IF l_debug = 1 THEN
6896            log_statement(l_api_name, 'default_rule',
6897                                 'Rule being used: ' || l_rule_id);
6898         END IF;
6899       ELSE
6900         l_rule_id  := p_rule_id;
6901       END IF;
6902 
6903       IF p_partial_success_allowed_flag IS NULL
6904          OR p_partial_success_allowed_flag = fnd_api.g_miss_char THEN
6905         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6906           fnd_message.set_name('WMS', 'WMS_PARTIAL_SUCC_FLAG_MISS');
6907            IF l_debug = 1 THEN
6908               log_error_msg(l_api_name, 'partial_succ_flag_missing');
6909            END IF;
6910           fnd_msg_pub.ADD;
6911         END IF;
6912         RAISE fnd_api.g_exc_error;
6913       END IF;
6914 
6915       IF p_transaction_temp_id IS NULL
6916          OR p_transaction_temp_id = fnd_api.g_miss_num THEN
6917         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6918           fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
6919           fnd_msg_pub.ADD;
6920            IF l_debug = 1 THEN
6921               log_error_msg(l_api_name, 'trx_req_line_id_missing');
6922            END IF;
6923         END IF;
6924         RAISE fnd_api.g_exc_error;
6925       END IF;
6926 
6927       IF p_organization_id IS NULL
6928          OR p_organization_id = fnd_api.g_miss_num THEN
6929         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6930           fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
6931           fnd_msg_pub.ADD;
6932           IF l_debug = 1 THEN
6933              log_error_msg(l_api_name, 'org_id_missing');
6934           END IF;
6935         END IF;
6936 
6937         RAISE fnd_api.g_exc_error;
6938       END IF;
6939 
6940       IF p_inventory_item_id IS NULL
6941          OR p_inventory_item_id = fnd_api.g_miss_num THEN
6942         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6943           fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
6944           fnd_msg_pub.ADD;
6945           IF l_debug = 1 THEN
6946              log_error_msg(l_api_name, 'item_id_missing');
6947           END IF;
6948         END IF;
6949 
6950         RAISE fnd_api.g_exc_error;
6951       END IF;
6952 
6953       IF  p_type_code = 2
6954           AND (p_tree_id IS NULL
6955                OR p_tree_id = fnd_api.g_miss_num
6956               ) THEN
6957         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6958           fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
6959           fnd_msg_pub.ADD;
6960           IF l_debug = 1 THEN
6961              log_error_msg(l_api_name, 'qty_tree_id_missing');
6962           END IF;
6963         END IF;
6964         RAISE fnd_api.g_exc_error;
6965       END IF;
6966     END IF;
6967 
6968     --inv_pp_debug.send_message_to_pipe('finished validations and qty tree init');
6969     --
6970     -- backup qty tree
6971     IF p_type_code = 2 THEN
6972        IF l_debug = 1 THEN
6973           log_statement(l_api_name, 'PICK','PICK');
6974           log_statement(l_api_name, 'backup_tree',
6975                        'Calling inv_quantity_tree_pvt.backup_tree');
6976        END IF;
6977       inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
6978       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6979        IF l_debug = 1 THEN
6980           log_statement(l_api_name, 'backup_tree_unexp_err',
6981                        'Unexpected error from inv_quantity_tree_pvt.backup_tree');
6982        END IF;
6983         RAISE fnd_api.g_exc_unexpected_error;
6984       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6985         IF l_debug = 1 THEN
6986            log_statement(l_api_name, 'backup_tree_err',
6987                        'Error from inv_quantity_tree_pvt.backup_tree');
6988         END IF;
6989         RAISE fnd_api.g_exc_error;
6990       END IF;
6991       --does the rule have any consistency restrictions?
6992       OPEN l_consist;
6993       FETCH l_consist INTO l_dummy;
6994       IF l_consist%NOTFOUND THEN
6995         l_consist_exists  := FALSE;
6996         IF l_debug = 1 THEN
6997            log_statement(l_api_name, 'consist_exist_false',
6998                        'Consistencies do not exist');
6999         END IF;
7000       ELSE
7001         l_consist_exists  := TRUE;
7002         IF l_debug = 1 THEN
7003            log_statement(l_api_name, 'consist_exist_true', 'Cosistencies exist');
7004          END IF;
7005       END IF;
7006       CLOSE l_consist;
7007     END IF;
7008     --log_statement(l_api_name, 'allocation_mode', 'consist done');
7009     --
7010     --Get allocation mode
7011     OPEN c_allocation_mode;
7012     FETCH c_allocation_mode INTO l_allocation_mode, l_quantity_function;
7013 
7014     --log_statement(l_api_name, 'allocation_mode', 'allocation_mode '||l_allocation_mode);
7015 
7016     IF c_allocation_mode%NOTFOUND
7017        OR l_allocation_mode IS NULL THEN
7018       --by default, make allocation mode 3
7019       l_allocation_mode  := 3;
7020     END IF;
7021 
7022     CLOSE c_allocation_mode;
7023 
7024 
7025     IF l_allocation_mode IN (3, 4, 5) THEN --value = 5 added for R12.1 replenishment project
7026       l_use_pick_uom  := TRUE;
7027     ELSE
7028       l_use_pick_uom  := FALSE;
7029     END IF;
7030 
7031     -- make sure, everything is clean
7032     freeglobals;
7033     wms_parameter_pvt.clearcache;
7034     --log_statement(l_api_name, 'apply', 'all cache cleared ');
7035     --
7036     g_trace_recs.DELETE;
7037     l_debug_on       := isruledebugon(p_simulation_mode);
7038     -- - [
7039     --query items table to see if item is serial controlled (picking) or if it
7040     --restricts subs or locators (putaway)
7041 
7042   /*  OPEN l_cur_serial;
7043     FETCH l_cur_serial
7044     INTO l_serial_control_code
7045        , l_restrict_subs_code
7046        , l_restrict_locs_code
7047        , l_lot_divisible_flag
7048        , l_lot_control_code
7049        , l_revision_control_code
7050        , l_grade_control_flag
7051        ;
7052 
7053     log_statement(l_api_name, 'apply', 'fecth iitem info done ');
7054     IF l_cur_serial%NOTFOUND THEN
7055       l_serial_control_code  := 1;
7056       l_restrict_subs_code   := 2;
7057       l_restrict_locs_code   := 2;
7058     END IF;
7059 
7060     CLOSE l_cur_serial;  */
7061 
7062 
7063     -- Removed the above code and added the following variables for performances
7064 
7065       l_return_value := INV_CACHE.set_item_rec(
7066 				   p_organization_id,
7067 				   p_inventory_item_id);
7068       If NOT l_return_value Then
7069 	If l_debug = 1 then
7070 	   log_statement(l_api_name, '-', 'Error setting from sub cache');
7071 	end if;
7072 	RAISE fnd_api.g_exc_unexpected_error;
7073       End If;
7074 
7075       l_serial_control_code 	:= NVL(inv_cache.item_rec.serial_number_control_code,1);
7076       l_restrict_subs_code  	:= NVL(inv_cache.item_rec.restrict_subinventories_code, 2);
7077       l_restrict_locs_code  	:= NVL(inv_cache.item_rec.restrict_locators_code, 2);
7078       l_lot_divisible_flag  	:= inv_cache.item_rec.lot_divisible_flag;
7079       l_lot_control_code    	:= inv_cache.item_rec.lot_control_code;
7080       l_revision_control_code 	:= inv_cache.item_rec.revision_qty_control_code;
7081       l_grade_control_flag 	:= inv_cache.item_rec.grade_control_flag;
7082 
7083     -- ]
7084 
7085     -- Only detail serial numbers if they are prespecified or entered
7086     -- at inventory receipt for this item.
7087     IF p_type_code = 2 THEN --pick
7088       IF l_serial_control_code IN (2, 5) THEN
7089          l_is_serial_control  := 1;
7090       ELSE
7091          l_is_serial_control  := 0;
7092       END IF;
7093     ELSE
7094       l_is_serial_control  := 0;
7095     END IF;
7096 
7097     IF p_detail_serial = TRUE THEN
7098       l_detail_serial  := 1;
7099     ELSE
7100       l_detail_serial  := 0;
7101     END IF;
7102     ------------ Added new code -----
7103 
7104 
7105        -- Logic to improve the performance for Material Status Checks
7106        -- Getting Values from  INV CACHE  and setting the l_detail_serial flag based on the following algoritham
7107        -- Based on the l_detail_falg, Serial_material status would be checked inside the Rule packages or
7108        -- Rules Engine API.
7109        -- ** Serial Mat.Status Check inside Rule Sql(R) / Engine (E)
7110        /*------------------------------------------------------------------------------------------------
7111         Serial   Serial   Serial      MSN          Group By         Serial Mat.Status     l_detail_serial
7112         Allowed  Status   Rule Objs   to be used   LOT/SUb/Loc  Required    Check in RuleSql
7113         -------------------------------------------------------------------------------------------------
7114         Y          Y       Y           Y             N            Y		Engine			1
7115         Y          Y       N           Y             N            Y  		Engine			1
7116         Y          N       Y           Y             N            N		-			2
7117         Y          N       N           Y             N            N		-			2
7118         --------------------------------------------------------------------------------------------------
7119         N          Y       Y           Y             Y            Y		Rule			3
7120         N          Y       N           Y             Y            Y  		Rule			3
7121         N          N       Y           Y             Y            N		-			4
7122         N          N       N           N(MOQD)       N            N		-			0
7123        --------------------------------------------------------------------------------------------------*/
7124    IF l_is_serial_control  = 1 THEN
7125        l_serial_status      := INV_CACHE.ITEM_REC.serial_status_enabled;
7126        --l_serial_status_id := INV_CACHE.ITEM_REC.serial_status_id;
7127        l_lot_status       := INV_CACHE.ITEM_REC.lot_status_enabled;
7128 
7129        IF l_detail_serial = 1 THEN
7130           IF  NVL(l_serial_status, 'N')  = 'Y'  THEN
7131                l_detail_serial := 1;
7132           ELSE
7133                l_detail_serial := 2;
7134           END IF;
7135        ELSE
7136           IF NVL(l_serial_status, 'N')  = 'Y'  THEN
7137                l_detail_serial := 3;
7138 	  ELSE
7139 	       l_detail_serial := 0;
7140           END IF;
7141       END IF;
7142 
7143     --- Checking, if any Serial object based attributes used by any Picking rules
7144     IF l_detail_serial =  0  THEN
7145       IF IsSerialObjectUsed( p_organization_id ) THEN
7146          l_detail_serial := 4;
7147       END IF;
7148      END IF;
7149     END IF;
7150     --
7151     -- [ If the org level flag is set to use Custom logic for Serial numbers,
7152     -- the MSNT is used but grouped by sub/loc
7153     If p_type_code = 2  THEN
7154        l_allocate_serial_flag := inv_cache.org_rec.allocate_serial_flag;
7155     END IF;
7156 
7157     IF  l_allocate_serial_flag = 'C' Then
7158        l_detail_serial := 4;
7159     End If;
7160      -- ]
7161     IF l_debug = 1 THEN
7162        log_statement(l_api_name, 'l_detail_serial', l_detail_serial);
7163        log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
7164        log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
7165     END IF;
7166     /*
7167     --- Bug      5504458
7168     --- Added the following code to handle the entire LPN mode as 'loose   LPN'
7169     --- for serial controlled item with serial allocation on
7170     --- Not sure if it correct or not because I don't see the business case.
7171     IF l_detail_serial  in (1,2) and l_allocation_mode = 1  THEN
7172        l_allocation_mode := 2;
7173     End if;
7174 
7175     --- End of 5504458
7176    */
7177 
7178     --get the name of the rule package
7179     getpackagename(l_rule_id, l_package_name);
7180     -- Initialize the pointer to the first trx detail input line
7181     wms_re_common_pvt.initinputpointer;
7182     --
7183     IF l_debug = 1 THEN
7184        log_statement(l_api_name, 'start_input_loop',
7185                     'Starting loop through input lines');
7186     END IF;
7187     -- Loop through all the trx detail input lines
7188     WHILE TRUE LOOP
7189       --
7190       l_max_tolerance := 0;
7191       -- Get the next trx detail input line
7192       wms_re_common_pvt.getnextinputline(
7193         l_pp_transaction_temp_id
7194       , l_revision
7195       , l_lot_number
7196       , l_lot_expiration_date
7197       , l_from_subinventory_code
7198       , l_from_locator_id
7199       , l_from_cost_group_id
7200       , l_to_subinventory_code
7201       , l_to_locator_id
7202       , l_to_cost_group_id
7203       , l_needed_quantity
7204       , l_sec_needed_quantity
7205       , l_grade_code
7206       , l_reservation_id
7207       , l_serial_number -- [ new code ]
7208       , l_lpn_id
7209       );
7210       EXIT WHEN l_pp_transaction_temp_id IS NULL;
7211       -- [ roll up the rem_tol_qty for Lot inadvisable items  ,   for picking
7212       --   This logic is not implemented . To be implemented in feature  ]
7213 
7214       IF l_debug = 1 THEN
7215         log_statement(l_api_name, 'input_rec', 'Got next input line');
7216         log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
7217         log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
7218         log_statement(l_api_name, 'input_serial', 'serial number:' || l_serial_number);
7219         log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
7220         log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
7221         log_statement(l_api_name, 'input_cg', 'cg:'   || l_from_cost_group_id);
7222         log_statement(l_api_name, 'input_tsub', 'tsub:' || l_to_subinventory_code);
7223         log_statement(l_api_name, 'input_tloc', 'tloc:' || l_to_locator_id);
7224         log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
7225         log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
7226         log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
7227         log_statement(l_api_name, 'input_qty', 'sec_qty:' || l_sec_needed_quantity);
7228 
7229       END IF;
7230       -- [ compute line level tolerances for lot indivisible item for non-reserved lines
7231       --   and the l_needed qty is adjusted to max allowed qty based on the max tol Qty
7232       --   If the tol qty is zero, then the l_needed qty remains unchanged. ]
7233       IF    l_lot_divisible_flag = 'N'
7234         and l_lot_control_code <> 1
7235         and p_type_code = 2
7236         and l_reservation_id is null THEN
7237           l_max_tolerance   :=  g_max_tolerance   ;
7238           l_needed_quantity :=  l_needed_quantity + l_max_tolerance;
7239       ELSIF p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
7240           IF g_max_tolerance < 0 THEN
7241                l_max_tolerance   := g_max_tolerance;
7242                l_needed_quantity := l_needed_quantity + l_max_tolerance;
7243           ELSIF l_allocation_mode in (1, 5) THEN
7244                l_max_tolerance   := g_max_tolerance;
7245                l_needed_quantity := l_needed_quantity + l_max_tolerance;
7246           ELSE
7247                l_max_tolerance   := 0;
7248           END IF;
7249       ELSE
7250           l_max_tolerance   := 0;
7251       END IF;
7252       IF l_debug = 1 THEN
7253           log_statement(l_api_name, 'New Needed Qty with tolerance ', 'qty:' || l_needed_quantity);
7254       END IF;
7255 
7256       IF ((p_project_id IS NOT NULL) AND (l_to_locator_id IS NOT NULL) AND (p_type_code = 1)) THEN
7257         --bug 2400549 - for WIP backflush transfer putaway,
7258         --always use the locator specified on the move order line, even
7259         --if that locator is from common stock (not project)
7260         --Bug 2666620: BackFlush MO Type Removed. It is now 5. Moreover Txn Action ID is 2 which is
7261         --already handled.
7262         IF NOT (wms_engine_pvt.g_move_order_type = 5 AND wms_engine_pvt.g_transaction_action_id = 2) THEN
7263            IF l_debug = 1 THEN
7264               log_statement(l_api_name, 'do_project1', 'Calling do project check');
7265            END IF;
7266           IF doprojectcheck(l_return_status, l_to_locator_id, p_project_id, p_task_id, l_to_locator_id, l_dummy_loc) THEN
7267             IF l_debug = 1 THEN
7268                log_statement(l_api_name, 'do_project1_success', 'Do Project Check passed');
7269             END IF;
7270             NULL;
7271           END IF;
7272         END IF;
7273       END IF;
7274 
7275       --
7276       -- Save the initial input qty for later usage
7277       l_initial_pri_quantity  := l_needed_quantity;
7278       l_input_lpn_id          := l_lpn_id;
7279 
7280       IF p_type_code = 2 THEN
7281         --check for null values.  NULL produces error in stored procedure,
7282         --  so we treat -9999 as NULL;
7283         -- since revision is varchar(3), use -99
7284         -- we only want to overwrite revision and lot for pick rules, since
7285         -- we use these values in putaway.
7286         IF (l_revision IS NULL) THEN
7287           l_revision  := '-99';
7288         END IF;
7289         IF (l_lot_number IS NULL) THEN
7290           l_lot_number  := '-9999';
7291         END IF;
7292       END IF;
7293 
7294       IF (p_type_code = 2) THEN --pick
7295         l_subinventory_code  := l_from_subinventory_code;
7296         l_locator_id         := l_from_locator_id;
7297         l_cost_group_id      := l_from_cost_group_id;
7298       ELSE --put away
7299         l_subinventory_code  := l_to_subinventory_code;
7300         l_locator_id         := l_to_locator_id;
7301         l_cost_group_id      := l_to_cost_group_id;
7302       END IF;
7303 
7304       IF (l_subinventory_code IS NULL) THEN
7305         l_subinventory_code  := '-9999';
7306       END IF;
7307 
7308       IF (l_locator_id IS NULL) THEN
7309         l_locator_id  := -9999;
7310       END IF;
7311 
7312       IF (l_cost_group_id IS NULL) THEN
7313         l_cost_group_id  := -9999;
7314       END IF;
7315 
7316       IF (l_lpn_id IS NULL) THEN
7317         l_lpn_id  := -9999;
7318       END IF;
7319 
7320       IF (p_project_id IS NULL) THEN
7321         l_project_id  := -9999;
7322       ELSE
7323         l_project_id  := p_project_id;
7324       END IF;
7325 
7326       IF (p_task_id IS NULL) THEN
7327         l_task_id  := -9999;
7328       ELSE
7329         l_task_id  := p_task_id;
7330       END IF;
7331 
7332       IF (p_unit_number IS NULL) THEN
7333         l_unit_number  := '-9999';
7334       ELSE
7335         l_unit_number  := p_unit_number;
7336       END IF;
7337 
7338       IF l_debug = 1 THEN
7339            log_statement(l_api_name, 'Set value for l_sl_rsv_is_detailed', 'if serial number is reserved');
7340            log_statement(l_api_name, 'l_serial_number',  l_serial_number);
7341            log_statement(l_api_name, 'l_rule_id',  l_rule_id);
7342            log_statement(l_api_name, 'l_reservation_id',  l_reservation_id);
7343 
7344       END IF;
7345       -- [ new code to check the serial number reservation ]
7346 
7347       l_sl_rsv_is_detailed := 'N' ;
7348       IF NVL(l_serial_number, '-999') <> '-999'  AND (  NVL(l_rule_id, 777)  = -999 or  NVL(l_reservation_id , 999) <> 999 ) THEN
7349          l_sl_rsv_is_detailed := 'Y' ;
7350       END IF;
7351 
7352 
7353       /* LG. Check the txn dtl lines with the control flags, then check the override rule flag
7354        * from the mtl_parameters, allocate directly if res is fully detailed.
7355        */
7356        --[
7357        -- If the Serial Number is reserved, Rules are not called and following code is called
7358        --]
7359       IF ( l_rule_override_flag = 'Y' OR  l_sl_rsv_is_detailed = 'Y' )  and p_type_code = 2 THEN
7360         IF l_debug = 1 THEN
7361            log_statement(l_api_name,'detailed', 'Rule Override flag is set ');
7362         END IF;
7363         -- Validate the txn detail
7364         l_reservation_is_detailed := 'Y';
7365         IF (wms_engine_pvt.g_org_loc_control IN (2, 3)                 -- org level
7366                 OR wms_engine_pvt.g_sub_loc_control IN (2, 3)          -- sub level
7367                 OR (wms_engine_pvt.g_sub_loc_control = 5               -- item level
7368                        AND wms_engine_pvt.g_item_loc_control IN (2, 3)
7369                    )
7370            )
7371         THEN
7372            IF l_debug = 1 THEN
7373               log_statement(l_api_name,'detailed', 'Locator should be there '|| l_locator_id);
7374            END IF;
7375            IF nvl(l_locator_id,-9999) = -9999 THEN
7376               l_reservation_is_detailed := 'N';
7377            END IF;
7378         END IF;
7379 
7380         IF l_lot_control_code <> 1 THEN -- lot controlled
7381            IF l_debug = 1 THEN
7382               log_statement(l_api_name,'detailed', 'Lot should be there'|| l_lot_number);
7383            END IF;
7384            IF nvl(l_lot_number,'-9999') = '-9999' THEN
7385               l_reservation_is_detailed := 'N';
7386            END IF;
7387         END IF;
7388 
7389         IF l_revision_control_code <> 1 THEN   -- revision controlled
7390            IF l_debug = 1 THEN
7391               log_statement(l_api_name,'detailed', 'Revision should be there'|| l_Revision);
7392            END IF;
7393            IF nvl(l_revision,'-99') = '-99' THEN
7394               l_reservation_is_detailed := 'N';
7395            END IF;
7396         END IF;
7397         /*IF l_grade_control_flag = 'Y'  THEN   -- grade controlled
7398            IF l_debug = 1 THEN
7399               log_statement(l_api_name,'detailed', 'Grade should be there'|| l_grade_code);
7400            END IF;
7401            IF nvl(l_grade_code,'-9999') = '-9999' THEN
7402               l_reservation_is_detailed := 'N';
7403            END IF;
7404         END IF;*/
7405 
7406         IF ( l_reservation_is_detailed = 'Y' OR  l_sl_rsv_is_detailed = 'Y' ) THEN
7407            IF l_debug = 1 THEN
7408               log_statement(l_api_name,'detailed', 'Reservation is fully detailed, validate and insert');
7409            END IF;
7410 
7411            -- [Checking the material status for serial /lots
7412            --  OPM Convergence project missed the mat-status check
7413            -- Logic : if the lot or serial number's material status is not allowed for transactions
7414            --         even though there is detailed reservations exist in the system, rule engine will
7415            --         ignore the record
7416            --         The mat-status is applicable for serial reserved items too ]
7417 
7418                 l_sub_loc_lot_trx_allowed 	:= 'Y';
7419 	        l_serial_trx_allowed		:= 'Y';
7420 	        l_serial_status_id 	 	:= 0;
7421 	        IF ((l_serial_number  IS NOT NULL)  AND  (NVL(l_serial_status, 'N')  = 'Y'))  THEN
7422 	           select status_id
7423 	             into l_serial_status_id
7424 	             from mtl_serial_numbers
7425 	            where inventory_item_id        = p_inventory_item_id
7426 	              and current_organization_id  = p_organization_id
7427 	              and serial_number            = l_serial_number;
7428 
7429 	             l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
7430 	                                          p_transaction_type_id
7431 	                                         ,p_organization_id
7432 	                                         ,p_inventory_item_id
7433 	                                         ,l_serial_status_id) ;
7434 	        END IF;
7435                -- Bug 4756156
7436 	       -- IF  ((l_lot_number IS NOT NULL)  AND (nvl(l_lot_status, 'Y') = 'Y'))  THEN
7437 	            l_sub_loc_lot_trx_allowed :=   inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
7438 	                                          p_transaction_type_id
7439 	                                         ,p_organization_id
7440 	                                         ,p_inventory_item_id
7441 	                                         ,l_subinventory_code
7442 	                                         ,l_locator_id
7443 	                                         ,l_lot_number);
7444 	       -- END IF;
7445 	        If  ( l_serial_trx_allowed <> 'Y' and l_sub_loc_lot_trx_allowed <> 'Y' ) THEN
7446 	             --   skip the input record and go to next rec , because mat status is not allowed
7447 	            IF l_debug = 1 THEN
7448 		       log_statement(l_api_name, 'Mat Status Check failed', 'Skipping the input rec');
7449 	            END IF;
7450 	            GOTO nextINputrecord;
7451 	        END IF;
7452            -- End of mat status check ]
7453 
7454            -- [ Allocating this line based on reservation without calling rules
7455            --   Make sure all the following values are either NULL or have some
7456            --   real values but not the defaulted values  eg '-99' or '-9999' etc..
7457            --   The  default values '-99', '-9999' may cause issues with Qty tree
7458            --   May have to default the value for Project, Task , unit
7459            --   This only applicable for line based on detailed reservation
7460            -- ]
7461 
7462            IF l_revision = '-99' THEN
7463               l_revision := NULL;
7464            END IF;
7465 
7466            IF l_subinventory_code = '-9999' THEN
7467               l_subinventory_code := NULL;
7468            END IF;
7469 
7470            IF l_locator_id  = -9999 THEN
7471               l_locator_id := NULL;
7472            END IF;
7473 
7474            IF  l_cost_group_id  = -9999 THEN
7475 	       l_cost_group_id := NULL;
7476 	   END IF;
7477 
7478 	   IF l_lpn_id = -9999 THEN
7479 	      l_lpn_id := NULL;
7480 	   END IF;
7481 
7482 	  IF (l_lot_number =  '-9999' ) THEN
7483 	      l_lot_number  := NULL;
7484           END IF;
7485 
7486            g_locs(1).revision               := l_revision;
7487            g_locs(1).lot_number             := l_lot_number;
7488            g_locs(1).subinventory_code      := l_subinventory_code;
7489            g_locs(1).locator_id             := l_locator_id;
7490            g_locs(1).quantity               := l_needed_quantity;
7491            g_locs(1).secondary_quantity     := l_sec_needed_quantity;
7492            g_locs(1).serial_number          := l_serial_number; -- [ new code ]
7493 
7494 
7495            validate_and_insert(
7496              x_return_status              => x_return_status
7497            , x_msg_count                  => x_msg_count
7498            , x_msg_data                   => x_msg_data
7499            , p_record_id                  => 1
7500            , p_needed_quantity            => l_needed_quantity
7501            , p_use_pick_uom               => FALSE
7502            , p_organization_id            => p_organization_id
7503            , p_inventory_item_id          => p_inventory_item_id
7504            , p_to_subinventory_code       => l_to_subinventory_code
7505            , p_to_locator_id              => l_to_locator_id
7506            , p_to_cost_group_id           => l_to_cost_group_id
7507            , p_primary_uom                => p_primary_uom
7508            , p_transaction_uom            => p_transaction_uom
7509            , p_transaction_temp_id        => p_transaction_temp_id
7510            , p_type_code                  => p_type_code
7511            , p_rule_id                    => l_rule_id
7512            , p_reservation_id             => l_reservation_id
7513            , p_tree_id                    => p_tree_id
7514            , p_debug_on                   => l_debug_on
7515            , p_needed_sec_quantity        => l_sec_needed_quantity
7516            , p_secondary_uom              => p_secondary_uom
7517            , p_grade_code                 => p_grade_code
7518            , x_inserted_record            => l_inserted_record
7519            , x_allocated_quantity         => l_allocated_quantity
7520            , x_remaining_quantity         => l_remaining_quantity
7521            , x_sec_allocated_quantity     => l_sec_allocated_quantity
7522            , x_sec_remaining_quantity     => l_sec_remaining_quantity
7523            );
7524            IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7525              IF l_debug = 1 THEN
7526                 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
7527              END IF;
7528              RAISE fnd_api.g_exc_unexpected_error;
7529            ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7530              IF l_debug = 1 THEN
7531                 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
7532              END IF;
7533              RAISE fnd_api.g_exc_error;
7534            END IF;
7535            /* done with this res go to the next */
7536            GOTO nextINputrecord;
7537         END IF;
7538       END IF;
7539 
7540       IF l_debug = 1 THEN
7541         IF p_type_code = 1 THEN
7542            log_statement(l_api_name, 'Input Rec :Calling rule with following value of type -', 'Putaway');
7543         ELSE
7544            log_statement(l_api_name, 'Input Rec :Calling rule with following value of type -', 'Picking');
7545         END IF;
7546         log_statement(l_api_name, 'Input Rec :l_rule_id', 		l_rule_id);
7547         log_statement(l_api_name, 'Input Rec :p_organization_id', 	p_organization_id);
7548         log_statement(l_api_name, 'Input Rec :p_inventory_item_id',  	p_inventory_item_id);
7549         log_statement(l_api_name, 'Input Rec :p_transaction_type_id',  	p_transaction_type_id);
7550         log_statement(l_api_name, 'Input Rec :l_revision',  		l_revision);
7551         log_statement(l_api_name, 'Input Rec :l_lot_number',  		l_lot_number);
7552         log_statement(l_api_name, 'Input Rec :l_subinventory_code',  	l_subinventory_code);
7553         log_statement(l_api_name, 'Input Rec :l_locator_id',  		l_locator_id);
7554         log_statement(l_api_name, 'Input Rec :l_cost_group_id',  	l_cost_group_id);
7555         log_statement(l_api_name, 'Input Rec :l_pp_transaction_temp_id',l_pp_transaction_temp_id);
7556         log_statement(l_api_name, 'Input Rec :l_is_serial_control', 	l_is_serial_control);
7557         log_statement(l_api_name, 'Input Rec :l_detail_serial',  	l_detail_serial);
7558         log_statement(l_api_name, 'Input Rec :p_detail_any_serial',  	p_detail_any_serial);
7559         log_statement(l_api_name, 'Input Rec :p_from_serial', 		p_from_serial);
7560         log_statement(l_api_name, 'Input Rec :p_to_serial', 		p_to_serial);
7561         log_statement(l_api_name, 'Input Rec :l_unit_number',  		l_unit_number);
7562         log_statement(l_api_name, 'Input Rec :l_lpn_id',  		l_lpn_id);
7563         log_statement(l_api_name, 'Input Rec :l_project_id',  		l_project_id);
7564         log_statement(l_api_name, 'Input Rec :l_task_id',  		l_task_id);
7565         log_statement(l_api_name, 'Input Rec :l_rule_result ',		l_rule_result);
7566         log_statement(l_api_name, 'Input Rec :l_restrict_subs_code ',  	l_restrict_subs_code);
7567         log_statement(l_api_name, 'Input Rec :l_restrict_locs_code ',	l_restrict_locs_code);
7568       END IF;
7569 
7570       For l_rule_counter IN 1..2  LOOP
7571          IF p_type_code = 2 THEN
7572            --pick_open_curs
7573            pick_open_rule(
7574               v_pick_cursor
7575             , l_rule_id
7576             , p_organization_id
7577             , p_inventory_item_id
7578             , p_transaction_type_id
7579             , l_revision
7580             , l_lot_number
7581             , l_subinventory_code
7582             , l_locator_id
7583             , l_cost_group_id
7584             , l_pp_transaction_temp_id
7585             , l_is_serial_control
7586             , l_detail_serial
7587             , p_detail_any_serial
7588             , p_from_serial
7589             , p_to_serial
7590             , l_unit_number
7591             , l_lpn_id
7592             , l_project_id
7593             , l_task_id
7594             , l_rule_result
7595             );
7596          ELSIF  p_type_code = 1  then
7597             put_open_rule(
7598               v_put_cursor
7599             , l_rule_id
7600             , p_organization_id
7601             , p_inventory_item_id
7602             , p_transaction_type_id
7603             , l_subinventory_code
7604             , l_locator_id
7605             , l_pp_transaction_temp_id
7606             , l_restrict_subs_code
7607             , l_restrict_locs_code
7608             , l_project_id
7609             , l_task_id
7610             , l_rule_result
7611             );
7612          END IF;
7613 
7614          IF l_rule_result  = 1 then
7615             IF l_debug = 1 THEN
7616                log_statement(l_api_name, 'Open Cursor package called ' , l_rule_counter);
7617                log_statement(l_api_name, 'rule_id ' , l_rule_id);
7618             END IF;
7619             EXIT;
7620          END IF;
7621          --log_statement(l_api_name, ' Before  =  l_rule_result ' , l_rule_result );
7622          --log_statement(l_api_name, ' Before  = wms_rule_pvt.g_rule_list_pick_ctr ' , wms_rule_pvt.g_rule_list_pick_ctr);
7623          IF (l_rule_result = 0) and l_rule_counter   = 2 THEN --error
7624            IF l_debug = 1 THEN
7625               log_statement(l_api_name, 'open_curs_err', 'Error calling open_curs');
7626               log_error_msg(l_api_name, 'rule_package_missing');
7627               log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
7628            END IF;
7629            fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
7630            fnd_message.set_token('RULEID', l_rule_id);
7631            fnd_msg_pub.ADD;
7632            RAISE fnd_api.g_exc_unexpected_error;
7633          END IF;
7634       END LOOP;
7635 
7636       IF (p_type_code = 2) THEN --pick
7637         g_locs_index           := 0;
7638         g_locs.DELETE;
7639         g_consists.DELETE;
7640         g_lpns.DELETE;
7641         g_first_order_by_rank  := NULL;
7642         g_first_consist_group  := 0;
7643         g_last_consist_group   := 0;
7644         l_order_by_rank        := 0;
7645       END IF;
7646 
7647       --If type code = 2 and allocation mode = 1
7648       --ENTIRE LPN
7649       IF  p_type_code = 2
7650           AND l_allocation_mode = 1 THEN
7651         l_cur_lpn_group    := 0;
7652         g_first_lpn_group  := 0;
7653         g_last_lpn_group   := 0;
7654         l_cur_lpn_rec      := 0;
7655 
7656         l_allocate_serial_flag := inv_cache.org_rec.allocate_serial_flag;
7657 
7658         IF l_debug = 1 THEN
7659            log_statement(l_api_name, 'alloc_lpns', 'Allocating Entire LPNs');
7660            log_statement(l_api_name, 'allocate_serial_flag', 'allocate_serial_flag = '||l_allocate_serial_flag);
7661         END IF;
7662 
7663         --for each record from rules cursor
7664         LOOP
7665            --Get record from rules cursor
7666            IF l_debug = 1 THEN
7667               log_statement(l_api_name, 'fetch_cursor', 'Getting rec from rule with FetchCursor');
7668            END IF;
7669            --  Added for Mat Stat check
7670            LOOP
7671            if l_debug = 1 THEN
7672               log_statement(l_api_name, 'fetch_cursor', 'inside Mat Stat check LOOP');
7673            END IF;
7674            -- For custom serial
7675            IF  ( l_allocate_serial_flag = 'C' ) AND (nvl(l_custom_serial_index,-1) < nvl(l_custom_select_serials.serial_number.LAST,-1)) THEN
7676               -- next record should be next serial from custom API
7677               l_custom_serial_index := l_custom_serial_index + 1;
7678               v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
7679               v_current_row.quantity := 1;
7680            ELSE
7681            --- Mat Stat checking --
7682              fetchcursor(
7683                x_return_status
7684              , x_msg_count
7685              , x_msg_data
7686              , v_pick_cursor
7687              , l_rule_id
7688              , v_current_row.revision
7689              , v_current_row.lot_number
7690              , v_current_row.lot_expiration_date
7691              , v_current_row.subinventory_code
7692              , v_current_row.locator_id
7693              , v_current_row.cost_group_id
7694              , v_current_row.uom_code
7695              , v_current_row.lpn_id
7696              , v_current_row.serial_number
7697              , v_current_row.quantity
7698              , v_current_row.secondary_quantity               -- new
7699              , v_current_row.grade_code                       -- new
7700              , v_current_row.consist_string
7701              , v_current_row.order_by_string
7702              , l_rows
7703              );
7704 
7705            EXIT WHEN  nvl(l_rows, 0)  = 0 ;  -- [ Added to to exit , if the rule is not returning any rows
7706            IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7707               IF l_debug = 1 THEN
7708                  log_error(l_api_name, 'uerr_fetch_cursor', 'Unexpected error in FetchCursor');
7709               END IF;
7710               RAISE fnd_api.g_exc_unexpected_error;
7711            ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7712               IF l_debug = 1 THEN
7713                  log_error(l_api_name, 'fetch_cursor ', 'Error in FetchCursor');
7714               END IF;
7715               RAISE fnd_api.g_exc_error;
7716            END IF;
7717 
7718            IF l_debug = 1 THEN
7719               log_statement(l_api_name, 'Serial Status - l_detail_serial ', l_detail_serial);
7720               log_statement(l_api_name, 'fetch_cursor - l_rows ', l_rows);
7721               log_statement(l_api_name, 'fetch_cursor - v_current_row.lot_number ', v_current_row.lot_number);
7722               log_statement(l_api_name, 'fetch_cursor - v_current_row.serial_number ', v_current_row.serial_number);
7723            END IF;
7724 
7725               IF  ( l_allocate_serial_flag = 'C' ) THEN
7726                      INV_DETAIL_SERIAL_PUB.Get_User_Serial_Numbers (
7727                    x_return_status           => x_return_status
7728                  , x_msg_count               => x_msg_count
7729                  , x_msg_data                => x_msg_data
7730                  , p_organization_id         => p_organization_id
7731                  , p_inventory_item_id       => p_inventory_item_id
7732                  , p_revision                => v_current_row.revision
7733                  , p_lot_number              => v_current_row.lot_number
7734                  , p_subinventory_code       => v_current_row.subinventory_code
7735                  , p_locator_id              => v_current_row.locator_id
7736                  , p_required_sl_qty         => v_current_row.quantity
7737                  , p_from_range              => p_from_serial
7738                  , p_to_range                => p_to_serial
7739                  , p_unit_number             => l_unit_number
7740                  , p_cost_group_id           => l_cost_group_id
7741                  , p_transaction_type_id     => NULL --p_transaction_type_id
7742                  , p_demand_source_type_id   => NULL --p_demand_source_type_id
7743                  , p_demand_source_header_id => NULL --p_demand_source_header_id
7744                  , p_demand_source_line_id   => NULL --p_demand_source_line_id
7745                  , x_serial_numbers          => l_custom_select_serials );
7746 
7747                 IF ( x_return_status = fnd_api.g_ret_sts_unexp_error ) THEN
7748                    IF ( l_debug = 1 ) THEN
7749                       log_error(l_api_name, 'uerr_Get_User_Serial_Numbers', 'Unexpected error in Get_User_Serial_Numbers');
7750                    END IF;
7751                    RAISE fnd_api.g_exc_unexpected_error;
7752                 ELSIF ( x_return_status = fnd_api.g_ret_sts_error ) THEN
7753                    IF ( l_debug = 1 ) THEN
7754                       log_error(l_api_name, 'Get_User_Serial_Numbers', 'Error in Get_User_Serial_Numbers');
7755                    END IF;
7756                    RAISE fnd_api.g_exc_error;
7757                 END IF;
7758 
7759                 l_custom_serial_index := l_custom_select_serials.serial_number.FIRST;
7760                 v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
7761                 v_current_row.quantity := 1;
7762               END IF;
7763            END IF; -- custom serial
7764            ------ is_serial_trx_allowed is_sub_loc_lot_trx_allowed
7765            -- EXIT WHEN l_rows = 0 ;
7766            l_sub_loc_lot_trx_allowed 	:= 'Y';
7767            l_serial_trx_allowed		:= 'Y';
7768            l_serial_status_id 	 	:= 0;
7769 
7770            IF v_current_row.serial_number IS NOT NULL  THEN
7771              IF l_detail_serial = 1 THEN
7772                  select status_id
7773                  into l_serial_status_id
7774                  from mtl_serial_numbers
7775                  where inventory_item_id        = p_inventory_item_id
7776                     and current_organization_id = p_organization_id
7777                     and serial_number           = v_current_row.serial_number;
7778 
7779                  l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
7780                                        p_transaction_type_id
7781                                       ,p_organization_id
7782                                       ,p_inventory_item_id
7783                                       ,l_serial_status_id) ;
7784              END IF;
7785              IF l_debug = 1 THEN
7786               log_statement(l_api_name, 'Serial Status - p_transaction_type_id ', p_transaction_type_id);
7787               log_statement(l_api_name, 'Serial Status - p_organization_id ', p_organization_id);
7788               log_statement(l_api_name, 'Serial Status -p_transaction_type_id ', p_organization_id);
7789               log_statement(l_api_name, 'Serial Status - p_inventory_item_id ', p_inventory_item_id);
7790               log_statement(l_api_name, 'Serial Status - serial_number ', v_current_row.serial_number);
7791               log_statement(l_api_name, 'Serial Status - l_serial_status_id ', l_serial_status_id);
7792               log_statement(l_api_name, 'Serial Status - l_serial_trx_allowed ', l_serial_trx_allowed);
7793              END IF;
7794            END IF;
7795            -- Bug 4756156
7796            -- IF  ((v_current_row.lot_number IS NOT NULL)  AND (nvl(l_lot_status, 'Y')  = 'Y'))  THEN
7797            -- LPN Status Project
7798 
7799                l_onhand_status_trx_allowed := 'Y';
7800 
7801                IF l_default_status_id = -1 THEN
7802                  IF l_debug = 1 THEN
7803                      log_statement(l_api_name, 'before calling trx_allowed: ', l_sub_loc_lot_trx_allowed);
7804                  END IF;
7805 
7806 			 l_onhand_status_trx_allowed := 'N';
7807                          l_sub_loc_lot_trx_allowed :=   inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
7808                                        p_transaction_type_id
7809                                       ,p_organization_id
7810                                       ,p_inventory_item_id
7811                                       ,v_current_row.subinventory_code
7812                                       ,v_current_row.locator_id
7813                                       ,v_current_row.lot_number);
7814 
7815                        IF l_debug = 1 THEN
7816 	                        log_statement(l_api_name, 'fetch_cursor - l_sub_loc_lot_trx_allowed ', l_sub_loc_lot_trx_allowed);
7817                        END IF;
7818                ELSE --  IF l_default_status_id = -1 THEN
7819 
7820                          l_sub_loc_lot_trx_allowed:='N';
7821                         IF (inv_cache.item_rec.serial_number_control_code in (1,6)) THEN
7822 			 l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
7823                                          p_transaction_type_id
7824                                         ,p_organization_id
7825                                         ,p_inventory_item_id
7826                                         ,v_current_row.subinventory_code
7827                                         ,v_current_row.locator_id
7828                                         ,v_current_row.lot_number
7829 		                                    , v_current_row.lpn_id);
7830                         END IF;
7831 	 	          IF l_debug = 1 THEN
7832 	                         log_statement(l_api_name, 'fetch_cursor - l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
7833                            END IF;
7834               END IF;
7835 
7836            -- END IF;
7837            --- ]
7838            EXIT WHEN  (    l_serial_trx_allowed      = 'Y'
7839                        and (l_sub_loc_lot_trx_allowed = 'Y' OR l_onhand_status_trx_allowed='Y'));
7840            -- >> Else fetch next record from the rule cursor --
7841            END LOOP;
7842        -- End of Mat Stat Check --
7843        -- LPN Status Project
7844 
7845           --initialize pointer to next rec
7846           v_current_row.next_rec  := 0;
7847           --if no more records
7848           IF l_rows  = 0 THEN
7849             IF l_debug = 1 THEN
7850                log_statement(l_api_name, 'no_more_rec', 'No more records from rule');
7851             END IF;
7852             IF l_consist_exists THEN
7853               --loop through consist groups, looking for groups where quantity = needed quantity
7854               l_cur_consist_group  := g_first_consist_group;
7855               IF l_debug = 1 THEN
7856                  log_statement(l_api_name, 'first_consist_group', 'First Consist Group in list: ' || l_cur_consist_group);
7857               END IF;
7858               LOOP
7859                 --EXIT WHEN l_needed_quantity <= 0;
7860                 IF g_over_allocation = 'N'
7861                 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
7862                 OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
7863                   EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
7864                 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
7865                   IF l_max_tolerance  >= 0 THEN
7866                      EXIT WHEN (l_needed_quantity <= l_max_tolerance)
7867                      OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
7868                   ELSE
7869                      EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
7870                   END IF;
7871                 END IF;
7872                 EXIT WHEN l_cur_consist_group = 0;
7873                 --IF g_consists(l_cur_consist_group).quantity = l_needed_quantity THEN
7874 		IF (g_consists(l_cur_consist_group).quantity BETWEEN (l_needed_quantity - l_max_tolerance) AND l_needed_quantity) THEN
7875                   --for each LPN in lpn array
7876                   l_cur_lpn_group  := g_consists(l_cur_consist_group).first_rec;
7877                   IF l_debug = 1 THEN
7878                      log_statement(l_api_name, 'first_lpn', 'First LPN in list: ' || l_cur_lpn_group);
7879                   END IF;
7880                   LOOP --loop through lpn in consist group
7881                     EXIT WHEN l_cur_lpn_group = 0;
7882                     --if lpn quantity is less than or equal to the needed quantity
7883                     -- and the LPN has been entirely allocated, use it
7884                     IF l_debug = 1 THEN
7885                        log_statement(l_api_name, 'alloc_stored_lpn', 'Allocating LPN. id: ' || l_cur_lpn_group);
7886                     END IF;
7887                     -- for each record in LPN
7888                     l_cur_lpn_rec      := g_lpns(l_cur_lpn_group).first_rec;
7889                     LOOP
7890                       EXIT WHEN l_cur_lpn_rec = 0;
7891                       g_trace_recs(l_cur_lpn_rec).entire_lpn_flag  := 'Y';
7892                       --call validate and insert
7893                       l_expected_quantity                          := g_locs(l_cur_lpn_rec).quantity;
7894                       validate_and_insert(
7895                         x_return_status              => x_return_status
7896                       , x_msg_count                  => x_msg_count
7897                       , x_msg_data                   => x_msg_data
7898                       , p_record_id                  => l_cur_lpn_rec
7899                       , p_needed_quantity            => l_needed_quantity
7900                       , p_use_pick_uom               => FALSE
7901                       , p_organization_id            => p_organization_id
7902                       , p_inventory_item_id          => p_inventory_item_id
7903                       , p_to_subinventory_code       => l_to_subinventory_code
7904                       , p_to_locator_id              => l_to_locator_id
7905                       , p_to_cost_group_id           => l_to_cost_group_id
7906                       , p_primary_uom                => p_primary_uom
7907                       , p_transaction_uom            => p_transaction_uom
7908                       , p_transaction_temp_id        => p_transaction_temp_id
7909                       , p_type_code                  => p_type_code
7910                       , p_rule_id                    => l_rule_id
7911                       , p_reservation_id             => l_reservation_id
7912                       , p_tree_id                    => p_tree_id
7913                       , p_debug_on                   => l_debug_on
7914                       , p_needed_sec_quantity        => l_sec_needed_quantity
7915                       , p_secondary_uom              => p_secondary_uom
7916                       , p_grade_code                 => p_grade_code
7917                       , x_inserted_record            => l_inserted_record
7918                       , x_allocated_quantity         => l_allocated_quantity
7919                       , x_remaining_quantity         => l_remaining_quantity
7920                       , x_sec_allocated_quantity     => l_sec_allocated_quantity
7921                       , x_sec_remaining_quantity     => l_sec_remaining_quantity
7922                       );
7923 
7924                       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7925                         IF l_debug = 1 THEN
7926                            log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
7927                         END IF;
7928                        RAISE fnd_api.g_exc_unexpected_error;
7929                       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7930                        IF l_debug = 1 THEN
7931                           log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
7932                        END IF;
7933                         RAISE fnd_api.g_exc_error;
7934                       END IF;
7935                       --if returns false
7936                       IF l_inserted_record = FALSE
7937                          OR l_allocated_quantity < l_expected_quantity THEN
7938                         IF l_debug = 1 THEN
7939                            log_statement(l_api_name, 'insert_failed', 'Record failed to allocation.  Rolling back and ' || 'invalidating LPN');
7940                            -- rollback quantity tree
7941                            log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
7942                         END IF;
7943                         inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
7944                         IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7945                           IF l_debug = 1 THEN
7946                              log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
7947                           END IF;
7948                          RAISE fnd_api.g_exc_unexpected_error;
7949                         ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7950                           IF l_debug = 1 THEN
7951                              log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
7952                           END IF;
7953                          RAISE fnd_api.g_exc_error;
7954                         END IF;
7955                         -- delete allocations
7956                         DELETE FROM wms_transactions_temp
7957                               WHERE line_type_code = 2
7958                                 AND type_code = p_type_code;
7959                         IF l_debug_on THEN
7960                           l_cur_rec  := g_lpns(l_cur_lpn_group).first_rec;
7961                           LOOP
7962                             g_trace_recs(l_cur_rec).entire_lpn_flag  := 'N';
7963                             g_trace_recs(l_cur_rec).suggested_qty    := 0;
7964                             EXIT WHEN l_cur_rec = l_cur_lpn_rec;
7965                             l_cur_rec                                := g_locs(l_cur_rec).next_rec;
7966                           END LOOP;
7967                         END IF;
7968                         IF l_debug = 1 THEN
7969                            log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
7970                         END IF;
7971                         -- Exit loop for each rec in this LPN
7972                         EXIT;
7973                       END IF; -- didn't allocate as much as expected
7974                       IF l_debug_on THEN
7975                         g_trace_recs(l_cur_lpn_rec).consist_string_flag  := 'Y';
7976                       END IF;
7977                       --decrease quantity needed
7978                       IF l_debug = 1 THEN
7979                          log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
7980                       END IF;
7981                       l_cur_lpn_rec                                := g_locs(l_cur_lpn_rec).next_rec;
7982                       EXIT WHEN l_cur_lpn_rec = 0;
7983                     --end loop through lpn recs
7984                     END LOOP; -- loop through recs w/in LPN
7985 
7986                     -- if no more quantity needed, exit LPN loop
7987                     l_needed_quantity  := l_needed_quantity - g_lpns(l_cur_lpn_group).quantity;
7988                     l_sec_needed_quantity  := l_sec_needed_quantity - g_lpns(l_cur_lpn_group).secondary_quantity;
7989 
7990 		    IF l_debug = 1 THEN
7991 			log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
7992 		    END IF;
7993 
7994                   --EXIT WHEN l_needed_quantity <= 0; -- consist loop
7995                     IF g_over_allocation = 'N'
7996 		    OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
7997 		    OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
7998 			EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
7999 		    ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8000 			IF l_max_tolerance  >= 0 THEN
8001 				EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8002 				OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8003 			ELSE
8004 				EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8005 			END IF;
8006                     END IF;
8007                     l_cur_lpn_group    := g_lpns(l_cur_lpn_group).next_consist_lpn_id;
8008                     EXIT WHEN l_cur_lpn_group = 0;
8009 
8010                      IF l_debug = 1 THEN
8011                         log_statement(l_api_name, 'next_lpn', 'Next LPN in list: ' || l_cur_lpn_group);
8012                      END IF;
8013 
8014                   END LOOP; --lpns in consist group
8015 
8016                   -- if no more quantity needed, exit LPN loop
8017                  --EXIT WHEN l_needed_quantity <= 0; -- consist loop
8018                    IF g_over_allocation = 'N'
8019                    OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8020                    OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
8021 			EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8022 		   ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8023 			IF l_max_tolerance  >= 0 THEN
8024 				EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8025 				OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8026 			ELSE
8027 				EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8028 			END IF;
8029                    END IF;
8030                 END IF; -- enough quantity to allocate
8031 
8032                 -- end loop through consist groups
8033                 l_cur_consist_group  := g_consists(l_cur_consist_group).next_group;
8034 
8035                 IF l_debug = 1 THEN
8036                    log_statement(l_api_name, 'next_consist_group', 'Next Consist Group in list: ' || l_cur_consist_group);
8037                 END IF;
8038 
8039               END LOOP;
8040 
8041               --exit outermost loop
8042               IF l_debug = 1 THEN
8043                  log_statement(l_api_name, 'lpn_alloc_finished', 'Finished checking all LPNS.  Exit LPN allocation.');
8044                END IF;
8045 
8046               EXIT; --outermost loop
8047             ELSE -- no consists
8048               --for each LPN in lpn array
8049               l_cur_lpn_group  := g_first_lpn_group;
8050 
8051               IF l_debug = 1 THEN
8052                  log_statement(l_api_name, 'first_lpn', 'First LPN in list: ' || g_first_lpn_group);
8053               END IF;
8054 
8055               LOOP
8056                 --EXIT WHEN l_needed_quantity <= 0;
8057                 IF g_over_allocation = 'N'
8058                 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8059                 OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
8060                   EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8061                 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8062                   IF l_max_tolerance  >= 0 THEN
8063                      EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8064                      OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8065                   ELSE
8066                      EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8067                   END IF;
8068                 END IF;
8069                 EXIT WHEN l_cur_lpn_group = 0;
8070 
8071                 --if lpn quantity is less than or equal to the needed quantity
8072                 -- and the LPN has been entirely allocated, use it
8073                 IF  g_lpns(l_cur_lpn_group).quantity <= l_needed_quantity
8074                     AND g_lpns(l_cur_lpn_group).total_quantity <> -1
8075                     AND g_lpns(l_cur_lpn_group).quantity = g_lpns(l_cur_lpn_group).total_quantity THEN
8076 
8077                   IF l_debug = 1 THEN
8078                      log_statement(l_api_name, 'alloc_stored_lpn', 'Allocating LPN. id: ' || l_cur_lpn_group);
8079                   END IF;
8080                   -- for each record in LPN
8081                   l_cur_lpn_rec  := g_lpns(l_cur_lpn_group).first_rec;
8082 
8083                   LOOP
8084                     EXIT WHEN l_cur_lpn_rec = 0;
8085                     g_trace_recs(l_cur_lpn_rec).entire_lpn_flag  := 'Y';
8086                     --call validate and insert
8087                     l_expected_quantity                          := g_locs(l_cur_lpn_rec).quantity;
8088                     validate_and_insert(
8089                       x_return_status              => x_return_status
8090                     , x_msg_count                  => x_msg_count
8091                     , x_msg_data                   => x_msg_data
8092                     , p_record_id                  => l_cur_lpn_rec
8093                     , p_needed_quantity            => l_needed_quantity
8094                     , p_use_pick_uom               => FALSE
8095                     , p_organization_id            => p_organization_id
8096                     , p_inventory_item_id          => p_inventory_item_id
8097                     , p_to_subinventory_code       => l_to_subinventory_code
8098                     , p_to_locator_id              => l_to_locator_id
8099                     , p_to_cost_group_id           => l_to_cost_group_id
8100                     , p_primary_uom                => p_primary_uom
8101                     , p_transaction_uom            => p_transaction_uom
8102                     , p_transaction_temp_id        => p_transaction_temp_id
8103                     , p_type_code                  => p_type_code
8104                     , p_rule_id                    => l_rule_id
8105                     , p_reservation_id             => l_reservation_id
8106                     , p_tree_id                    => p_tree_id
8107                     , p_debug_on                   => l_debug_on
8108                     , p_needed_sec_quantity        => l_sec_needed_quantity
8109                     , p_secondary_uom              => p_secondary_uom
8110                     , p_grade_code                 => p_grade_code
8111                     , x_inserted_record            => l_inserted_record
8112                     , x_allocated_quantity         => l_allocated_quantity
8113                     , x_remaining_quantity         => l_remaining_quantity
8114                     , x_sec_allocated_quantity     => l_sec_allocated_quantity
8115                     , x_sec_remaining_quantity     => l_sec_remaining_quantity
8116                     );
8117 
8118                     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8119                        IF l_debug = 1 THEN
8120                           log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
8121                        END IF;
8122                       RAISE fnd_api.g_exc_unexpected_error;
8123                     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8124                       IF l_debug = 1 THEN
8125                          log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
8126                       END IF;
8127                       RAISE fnd_api.g_exc_error;
8128                     END IF;
8129 
8130                     --if returns false
8131                     IF l_inserted_record = FALSE
8132                        OR l_allocated_quantity < l_expected_quantity THEN
8133                       IF l_debug = 1 THEN
8134                          log_statement(l_api_name, 'insert_failed', 'Record failed to allocation.  Rolling back and ' || 'invalidating LPN');
8135                          -- rollback quantity tree
8136                          log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
8137                       END IF;
8138 
8139                       inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
8140 
8141                       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8142                         IF l_debug = 1 THEN
8143                            log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
8144                         END IF;
8145                         RAISE fnd_api.g_exc_unexpected_error;
8146                       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8147                         IF l_debug = 1 THEN
8148                            log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
8149                         END IF;
8150                         RAISE fnd_api.g_exc_error;
8151                       END IF;
8152 
8153                       -- set lpn quantity to -1
8154                       --no need to call invalidate, since we'll never see this
8155                       -- LPN record again
8156 
8157                       -- delete allocations
8158                       DELETE FROM wms_transactions_temp
8159                             WHERE line_type_code = 2
8160                               AND type_code = p_type_code;
8161 
8162                       IF l_debug_on THEN
8163                         l_cur_rec  := g_lpns(l_cur_lpn_group).first_rec;
8164                         LOOP
8165                           g_trace_recs(l_cur_rec).entire_lpn_flag  := 'N';
8166                           g_trace_recs(l_cur_rec).suggested_qty    := 0;
8167                           EXIT WHEN l_cur_rec = l_cur_lpn_rec;
8168                           l_cur_rec                                := g_locs(l_cur_rec).next_rec;
8169                         END LOOP;
8170                       END IF;
8171 
8172                       IF l_debug = 1 THEN
8173                          log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
8174                       END IF;
8175 
8176                       -- Exit loop for each rec in this LPN
8177                       EXIT;
8178                     END IF; -- didn't allocate as much as expected
8179 
8180                     --decrease quantity needed
8181                     l_needed_quantity                            := l_needed_quantity - l_allocated_quantity;
8182                     l_sec_needed_quantity                        := l_sec_needed_quantity - l_sec_allocated_quantity;
8183 
8184                     IF l_debug = 1 THEN
8185                        log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
8186                        log_statement(l_api_name, 'need_qty', 'New sec needed quantity: ' || l_sec_needed_quantity);
8187                     END IF;
8188 
8189                   --EXIT WHEN l_needed_quantity <= 0;
8190                     IF g_over_allocation = 'N'
8191                    OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8192                    OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
8193 			EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8194 		   ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8195 			IF l_max_tolerance  >= 0 THEN
8196 				EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8197 				OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8198 			ELSE
8199 				EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8200 			END IF;
8201                    END IF;
8202                     l_cur_lpn_rec                                := g_locs(l_cur_lpn_rec).next_rec;
8203                   --end loop through lpn recs
8204 
8205                   END LOOP; -- loop through recs w/in LPN
8206 
8207                   -- if no more quantity needed, exit LPN loop
8208                 --EXIT WHEN l_needed_quantity <= 0;
8209                   IF g_over_allocation = 'N'
8210                   OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8211                   OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
8212 			EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8213 		  ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8214 			IF l_max_tolerance  >= 0 THEN
8215 				EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8216 				OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8217 			ELSE
8218 				EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8219 			END IF;
8220                   END IF;
8221                 END IF; --needed qty > lpn.quantity
8222 
8223                 l_cur_lpn_group  := g_lpns(l_cur_lpn_group).next_group;
8224 
8225                 IF l_debug = 1 THEN
8226                    log_statement(l_api_name, 'next_lpn', 'Next LPN in list: ' || l_cur_lpn_group);
8227                 END IF;
8228 
8229              -- end loop through lpn groups
8230               END LOOP;
8231 
8232               --exit outermost loop
8233               IF l_debug = 1 THEN
8234                  log_statement(l_api_name, 'lpn_alloc_finished', 'Finished checking all LPNS.  Exit LPN allocation.');
8235               END IF;
8236 
8237               EXIT;
8238             END IF; --consists exist
8239           END IF; --if no more records
8240 
8241           --add record to table
8242           g_locs_index            := g_locs_index + 1;
8243 
8244           IF l_debug = 1 THEN
8245              log_statement(l_api_name, 'loc_index', 'loc index: ' || g_locs_index);
8246           END IF;
8247 
8248           g_locs(g_locs_index)    := v_current_row;
8249 
8250           --initialize trace records
8251           IF l_debug_on THEN
8252             log_statement(l_api_name, 'init_trace', 'Init trace record');
8253             g_trace_recs(g_locs_index).revision                 := v_current_row.revision;
8254             g_trace_recs(g_locs_index).lot_number               := v_current_row.lot_number;
8255             g_trace_recs(g_locs_index).lot_expiration_date      := v_current_row.lot_expiration_date;
8256             g_trace_recs(g_locs_index).subinventory_code        := v_current_row.subinventory_code;
8257             g_trace_recs(g_locs_index).locator_id               := v_current_row.locator_id;
8258             g_trace_recs(g_locs_index).cost_group_id            := v_current_row.cost_group_id;
8259             g_trace_recs(g_locs_index).lpn_id                   := v_current_row.lpn_id;
8260             g_trace_recs(g_locs_index).uom_code                 := v_current_row.uom_code;
8261             g_trace_recs(g_locs_index).quantity                 := v_current_row.quantity;
8262             g_trace_recs(g_locs_index).secondary_qty            := v_current_row.secondary_quantity;
8263             g_trace_recs(g_locs_index).grade_code               := v_current_row.grade_code;
8264             g_trace_recs(g_locs_index).secondary_uom_code       := v_current_row.secondary_uom_code;
8265             g_trace_recs(g_locs_index).serial_number            := v_current_row.serial_number;
8266             --set LPN flag to no
8267             g_trace_recs(g_locs_index).consist_string_flag      := 'V';
8268             g_trace_recs(g_locs_index).partial_pick_flag        := 'Y';
8269             g_trace_recs(g_locs_index).order_string_flag        := 'V';
8270             g_trace_recs(g_locs_index).pick_uom_flag            := 'V';
8271             g_trace_recs(g_locs_index).serial_number_used_flag  := 'V';
8272             g_trace_recs(g_locs_index).entire_lpn_flag          := 'N';
8273             --write to log file
8274            log_statement(l_api_name, 'rev', 'revision: ' || v_current_row.revision);
8275            log_statement(l_api_name, 'lot', 'lot: ' || v_current_row.lot_number);
8276            log_statement(l_api_name, 'sub', 'sub:' || v_current_row.subinventory_code);
8277            log_statement(l_api_name, 'loc', 'loc: ' || v_current_row.locator_id);
8278            log_statement(l_api_name, 'cg', 'cg: ' || v_current_row.cost_group_id);
8279            log_statement(l_api_name, 'lpn', 'lpn: ' || v_current_row.lpn_id);
8280            log_statement(l_api_name, 'sn', 'sn: ' || v_current_row.serial_number);
8281            log_statement(l_api_name, 'qty', 'quantity: ' || v_current_row.quantity);
8282            log_statement(l_api_name, 'sqty', 'secondary_quantity: ' || v_current_row.secondary_quantity);
8283            log_statement(l_api_name, 'uom', 'uom_code: ' || v_current_row.uom_code);
8284            log_statement(l_api_name, 'suom', 'secondary_uom_code: ' || v_current_row.secondary_uom_code);
8285            log_statement(l_api_name, 'ord', 'order:' || v_current_row.order_by_string);
8286            log_statement(l_api_name, 'con', 'consist:' || v_current_row.consist_string);
8287          END IF;
8288 
8289           --if lpn already exists
8290           IF g_lpns.EXISTS(v_current_row.lpn_id) THEN
8291             IF l_debug = 1 THEN
8292                log_statement(l_api_name, 'lpn_exists', 'This LPN group already exists');
8293             END IF;
8294             --if lpn consist string is different than rec's consist string,
8295             --this LPN will never be allocated entirely. Remove LPN from list.
8296             IF g_lpns(v_current_row.lpn_id).total_quantity < 0 THEN
8297               IF l_debug = 1 THEN
8298                  log_statement(l_api_name, 'invalid_lpn', 'This LPN is invalid');
8299               END IF;
8300               GOTO nextoutputrecord;
8301             ELSIF  l_consist_exists
8302                    AND g_lpns(v_current_row.lpn_id).consist_string <> v_current_row.consist_string THEN
8303 
8304               IF l_debug = 1 THEN
8305                  log_statement(l_api_name, 'no_consist', 'This record has a ' || 'different consist string than its LPN.  Invalidating LPN');
8306               END IF;
8307 
8308               invalidate_lpn_group(v_current_row.lpn_id);
8309 
8310               IF l_debug_on THEN
8311                 g_trace_recs(g_locs_index).consist_string_flag  := 'N';
8312                 l_cur_rec                                       := g_lpns(v_current_row.lpn_id).first_rec;
8313 
8314                 LOOP
8315                   EXIT WHEN l_cur_rec = 0;
8316                   g_trace_recs(l_cur_rec).consist_string_flag  := 'N';
8317                   l_cur_rec                                    := g_locs(l_cur_rec).next_rec;
8318                 END LOOP;
8319               END IF;
8320 
8321               GOTO nextoutputrecord;
8322             --bug 2356370 - need to recheck the LPN total quantity to make
8323             -- sure it doesn't exceed the needed quantity.
8324             ELSIF g_lpns(v_current_row.lpn_id).total_quantity > l_needed_quantity THEN
8325 
8326               IF l_debug = 1 THEN
8327                  log_statement(
8328                  l_api_name
8329                , 'bad_tot_qty2'
8330                , 'The total quantity for' || ' this LPN exceeds the needed quantity.  Invalidating LPN.'
8331                 );
8332               END IF;
8333 
8334               invalidate_lpn_group(v_current_row.lpn_id);
8335               --goto next output record
8336               GOTO nextoutputrecord;
8337             END IF;
8338 
8339             --increase LPN quantity
8340             g_lpns(v_current_row.lpn_id).quantity                   := g_lpns(v_current_row.lpn_id).quantity
8341                                                                        + v_current_row.quantity;
8342             g_lpns(v_current_row.lpn_id).secondary_quantity         := g_lpns(v_current_row.lpn_id).secondary_quantity
8343                                                                        + v_current_row.secondary_quantity;
8344             --set pointers
8345             g_locs(g_lpns(v_current_row.lpn_id).last_rec).next_rec  := g_locs_index;
8346             g_lpns(v_current_row.lpn_id).last_rec                   := g_locs_index;
8347           --else lpn does not already exist
8348           ELSE
8349 
8350             IF l_debug = 1 THEN
8351                log_statement(l_api_name, 'new_lpn', 'Creating a new LPN group');
8352             END IF;
8353 
8354             g_lpns(v_current_row.lpn_id).lpn_id                := v_current_row.lpn_id;
8355             g_lpns(v_current_row.lpn_id).first_rec             := g_locs_index;
8356             g_lpns(v_current_row.lpn_id).last_rec              := g_locs_index;
8357             g_lpns(v_current_row.lpn_id).quantity              := v_current_row.quantity;
8358             g_lpns(v_current_row.lpn_id).secondary_quantity    := v_current_row.secondary_quantity;
8359             g_lpns(v_current_row.lpn_id).grade_code            := v_current_row.grade_code;
8360             g_lpns(v_current_row.lpn_id).prev_group            := 0;
8361             g_lpns(v_current_row.lpn_id).next_group            := 0;
8362             g_lpns(v_current_row.lpn_id).prev_consist_lpn_id   := 0;
8363             g_lpns(v_current_row.lpn_id).next_consist_lpn_id   := 0;
8364             g_lpns(v_current_row.lpn_id).parent_consist_group  := 0;
8365             g_lpns(v_current_row.lpn_id).consist_string        := v_current_row.consist_string;
8366             --query total quantity for LPN
8367             OPEN c_lpn_quantity;
8368             FETCH c_lpn_quantity INTO g_lpns(v_current_row.lpn_id).total_quantity;
8369 
8370             IF l_debug = 1 THEN
8371                log_statement(l_api_name, 'tot_qty', 'Total quantity for this LPN: ' || g_lpns(v_current_row.lpn_id).total_quantity);
8372             END IF;
8373 
8374             --IF total quantity > quantity needed
8375             IF c_lpn_quantity%NOTFOUND
8376                OR g_lpns(v_current_row.lpn_id).total_quantity IS NULL
8377                OR g_lpns(v_current_row.lpn_id).total_quantity <= 0
8378                OR g_lpns(v_current_row.lpn_id).total_quantity > l_needed_quantity THEN
8379               CLOSE c_lpn_quantity;
8380 
8381               IF l_debug = 1 THEN
8382                  log_statement(
8383                  l_api_name
8384                  , 'bad_tot_qty'
8385                  , 'The total quantity for' || ' this LPN keeps it from being allocated.  Invalidating LPN.'
8386                  );
8387               END IF;
8388 
8389               invalidate_lpn_group(v_current_row.lpn_id);
8390               --goto next output record
8391               GOTO nextoutputrecord;
8392             END IF;
8393 
8394             CLOSE c_lpn_quantity;
8395 
8396             IF NVL(l_cur_order_by_string, '@@@') <> NVL(v_current_row.order_by_string, '@@@') THEN
8397               l_order_by_rank        := l_order_by_rank + 1;
8398               l_cur_order_by_string  := v_current_row.order_by_string;
8399 
8400               IF g_first_order_by_rank IS NULL THEN
8401                 g_first_order_by_rank  := l_order_by_rank;
8402               END IF;
8403             END IF;
8404 
8405             g_lpns(v_current_row.lpn_id).order_by_rank         := l_order_by_rank;
8406             --initialize record in LPN array
8407             g_lpns(v_current_row.lpn_id).prev_group            := g_last_lpn_group;
8408 
8409             IF g_first_lpn_group = 0 THEN
8410               g_first_lpn_group  := v_current_row.lpn_id;
8411             ELSE
8412               g_lpns(g_last_lpn_group).next_group  := v_current_row.lpn_id;
8413             END IF;
8414 
8415             g_last_lpn_group                                   := v_current_row.lpn_id;
8416           END IF; --if lpn already exists
8417 
8418           --validate from/to sub/loc
8419           --if fail, invalidate LPN and goto next output record
8420           --first check to make sure picking from dest sub is not allowed;
8421           --then, based on type code, compare src sub to dest sub;
8422           --next, check to see if sub and item are locator controlled;
8423           --if loc control, go to next record only if src loc = dest loc;
8424           --if not loc control, go to next records (since subs are equal);
8425           --all of the global variables are set in
8426           --wms_engine_pvt.create_suggestions
8427           IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
8428               AND v_current_row.subinventory_code = l_to_subinventory_code
8429              ) THEN
8430             IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
8431                 OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
8432                 OR (wms_engine_pvt.g_sub_loc_control = 5
8433                     AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
8434                    )
8435                ) THEN
8436               IF (v_current_row.locator_id = l_to_locator_id) THEN
8437 
8438                 IF l_debug = 1 THEN
8439                    log_event(
8440                      l_api_name
8441                     , 'sub_loc_same'
8442                     , 'Cannot use this ' || 'location since source subinventory and locator are' || ' same as destination subinventory and locator'
8443                     );
8444                  END IF;
8445 
8446                 IF l_debug_on THEN
8447                   g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'N';
8448                 END IF;
8449 
8450                 invalidate_lpn_group(v_current_row.lpn_id);
8451                 GOTO nextoutputrecord;
8452               END IF;
8453             ELSE
8454 
8455               IF l_debug = 1 THEN
8456                  log_event(
8457                    l_api_name
8458                    , 'sub_same'
8459                    , 'Cannot use this ' || 'location since source subinventory is ' || 'same as destination subinventory'
8460                   );
8461                END IF;
8462 
8463               IF l_debug_on THEN
8464                 g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'N';
8465               END IF;
8466 
8467               invalidate_lpn_group(v_current_row.lpn_id);
8468               GOTO nextoutputrecord;
8469             END IF;
8470           END IF;
8471 
8472           IF l_debug_on THEN
8473             g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'Y';
8474           END IF;
8475 
8476           --query quantity tree
8477           --If att < rec quantity, invalidate LPN and goto next output record
8478 
8479           IF l_debug = 1 THEN
8480              log_statement(l_api_name, 'query tree', 'Calling Query Tree');
8481           END if;
8482            -- BUG 3609380
8483            -- Allocation was being treated as a subinventory transfer, and hence not honoring
8484            -- reservations alredy made on any level higher than SUB. Changes to treat as Issue
8485            -- by removing l_to_subinevntory_code.
8486           inv_quantity_tree_pvt.query_tree
8487                  (
8488                      p_api_version_number         =>    g_qty_tree_api_version
8489                    , p_init_msg_lst               =>    fnd_api.g_false -- p_init_msg_lst
8490                    , x_return_status              =>    x_return_status
8491                    , x_msg_count                  =>    x_msg_count
8492                    , x_msg_data                   =>    x_msg_data
8493                    , p_tree_id                    =>    p_tree_id
8494                    , p_revision                   =>    v_current_row.revision
8495                    , p_lot_number                 =>    v_current_row.lot_number
8496                    , p_subinventory_code          =>    v_current_row.subinventory_code
8497                    , p_locator_id                 =>    v_current_row.locator_id
8498                    , x_qoh                        =>   l_qoh
8499                    , x_sqoh                       =>   l_sqoh
8500                    , x_rqoh                       =>   l_rqoh
8501                    , x_srqoh                      =>   l_srqoh
8502                    , x_qr                         =>   l_qr
8503                    , x_sqr                        =>   l_sqr
8504                    , x_qs                         =>   l_qs
8505                    , x_sqs                        =>   l_sqs
8506                    , x_att                        =>   l_att
8507                    , x_satt                       =>   l_satt
8508                    , x_atr                        =>   l_atr
8509                    , x_satr                       =>   l_satr
8510                    , p_transfer_subinventory_code =>    chk_for_passing_xfer_sub ( p_transaction_temp_id , l_to_subinventory_code) -- Bug# 4099907
8511                    , p_cost_group_id              =>    v_current_row.cost_group_id
8512                    , p_lpn_id                     =>    v_current_row.lpn_id
8513                  );
8514 
8515           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8516             IF l_debug = 1 THEN
8517                log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
8518             END IF;
8519             RAISE fnd_api.g_exc_unexpected_error;
8520           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8521             IF l_debug = 1 THEN
8522                log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
8523             END if;
8524             RAISE fnd_api.g_exc_error;
8525           END IF;
8526 
8527           IF l_debug = 1 THEN
8528              log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
8529           END IF;
8530 
8531           --If not all of the record is available, then we can't allocate
8532           --the entire LPN
8533           IF l_att < v_current_row.quantity THEN
8534             IF l_debug = 1 THEN
8535                log_statement(l_api_name, 'not_enough_att', 'Not all the material is available for this rec. Skipping this LPN');
8536             END IF;
8537             IF l_debug_on THEN
8538               g_trace_recs(g_locs_index).att_qty                 := l_att;
8539               g_trace_recs(g_locs_index).secondary_att_qty       := l_satt;
8540               g_trace_recs(g_locs_index).att_qty_flag            := 'N';
8541             END IF;
8542             invalidate_lpn_group(v_current_row.lpn_id);
8543             GOTO nextoutputrecord;
8544           END IF;
8545 
8546           IF l_debug_on THEN
8547             g_trace_recs(g_locs_index).att_qty                 := l_att;
8548             g_trace_recs(g_locs_index).secondary_att_qty       := l_satt;
8549             g_trace_recs(g_locs_index).att_qty_flag            := 'Y';
8550           END IF;
8551 
8552           --If LPN is not in first order by group OR
8553             --goto next output record
8554           IF g_lpns(v_current_row.lpn_id).quantity < g_lpns(v_current_row.lpn_id).total_quantity THEN
8555             IF l_debug = 1 THEN
8556                log_statement(l_api_name, 'not_enough_lpn_qty', 'Not enough quantity allocated for this LPN. Getting next record');
8557             END IF;
8558             -- Bug #5345736
8559             --invalidate_lpn_group(v_current_row.lpn_id); --bug 6831349
8560             GOTO nextoutputrecord;
8561           END IF;
8562 
8563           IF l_consist_exists THEN
8564             --find consist group
8565             -- used in get_hash_value.  That procedure works best if
8566               -- hashsize is power of 2
8567             l_hash_size                                        := POWER(2, 15);
8568             --get hash index for this consist string
8569             IF l_debug = 1 THEN
8570                log_statement(l_api_name, 'get_hash_value', 'Calling get_hash_value for consist string');
8571             END IF;
8572             l_cur_consist_group                                :=
8573             DBMS_UTILITY.get_hash_value(NAME => g_lpns(v_current_row.lpn_id).consist_string, base => 1, hash_size => l_hash_size);
8574             --Because the hash function can return the same index for different
8575             -- consist strings, we have to check to see if the group at the index
8576             -- returned above has the same consist string as the current record.
8577             -- If not, look at the next record.  Continue on until we find the
8578             -- correct consist group or determine that the group has not been
8579             -- defined yet
8580             LOOP
8581               EXIT WHEN NOT g_consists.EXISTS(l_cur_consist_group);
8582               EXIT WHEN g_consists(l_cur_consist_group).consist_string = g_lpns(v_current_row.lpn_id).consist_string;
8583               l_cur_consist_group  := l_cur_consist_group + 1;
8584             END LOOP;
8585 
8586             --see if consist group already exists
8587             --If group does exist
8588             IF g_consists.EXISTS(l_cur_consist_group) THEN
8589 
8590               IF l_debug = 1 THEN
8591                  log_statement(l_api_name, 'group_exists', 'The consist group already exists');
8592               END IF;
8593 
8594               --if lpn quantity would exceed needed quantity, invalidate lpn
8595               IF g_consists(l_cur_consist_group).quantity + g_lpns(v_current_row.lpn_id).quantity > l_needed_quantity THEN
8596 
8597                 IF l_debug = 1 THEN
8598                    log_statement(l_api_name, 'too_much_qty', 'LPN quantity would exceed quantity needed.');
8599                 END IF;
8600 
8601                 invalidate_lpn_group(v_current_row.lpn_id);
8602                 GOTO nextoutputrecord;
8603               END IF;
8604 
8605               --set pointer values
8606               g_lpns(v_current_row.lpn_id).prev_consist_lpn_id                      := g_consists(l_cur_consist_group).last_rec;
8607               g_lpns(g_consists(l_cur_consist_group).last_rec).next_consist_lpn_id  := v_current_row.lpn_id;
8608               g_consists(l_cur_consist_group).last_rec                              := v_current_row.lpn_id;
8609               --increase group quantity
8610               --g_consists(l_cur_consist_group).quantity                              :=
8611                --                                                               g_consists(l_cur_consist_group).quantity + l_possible_quantity;
8612 	       g_consists(l_cur_consist_group).quantity				:= g_consists(l_cur_consist_group).quantity + g_lpns(v_current_row.lpn_id).quantity;
8613             --If group does not exist
8614             ELSE
8615 
8616               IF l_debug = 1 THEN
8617                  log_statement(l_api_name, 'new_group', 'Creating a new consist group');
8618               END IF;
8619 
8620               --create new group
8621               g_consists(l_cur_consist_group).consist_string            := g_lpns(v_current_row.lpn_id).consist_string;
8622               g_consists(l_cur_consist_group).first_rec                 := v_current_row.lpn_id;
8623               g_consists(l_cur_consist_group).last_rec                  := v_current_row.lpn_id;
8624               g_consists(l_cur_consist_group).next_group                := 0;
8625               g_consists(l_cur_consist_group).quantity                  := v_current_row.quantity;
8626               g_consists(l_cur_consist_group).secondary_quantity        := v_current_row.secondary_quantity;
8627               g_consists(l_cur_consist_group).grade_code                := v_current_row.grade_code;
8628               g_consists(l_cur_consist_group).order_by_rank             := g_lpns(v_current_row.lpn_id).order_by_rank;
8629 
8630               IF g_first_consist_group = 0 THEN
8631                 g_first_consist_group  := l_cur_consist_group;
8632               ELSE
8633                 g_consists(g_last_consist_group).next_group  := l_cur_consist_group;
8634               END IF;
8635 
8636               g_last_consist_group                            := l_cur_consist_group;
8637             END IF;
8638 
8639             g_lpns(v_current_row.lpn_id).parent_consist_group  := l_cur_consist_group;
8640 
8641             --only allocate a consist group if the quantity = needed quantity
8642             --exactly
8643             --IF g_consists(l_cur_consist_group).quantity <> l_needed_quantity THEN
8644 	    IF g_consists(l_cur_consist_group).quantity < l_needed_quantity - l_max_tolerance THEN
8645 
8646               IF l_debug = 1 THEN
8647                  log_statement(l_api_name, 'not_enough_qty', 'Not enough quantity to allocate consist group');
8648               END IF;
8649 
8650               GOTO nextoutputrecord;
8651             END IF;
8652 
8653             IF g_consists(l_cur_consist_group).order_by_rank <> g_first_order_by_rank THEN
8654               IF l_debug = 1 THEN
8655                  log_statement(l_api_name, 'consist_order_by', 'Consist group is not first based on sort criteria');
8656               END IF;
8657               GOTO nextoutputrecord;
8658             END IF;
8659 
8660             l_lpn_id                                           := g_consists(l_cur_consist_group).first_rec;
8661           -- no consists
8662           ELSIF g_lpns(v_current_row.lpn_id).order_by_rank <> g_first_order_by_rank THEN
8663 
8664             IF l_debug = 1 THEN
8665                log_statement(l_api_name, 'not_first_order_by', 'Not first LPN based on sort criteria.  Getting next record.');
8666             END IF;
8667             GOTO nextoutputrecord;
8668           ELSE
8669             l_lpn_id  := v_current_row.lpn_id;
8670           END IF;
8671 
8672           LOOP -- loop through LPNS
8673             --Allocation process.  If consist exists, we loop through all
8674             -- the lpns in the consist group.  If no consistency restrictions,
8675             -- we exit the loop after allocating the first lpn
8676 
8677             IF l_debug = 1 THEN
8678                log_statement(l_api_name, 'alloc_lpn', 'Allocation lpn: ' || l_lpn_id);
8679             END IF;
8680 
8681            --Allocate the LPN, since the LPN is in the first order by group
8682             --  and the LPN has all possible suggestions
8683             --For each record in LPN
8684             l_cur_lpn_rec      := g_lpns(l_lpn_id).first_rec;
8685 
8686             LOOP
8687               EXIT WHEN l_cur_lpn_rec = 0;
8688 
8689               --Call validate and insert
8690               IF l_debug_on THEN
8691                 g_trace_recs(l_cur_lpn_rec).consist_string_flag  := 'Y';
8692                 g_trace_recs(l_cur_lpn_rec).entire_lpn_flag      := 'Y';
8693               END IF;
8694 
8695               IF l_debug = 1 THEN
8696                  log_statement(l_api_name, 'val_insert', 'Calling validate_and_insert');
8697               END IF;
8698 
8699               validate_and_insert(
8700                 x_return_status              => x_return_status
8701               , x_msg_count                  => x_msg_count
8702               , x_msg_data                   => x_msg_data
8703               , p_record_id                  => l_cur_lpn_rec
8704               , p_needed_quantity            => l_needed_quantity
8705               , p_use_pick_uom               => FALSE
8706               , p_organization_id            => p_organization_id
8707               , p_inventory_item_id          => p_inventory_item_id
8708               , p_to_subinventory_code       => l_to_subinventory_code
8709               , p_to_locator_id              => l_to_locator_id
8710               , p_to_cost_group_id           => l_to_cost_group_id
8711               , p_primary_uom                => p_primary_uom
8712               , p_transaction_uom            => p_transaction_uom
8713               , p_transaction_temp_id        => p_transaction_temp_id
8714               , p_type_code                  => p_type_code
8715               , p_rule_id                    => l_rule_id
8716               , p_reservation_id             => l_reservation_id
8717               , p_tree_id                    => p_tree_id
8718               , p_debug_on                   => l_debug_on
8719               , p_needed_sec_quantity        => l_sec_needed_quantity
8720               , p_secondary_uom              => p_secondary_uom
8721               , p_grade_code                 => p_grade_code
8722               , x_inserted_record            => l_inserted_record
8723               , x_allocated_quantity         => l_allocated_quantity
8724               , x_remaining_quantity         => l_remaining_quantity
8725               , x_sec_allocated_quantity     => l_sec_allocated_quantity
8726               , x_sec_remaining_quantity     => l_sec_remaining_quantity
8727               );
8728 
8729               IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8730 
8731                 IF l_debug = 1 THEN
8732                    log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
8733                 END IF;
8734 
8735                 RAISE fnd_api.g_exc_unexpected_error;
8736               ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8737 
8738                 IF l_debug = 1 THEN
8739                    log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
8740                 END IF;
8741 
8742                 RAISE fnd_api.g_exc_error;
8743               END IF;
8744 
8745               --If this fails
8746               IF l_inserted_record = FALSE
8747                  OR l_allocated_quantity < g_locs(l_cur_lpn_rec).quantity THEN
8748 
8749                 IF l_debug = 1 THEN
8750                    log_statement(l_api_name, 'insert_fail', 'Record failed to insert.' || 'Invalidating LPN');
8751                 END IF;
8752 
8753                 --invalidate LPN
8754                 IF l_consist_exists THEN
8755                   l_cur_consist_group                       := g_lpns(l_lpn_id).parent_consist_group;
8756                   l_prev_rec                                := g_lpns(l_lpn_id).prev_consist_lpn_id;
8757                   l_next_rec                                := g_lpns(l_lpn_id).next_consist_lpn_id;
8758                   g_consists(l_cur_consist_group).quantity  := g_consists(l_cur_consist_group).quantity - g_lpns(l_lpn_id).quantity;
8759                   g_consists(l_cur_consist_group).secondary_quantity  :=
8760                                       g_consists(l_cur_consist_group).secondary_quantity - g_lpns(l_lpn_id).secondary_quantity;
8761 
8762                   IF g_consists(l_cur_consist_group).first_rec = l_lpn_id THEN
8763                     g_consists(l_cur_consist_group).first_rec      := l_next_rec;
8764                     g_consists(l_cur_consist_group).order_by_rank  := g_lpns(l_next_rec).order_by_rank;
8765                   END IF;
8766 
8767                   IF g_consists(l_cur_consist_group).last_rec = l_lpn_id THEN
8768                     g_consists(l_cur_consist_group).last_rec  := l_prev_rec;
8769                   END IF;
8770 
8771                   g_lpns(l_next_rec).prev_consist_lpn_id    := l_prev_rec;
8772                   g_lpns(l_prev_rec).next_consist_lpn_id    := l_next_rec;
8773                 END IF;
8774 
8775                 invalidate_lpn_group(l_lpn_id);
8776                 --restore quantity tree
8777 
8778                 IF l_debug = 1 THEN
8779                   log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
8780                 END IF;
8781 
8782                 inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
8783 
8784                 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8785 
8786                   IF l_debug = 1 THEN
8787                      log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
8788                   END IF;
8789 
8790                   RAISE fnd_api.g_exc_unexpected_error;
8791                 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8792 
8793                   IF l_debug = 1 THEN
8794                      log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
8795                   END IF;
8796 
8797                   RAISE fnd_api.g_exc_error;
8798                 END IF;
8799 
8800                 --delete allocations
8801                 --is this okay?? what if multiple input lines?
8802                 DELETE FROM wms_transactions_temp
8803                       WHERE line_type_code = 2
8804                         AND type_code = p_type_code;
8805 
8806                 IF l_debug_on THEN
8807                   l_cur_rec  := g_lpns(l_lpn_id).first_rec;
8808 
8809                   LOOP
8810                     g_trace_recs(l_cur_rec).entire_lpn_flag  := 'N';
8811                     g_trace_recs(l_cur_rec).suggested_qty    := 0;
8812                     EXIT WHEN l_cur_rec = l_cur_lpn_rec;
8813                     l_cur_rec                                := g_locs(l_cur_rec).next_rec;
8814                   END LOOP;
8815                 END IF;
8816 
8817                 IF l_debug = 1 THEN
8818                    log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
8819                 END IF;
8820 
8821                -- With this LPN invalidated, go get next record
8822                 GOTO nextoutputrecord;
8823               END IF;
8824 
8825               l_cur_lpn_rec  := g_locs(l_cur_lpn_rec).next_rec;
8826             --end loop (each rec in lpn)
8827             END LOOP;
8828 
8829             --decrease quantity needed
8830             l_needed_quantity  := l_needed_quantity - g_lpns(l_lpn_id).quantity;
8831             l_sec_needed_quantity  := l_sec_needed_quantity - g_lpns(l_lpn_id).secondary_quantity;
8832 
8833             IF l_debug = 1 THEN
8834                log_statement(l_api_name, 'need_qty', 'New Needed Quantity: ' || l_needed_quantity);
8835                log_statement(l_api_name, 'need_qty', 'New sec Needed Quantity: ' || l_sec_needed_quantity);
8836             END IF;
8837 
8838             --EXIT WHEN l_needed_quantity = 0;
8839             IF g_over_allocation = 'N'
8840             OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8841             OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
8842               EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8843             ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8844               IF l_max_tolerance  >= 0 THEN
8845                  EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8846                  OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8847               ELSE
8848                  EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8849               END IF;
8850             END IF;
8851 
8852             --Once LPN has been allocated, remove it from the LPN list
8853             IF l_consist_exists THEN
8854               l_lpn_id  := g_lpns(l_lpn_id).next_consist_lpn_id;
8855               EXIT WHEN l_lpn_id = 0;
8856             ELSE
8857               invalidate_lpn_group(l_lpn_id);
8858               EXIT;
8859             END IF;
8860           END LOOP; -- loop through LPNS
8861 
8862          -- EXIT WHEN l_needed_quantity <= 0;
8863           IF g_over_allocation = 'N'
8864             OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8865             OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
8866               EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8867             ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8868               IF l_max_tolerance  >= 0 THEN
8869                  EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8870                  OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8871               ELSE
8872                  EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8873               END IF;
8874             END IF;
8875 
8876           <<nextoutputrecord>>
8877           NULL;
8878         --End outermost loop
8879         END LOOP;
8880       --else if type code = 2
8881       --PICK
8882       ELSIF p_type_code = 2 THEN
8883         l_cur_uom_rec          := 0;
8884         l_first_uom_rec        := 0;
8885         l_last_uom_rec         := 0;
8886         l_cur_consist_group    := 0;
8887         g_first_consist_group  := 0;
8888 
8889         IF l_debug = 1 THEN
8890            log_statement(l_api_name, 'start_alloc', 'Start allocation process');
8891         END IF;
8892 
8893         --for each record returned from cursor
8894         LOOP --Get record from rules cursor
8895           IF l_debug = 1 THEN
8896              log_statement(l_api_name, 'fetch_cursor', 'Getting rec from rule with FetchCursor');
8897           END IF;
8898           -- Added the loop for Mat Stat check --
8899           LOOP
8900            if l_debug = 1 THEN
8901               log_statement(l_api_name, 'fetch_cursor', 'inside Mat Stat check LOOP');
8902            END IF;
8903            --  Mat Stat --
8904               fetchcursor(
8905                 x_return_status
8906               , x_msg_count
8907               , x_msg_data
8908               , v_pick_cursor
8909               , l_rule_id
8910               , v_current_row.revision
8911               , v_current_row.lot_number
8912               , v_current_row.lot_expiration_date
8913               , v_current_row.subinventory_code
8914               , v_current_row.locator_id
8915               , v_current_row.cost_group_id
8916               , v_current_row.uom_code
8917               , v_current_row.lpn_id
8918               , v_current_row.serial_number
8919               , v_current_row.quantity
8920               , v_current_row.secondary_quantity               -- new
8921               , v_current_row.grade_code                       -- new
8922               , v_current_row.consist_string
8923               , v_current_row.order_by_string
8924               , l_rows
8925               );
8926 
8927               IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8928                 IF l_debug = 1 THEN
8929                    log_error(l_api_name, 'uerr_fetch_cursor', 'Unexpected error in FetchCursor');
8930                 END IF;
8931                 RAISE fnd_api.g_exc_unexpected_error;
8932               ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8933                 IF l_debug = 1 THEN
8934                    log_error(l_api_name, 'err_fetch_cursor', 'Error in FetchCursor');
8935                 END IF;
8936                 RAISE fnd_api.g_exc_error;
8937               END IF;
8938 
8939            --  is_serial_trx_allowed is_sub_loc_lot_trx_allowed
8940             EXIT WHEN  nvl(l_rows, 0)  = 0 ;  -- [ Added to to exit , if the rule is not returning any rows
8941             l_sub_loc_lot_trx_allowed   := 'Y';
8942             l_serial_trx_allowed        := 'Y';
8943             l_serial_status_id   := 0;
8944 
8945            IF l_debug = 1 THEN
8946               log_statement(l_api_name, 'Serial Status - l_detail_serial ', l_detail_serial);
8947               log_statement(l_api_name, 'fetch_cursor - l_rows ', l_rows);
8948               log_statement(l_api_name, 'fetch_cursor - v_current_row.lot_number ', v_current_row.lot_number);
8949               log_statement(l_api_name, 'fetch_cursor - v_current_row.serial_number ', v_current_row.serial_number);
8950            END IF;
8951             IF v_current_row.serial_number IS NOT NULL  THEN
8952 
8953                IF l_detail_serial = 1 THEN
8954                  select status_id
8955                    into l_serial_status_id
8956                    from mtl_serial_numbers
8957                   where inventory_item_id       = p_inventory_item_id
8958                     and current_organization_id = p_organization_id
8959                     and serial_number           = v_current_row.serial_number;
8960 
8961                    l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
8962                                                                  p_transaction_type_id
8963                                                                 ,p_organization_id
8964                                                                 ,p_inventory_item_id
8965                                                                 ,l_serial_status_id) ;
8966                 END IF;
8967                 IF l_debug = 1 THEN
8968 
8969                    log_statement(l_api_name, 'Serial Status - p_transaction_type_id ', p_transaction_type_id);
8970                    log_statement(l_api_name, 'Serial Status - p_organization_id ', p_organization_id);
8971                    log_statement(l_api_name, 'Serial Status - p_inventory_item_id ', p_inventory_item_id);
8972                    log_statement(l_api_name, 'Serial Status - serial_number ', v_current_row.serial_number);
8973                    log_statement(l_api_name, 'Serial Status - l_serial_status_id ', l_serial_status_id);
8974                    log_statement(l_api_name, 'Serial Status - l_serial_trx_allowed ', l_serial_trx_allowed);
8975 
8976                 END IF;
8977             END IF;
8978             -- Bug 4756156
8979             -- IF  ((v_current_row.lot_number IS NOT NULL)  AND (l_lot_status  = 'Y'))  THEN
8980              -- LPN Status Project
8981                l_onhand_status_trx_allowed := 'Y';
8982                IF l_default_status_id = -1 THEN
8983                       l_onhand_status_trx_allowed := 'N';
8984 	              l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
8985 			                         p_transaction_type_id
8986 				                ,p_organization_id
8987 					        ,p_inventory_item_id
8988 	                                        ,v_current_row.subinventory_code
8989 		                                ,v_current_row.locator_id
8990 			                        ,v_current_row.lot_number);
8991 
8992 					/*log_statement(l_api_name, 'Stasus', 'Before calling my method-Amrita);
8993 	                          	l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
8994                                            p_transaction_type_id
8995                                         ,p_organization_id
8996                                         ,p_inventory_item_id
8997                                         ,v_current_row.subinventory_code
8998                                         ,v_current_row.locator_id
8999                                         ,v_current_row.lot_number);*/
9000                                  IF l_debug = 1 THEN
9001                                       log_statement(l_api_name, 'fetch_cursor - l_sub_loc_lot_trx_allowed: ', l_sub_loc_lot_trx_allowed);
9002                                 END IF;
9003 
9004 	      ELSE
9005 		    l_sub_loc_lot_trx_allowed:='N';
9006 		    if (inv_cache.item_rec.serial_number_control_code in (1,6)) then
9007                     l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
9008 		               	        p_transaction_type_id
9009                                         ,p_organization_id
9010                                         ,p_inventory_item_id
9011                                         ,v_current_row.subinventory_code
9012                                         ,v_current_row.locator_id
9013                                         ,v_current_row.lot_number
9014 		                        , v_current_row.lpn_id);
9015 		    end if;
9016 		        IF l_debug = 1 THEN
9017 	                     log_statement(l_api_name, 'fetch_cursor - l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
9018                         END IF;
9019 	      END IF;
9020 
9021                    -- END IF;
9022            EXIT WHEN  (    l_serial_trx_allowed      = 'Y'
9023                        and (l_sub_loc_lot_trx_allowed = 'Y' OR l_onhand_status_trx_allowed='Y'));
9024 
9025            -- >> Else fetch next record from the rule cursor --
9026          END LOOP;
9027          -- End of Mat Stat Check --
9028 	-- LPN Status Project
9029 
9030           v_current_row.next_rec  := 0;
9031 
9032           --if no more records
9033           IF l_rows = 0 THEN
9034             IF l_debug = 1 THEN
9035                log_statement(l_api_name, 'no_recs', 'No more records from cursor');
9036             END IF;
9037 
9038 
9039 	    -- (FOR R12.1 REPLENISHMENT PROJECT - 6681109) STARTS ---
9040 	    -- IN R12 BRANCH , the code will not do any harm as the allocation mode = 5 value
9041 	    -- is only available in R12 Main Line code and the logic in contained WITH value =  here
9042 
9043 	    -- if allocation mode = 5
9044 	    IF  l_allocation_mode = 5
9045 	      AND l_first_uom_rec <> 0 and l_needed_quantity > 0 THEN
9046 	       -- After all location-based records (from where there was possibility of getting allocation in the
9047 	       -- first round of scan) gets exhausted, it comes here for the second round of scan. At that point,
9048 	       -- we know the final unallocated qty after the first round of scan and that is the qty which are
9049 	       -- candidate for replenishment
9050 
9051 	       IF l_debug = 1 THEN
9052 		  log_statement(l_api_name, 'exit_final_unallocated_qty',
9053 		'Can not allocate any further with pick UOM for current input RECORD - COMING out of the outer loop');
9054 	       END IF;
9055 
9056 	       EXIT; -- Can not allocate any further; so come out of the outer loop
9057 
9058 	       -- (FOR R12.1 REPLENISHMENT PROJECT - 6681109) ENDS ---
9059 
9060 	       --if allocation mode IN 3,4
9061 	     ELSIF  l_allocation_mode IN (3, 4)
9062 	       AND l_first_uom_rec <> 0 THEN
9063 	       --for each record in pick uom list
9064 	       IF l_debug = 1 THEN
9065 		  log_statement(l_api_name, 'pick_uom', 'Allocate pick UOM table');
9066 	       END IF;
9067 	       LOOP
9068 		  l_cur_uom_rec                   := l_first_uom_rec;
9069 		  EXIT WHEN l_cur_uom_rec = 0;
9070 		  --remove rec from list
9071 		  l_first_uom_rec                 := g_locs(l_cur_uom_rec).next_rec;
9072 		  g_locs(l_cur_uom_rec).next_rec  := 0;
9073 
9074 		  --If consist restrictions
9075 		  IF l_consist_exists THEN
9076 
9077                   IF l_debug = 1 THEN
9078                      log_statement(l_api_name, 'insert_consist', 'Calling Insert_Consist_Record');
9079                   END IF;
9080 
9081                   --call insert consist record
9082                   insert_consist_record(
9083                     x_return_status              => x_return_status
9084                   , x_msg_count                  => x_msg_count
9085                   , x_msg_data                   => x_msg_data
9086                   , p_record_id                  => l_cur_uom_rec
9087                   , p_needed_quantity            => l_needed_quantity
9088                   , p_use_pick_uom               => FALSE
9089                   , p_organization_id            => p_organization_id
9090                   , p_inventory_item_id          => p_inventory_item_id
9091                   , p_to_subinventory_code       => l_to_subinventory_code
9092                   , p_to_locator_id              => l_to_locator_id
9093                   , p_to_cost_group_id           => l_to_cost_group_id
9094                   , p_primary_uom                => p_primary_uom
9095                   , p_transaction_uom            => p_transaction_uom
9096                   , p_transaction_temp_id        => p_transaction_temp_id
9097                   , p_type_code                  => p_type_code
9098                   , p_rule_id                    => l_rule_id
9099                   , p_reservation_id             => l_reservation_id
9100                   , p_tree_id                    => p_tree_id
9101                   , p_debug_on                   => l_debug_on
9102                   , p_order_by_rank              => l_order_by_rank
9103                   , p_needed_sec_quantity        => l_sec_needed_quantity
9104                   , p_secondary_uom              => p_secondary_uom
9105                   , p_grade_code                 => p_grade_code
9106                   , x_finished                   => l_finished
9107                   , x_remaining_quantity         => l_remaining_quantity
9108                   );
9109 
9110                   IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9111                     IF l_debug = 1 THEN
9112                        log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
9113                     END IF;
9114                     RAISE fnd_api.g_exc_unexpected_error;
9115                   ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9116                     IF l_debug = 1 THEN
9117                        log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
9118                     END IF;
9119                     RAISE fnd_api.g_exc_error;
9120                   END IF;
9121 
9122                   --if allocated a consist group, exit pick uom loop
9123                   IF l_finished THEN
9124                     IF l_debug = 1 THEN
9125                        log_statement(l_api_name, 'consist_finished', 'Allocated all needed quantity with consist group');
9126                     END IF;
9127                     l_needed_quantity  := 0;
9128                     l_sec_needed_quantity  := 0;
9129                     EXIT;
9130                   END IF;
9131                 --else no consist restrictions
9132                 ELSE
9133                   IF l_debug = 1 THEN
9134                      log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_Insert');
9135                   END IF;
9136                   --call Validate and insert
9137                   validate_and_insert(
9138                     x_return_status              => x_return_status
9139                   , x_msg_count                  => x_msg_count
9140                   , x_msg_data                   => x_msg_data
9141                   , p_record_id                  => l_cur_uom_rec
9142                   , p_needed_quantity            => l_needed_quantity
9143                   , p_use_pick_uom               => FALSE
9144                   , p_organization_id            => p_organization_id
9145                   , p_inventory_item_id          => p_inventory_item_id
9146                   , p_to_subinventory_code       => l_to_subinventory_code
9147                   , p_to_locator_id              => l_to_locator_id
9148                   , p_to_cost_group_id           => l_to_cost_group_id
9149                   , p_primary_uom                => p_primary_uom
9150                   , p_transaction_uom            => p_transaction_uom
9151                   , p_transaction_temp_id        => p_transaction_temp_id
9152                   , p_type_code                  => p_type_code
9153                   , p_rule_id                    => l_rule_id
9154                   , p_reservation_id             => l_reservation_id
9155                   , p_tree_id                    => p_tree_id
9156                   , p_debug_on                   => l_debug_on
9157                   , p_needed_sec_quantity        => l_sec_needed_quantity
9158                   , p_secondary_uom              => p_secondary_uom
9159                   , p_grade_code                 => p_grade_code
9160                   , x_inserted_record            => l_inserted_record
9161                   , x_allocated_quantity         => l_allocated_quantity
9162                   , x_remaining_quantity         => l_remaining_quantity
9163                   , x_sec_allocated_quantity     => l_sec_allocated_quantity
9164                   , x_sec_remaining_quantity     => l_sec_remaining_quantity
9165                   );
9166 
9167                   IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9168                     IF l_debug = 1 THEN
9169                        log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9170                     END IF;
9171                     RAISE fnd_api.g_exc_unexpected_error;
9172                   ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9173                     IF l_debug = 1 THEN
9174                        log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9175                     END IF;
9176                     RAISE fnd_api.g_exc_error;
9177                   END IF;
9178 
9179                   --If returns true, decrease needed quantity
9180                   IF l_inserted_record THEN
9181                     l_needed_quantity  := l_needed_quantity - l_allocated_quantity;
9182                     l_sec_needed_quantity  := l_sec_needed_quantity - l_sec_allocated_quantity;
9183                     IF l_debug = 1 THEN
9184                        log_statement(l_api_name, 'need_qty', 'New Needed quantity: ' || l_needed_quantity);
9185                        log_statement(l_api_name, 'sec need_qty', 'sec New Needed quantity: ' || l_sec_needed_quantity);
9186                     END IF;
9187                   END IF;
9188                 END IF; -- consist records
9189 
9190                 --exit pick UOM loop when needed qty = 0
9191                 --EXIT WHEN l_needed_quantity = 0;
9192                 IF g_over_allocation = 'N'
9193                 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9194                 OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
9195 			EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9196                 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9197 			IF l_max_tolerance  >= 0 THEN
9198 				EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9199 				OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9200 			ELSE
9201 				EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9202 			END IF;
9203                 END IF;
9204                 --end loop (pick UOM)
9205                 l_cur_uom_rec                   := g_locs(l_cur_uom_rec).next_rec;
9206               END LOOP; --pick UOM
9207 
9208               --if needed qty = 0, exit outer loop
9209             --EXIT WHEN l_needed_quantity = 0;
9210               IF g_over_allocation = 'N'
9211               OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9212               OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
9213 			EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9214 	      ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9215 			IF l_max_tolerance  >= 0 THEN
9216 				EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9217 				OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9218 			ELSE
9219 				EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9220 			END IF;
9221               END IF;
9222             END IF; --allocation mode in 3,4
9223 
9224             --if consist restrictions
9225             IF l_consist_exists THEN
9226 
9227               IF l_debug = 1 THEN
9228                  log_statement(l_api_name, 'consist', 'Reading from consist groups');
9229               END IF;
9230               --for each record in consist group
9231               l_cur_consist_group  := g_first_consist_group;
9232 
9233               IF l_debug = 1 THEN
9234                  log_statement(l_api_name, 'first_consist', 'First consist group:' || g_first_consist_group);
9235               END IF;
9236 
9237               LOOP
9238                 EXIT WHEN l_cur_consist_group = 0;
9239 
9240                 --if group alloc qty > needed qty
9241                 IF g_consists(l_cur_consist_group).quantity >= l_needed_quantity THEN
9242                   IF l_debug = 1 THEN
9243                      log_statement(l_api_name, 'alloc_consist', 'Found a consist group to allocate');
9244                   END IF;
9245                   --call allocate_consist_group
9246                   allocate_consist_group(
9247                     x_return_status              => x_return_status
9248                   , x_msg_count                  => x_msg_count
9249                   , x_msg_data                   => x_msg_data
9250                   , p_group_id                   => l_cur_consist_group
9251                   , p_needed_quantity            => l_needed_quantity
9252                   , p_use_pick_uom               => FALSE
9253                   , p_organization_id            => p_organization_id
9254                   , p_inventory_item_id          => p_inventory_item_id
9255                   , p_to_subinventory_code       => l_to_subinventory_code
9256                   , p_to_locator_id              => l_to_locator_id
9257                   , p_to_cost_group_id           => l_to_cost_group_id
9258                   , p_primary_uom                => p_primary_uom
9259                   , p_transaction_uom            => p_transaction_uom
9260                   , p_transaction_temp_id        => p_transaction_temp_id
9261                   , p_type_code                  => p_type_code
9262                   , p_rule_id                    => l_rule_id
9263                   , p_reservation_id             => l_reservation_id
9264                   , p_tree_id                    => p_tree_id
9265                   , p_debug_on                   => l_debug_on
9266                   , p_needed_sec_quantity        => l_sec_needed_quantity
9267                   , p_secondary_uom              => p_secondary_uom
9268                   , p_grade_code                 => p_grade_code
9269                   , p_lot_divisible_flag         => inv_cache.item_rec.lot_divisible_flag
9270                   , x_success                    => l_finished
9271                   );
9272 
9273                   IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9274                     IF l_debug = 1 THEN
9275                        log_statement(l_api_name, 'uerr_allocate_consist', 'Unexpected error in allocate_consist_group');
9276                     END IF;
9277                     RAISE fnd_api.g_exc_unexpected_error;
9278                   ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9279                     IF l_debug = 1 THEN
9280                        log_statement(l_api_name, 'err_allocate_consist', 'Error in allocate_consist_group');
9281                     END IF;
9282                     RAISE fnd_api.g_exc_error;
9283                   END IF;
9284 
9285                   --if finished = true
9286                   --exit consist restrictions loop
9287                   IF l_finished THEN
9288                     IF l_debug = 1 THEN
9289                        log_statement(l_api_name, 'allocated_consist', 'Successfully allocated consistency group');
9290                     END IF;
9291                     l_needed_quantity  := 0;
9292                     l_sec_needed_quantity  := 0;
9293                     EXIT;
9294                   END IF;
9295                 END IF;
9296 
9297                 --end consist loop
9298                 l_cur_consist_group  := g_consists(l_cur_consist_group).next_group;
9299 
9300                 IF l_debug = 1 THEN
9301                    log_statement(l_api_name, 'next_consist', 'Next consist group: ' || l_cur_consist_group);
9302                 END IF;
9303 
9304              END LOOP;
9305             --Exit outermost loop
9306             END IF; -- consist records
9307 
9308             IF l_debug = 1 THEN
9309                log_statement(l_api_name, 'end_alloc', 'No more pick UOM or ' || 'consistecy records to Allocate.');
9310             END IF;
9311 
9312             EXIT;
9313           END IF; --no more record
9314 
9315           IF l_debug = 1 THEN
9316              log_statement(l_api_name, 'order_string', 'Checking order string');
9317           END IF;
9318 
9319           --if allocation mode = 3 and record has different order by string
9320           IF  l_allocation_mode = 3
9321               AND l_first_uom_rec <> 0
9322               AND v_current_row.order_by_string <> l_cur_order_by_string THEN
9323 
9324             IF l_debug = 1 THEN
9325                log_statement(l_api_name, 'change string', 'The order_by_string has changed.  Reading from pick UOM list');
9326             END IF;
9327 
9328             l_cur_uom_rec    := l_first_uom_rec;
9329 
9330             LOOP
9331               EXIT WHEN l_cur_uom_rec = 0;
9332 
9333               --If consist restrictions
9334               IF l_consist_exists THEN
9335 
9336                 IF l_debug = 1 THEN
9337                    log_statement(l_api_name, 'insert_consist', 'Calling insert consist record from pick UOM list');
9338                 END IF;
9339 
9340                 --call insert consist record
9341                 insert_consist_record(
9342                   x_return_status              => x_return_status
9343                 , x_msg_count                  => x_msg_count
9344                 , x_msg_data                   => x_msg_data
9345                 , p_record_id                  => l_cur_uom_rec
9346                 , p_needed_quantity            => l_needed_quantity
9347                 , p_use_pick_uom               => FALSE
9348                 , p_organization_id            => p_organization_id
9349                 , p_inventory_item_id          => p_inventory_item_id
9350                 , p_to_subinventory_code       => l_to_subinventory_code
9351                 , p_to_locator_id              => l_to_locator_id
9352                 , p_to_cost_group_id           => l_to_cost_group_id
9353                 , p_primary_uom                => p_primary_uom
9354                 , p_transaction_uom            => p_transaction_uom
9355                 , p_transaction_temp_id        => p_transaction_temp_id
9356                 , p_type_code                  => p_type_code
9357                 , p_rule_id                    => l_rule_id
9358                 , p_reservation_id             => l_reservation_id
9359                 , p_tree_id                    => p_tree_id
9360                 , p_debug_on                   => l_debug_on
9361                 , p_order_by_rank              => l_order_by_rank
9362                 , p_needed_sec_quantity        => l_sec_needed_quantity
9363                 , p_secondary_uom              => p_secondary_uom
9364                 , p_grade_code                 => p_grade_code
9365                 , x_finished                   => l_finished
9366                 , x_remaining_quantity         => l_remaining_quantity
9367                 );
9368 
9369                 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9370                   IF l_debug = 1 THEN
9371                      log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
9372                   END IF;
9373                   RAISE fnd_api.g_exc_unexpected_error;
9374                 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9375                   IF l_debug = 1 THEN
9376                      log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
9377                   END IF;
9378                   RAISE fnd_api.g_exc_error;
9379                 END IF;
9380 
9381                 --if allocated a consist group, exit pick uom loop
9382                 IF l_finished THEN
9383 
9384                   IF l_debug = 1 THEN
9385                      log_statement(l_api_name, 'finish_consist', 'Successfully allocated a consistency group');
9386                   END IF;
9387 
9388                   l_needed_quantity  := 0;
9389                   l_sec_needed_quantity  := 0;
9390                   EXIT;
9391                 END IF;
9392               --else no consist restrictions
9393               ELSE
9394 
9395                 IF l_debug = 1 THEN
9396                    log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_insert for pick uom list');
9397                 END IF;
9398 
9399                --call Validate and insert
9400                 validate_and_insert(
9401                   x_return_status              => x_return_status
9402                 , x_msg_count                  => x_msg_count
9403                 , x_msg_data                   => x_msg_data
9404                 , p_record_id                  => l_cur_uom_rec
9405                 , p_needed_quantity            => l_needed_quantity
9406                 , p_use_pick_uom               => FALSE
9407                 , p_organization_id            => p_organization_id
9408                 , p_inventory_item_id          => p_inventory_item_id
9409                 , p_to_subinventory_code       => l_to_subinventory_code
9410                 , p_to_locator_id              => l_to_locator_id
9411                 , p_to_cost_group_id           => l_to_cost_group_id
9412                 , p_primary_uom                => p_primary_uom
9413                 , p_transaction_uom            => p_transaction_uom
9414                 , p_transaction_temp_id        => p_transaction_temp_id
9415                 , p_type_code                  => p_type_code
9416                 , p_rule_id                    => l_rule_id
9417                 , p_reservation_id             => l_reservation_id
9418                 , p_tree_id                    => p_tree_id
9419                 , p_debug_on                   => l_debug_on
9420                 , p_needed_sec_quantity        => l_sec_needed_quantity
9421                 , p_secondary_uom              => p_secondary_uom
9422                 , p_grade_code                 => p_grade_code
9423                 , x_inserted_record            => l_inserted_record
9424                 , x_allocated_quantity         => l_allocated_quantity
9425                 , x_remaining_quantity         => l_remaining_quantity
9426                 , x_sec_allocated_quantity     => l_sec_allocated_quantity
9427                 , x_sec_remaining_quantity     => l_sec_remaining_quantity
9428                 );
9429 
9430                 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9431                   IF l_debug = 1 THEN
9432                      log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9433                   END IF;
9434                   RAISE fnd_api.g_exc_unexpected_error;
9435                 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9436                   IF l_debug = 1 THEN
9437                      log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9438                   END IF;
9439                   RAISE fnd_api.g_exc_error;
9440                 END IF;
9441 
9442                 --If returns true, decrease needed quantity
9443                 IF l_inserted_record THEN
9444                   l_needed_quantity  := l_needed_quantity - l_allocated_quantity;
9445                   l_sec_needed_quantity  := l_sec_needed_quantity - l_sec_allocated_quantity;
9446 
9447                   IF l_debug = 1 THEN
9448                      log_statement(l_api_name, 'success_validate', 'Successfully inserted record.  New needed quantity: ' || l_needed_quantity);
9449                      log_statement(l_api_name, 'success_validate', 'Successfully inserted record.  sec New needed quantity: ' || l_sec_needed_quantity);
9450                   END IF;
9451 
9452                 END IF;
9453               END IF; -- consist records
9454 
9455               --exit pick UOM loop when needed qty = 0
9456             --EXIT WHEN l_needed_quantity = 0;
9457               IF g_over_allocation = 'N'
9458               OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9459               OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
9460 		EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9461               ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9462 		IF l_max_tolerance  >= 0 THEN
9463 			EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9464 			OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9465 		ELSE
9466 			EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9467 		END IF;
9468               END IF;
9469               l_cur_uom_rec  := g_locs(l_cur_uom_rec).next_rec;
9470             --end loop (pick UOM)
9471             END LOOP; --pick UOM
9472 
9473             IF l_debug = 1 THEN
9474                log_statement(l_api_name, 'end_pick_uom', 'End Pick UOM loop');
9475             END IF;
9476 
9477             l_first_uom_rec  := 0;
9478             l_cur_uom_rec    := 0;
9479             l_last_uom_rec   := 0;
9480           END IF;
9481 
9482         --EXIT WHEN l_needed_quantity = 0;
9483           IF g_over_allocation = 'N'
9484           OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9485           OR  WMS_Engine_PVT.g_move_order_type <> 3 THEN
9486               EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9487           ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9488               IF l_max_tolerance  >= 0 THEN
9489                  EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9490                  OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9491               ELSE
9492                  EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9493               END IF;
9494           END IF;
9495 
9496           IF NVL(l_cur_order_by_string, '@@@') <> NVL(v_current_row.order_by_string, '@@@') THEN
9497 
9498             IF l_debug = 1 THEN
9499                log_statement(l_api_name, 'order_rank', 'Setting order rank');
9500             END IF;
9501 
9502             l_order_by_rank        := l_order_by_rank + 1;
9503             l_cur_order_by_string  := v_current_row.order_by_string;
9504 
9505             IF g_first_order_by_rank IS NULL THEN
9506               log_statement(l_api_name, 'first_order', 'Setting first order rank');
9507               g_first_order_by_rank  := l_order_by_rank;
9508             END IF;
9509           END IF;
9510 
9511           g_locs_index            := g_locs_index + 1;
9512 
9513           IF l_debug = 1 THEN
9514              log_statement(l_api_name, 'loc_index', 'New loc index: ' || g_locs_index);
9515           END IF;
9516 
9517           g_locs(g_locs_index)    := v_current_row;
9518 
9519           --initialize trace records
9520           IF l_debug_on THEN
9521 
9522             IF l_debug = 1 THEN
9523                log_statement(l_api_name, 'trace_init', 'Init Trace Record');
9524             END IF;
9525 
9526             g_trace_recs(g_locs_index).revision                 := v_current_row.revision;
9527             g_trace_recs(g_locs_index).lot_number               := v_current_row.lot_number;
9528             g_trace_recs(g_locs_index).lot_expiration_date      := v_current_row.lot_expiration_date;
9529             g_trace_recs(g_locs_index).subinventory_code        := v_current_row.subinventory_code;
9530             g_trace_recs(g_locs_index).locator_id               := v_current_row.locator_id;
9531             g_trace_recs(g_locs_index).cost_group_id            := v_current_row.cost_group_id;
9532             g_trace_recs(g_locs_index).lpn_id                   := v_current_row.lpn_id;
9533             g_trace_recs(g_locs_index).uom_code                 := v_current_row.uom_code;
9534             g_trace_recs(g_locs_index).quantity                 := v_current_row.quantity;
9535             g_trace_recs(g_locs_index).secondary_qty            := v_current_row.secondary_quantity;
9536             g_trace_recs(g_locs_index).grade_code               := v_current_row.grade_code;
9537             g_trace_recs(g_locs_index).serial_number            := v_current_row.serial_number;
9538             g_trace_recs(g_locs_index).consist_string_flag      := 'V';
9539             g_trace_recs(g_locs_index).partial_pick_flag        := 'Y';
9540             g_trace_recs(g_locs_index).order_string_flag        := 'Y';
9541             g_trace_recs(g_locs_index).pick_uom_flag            := 'V';
9542             g_trace_recs(g_locs_index).serial_number_used_flag  := 'V';
9543             g_trace_recs(g_locs_index).entire_lpn_flag          := 'V';
9544             --write to log file
9545 
9546             IF l_debug = 1 THEN
9547                log_statement(l_api_name, 'rev', 'revision: ' || v_current_row.revision);
9548                log_statement(l_api_name, 'lot', 'lot: ' || v_current_row.lot_number);
9549                log_statement(l_api_name, 'sub', 'sub:' || v_current_row.subinventory_code);
9550                log_statement(l_api_name, 'loc', 'loc: ' || v_current_row.locator_id);
9551                log_statement(l_api_name, 'cg', 'cg: ' || v_current_row.cost_group_id);
9552                log_statement(l_api_name, 'lpn', 'lpn: ' || v_current_row.lpn_id);
9553                log_statement(l_api_name, 'sn', 'sn: ' || v_current_row.serial_number);
9554                log_statement(l_api_name, 'qty', 'quantity: ' || v_current_row.quantity);
9555                log_statement(l_api_name, 'sqty', 'sec_quantity: ' || v_current_row.secondary_quantity);
9556                log_statement(l_api_name, 'grade', 'grade_code: ' || v_current_row.grade_code);
9557                log_statement(l_api_name, 'uom', 'uom_code: ' || v_current_row.uom_code);
9558                log_statement(l_api_name, 'suom', 'sec_uom_code: ' || v_current_row.secondary_uom_code);
9559                log_statement(l_api_name, 'ord', 'order:' || v_current_row.order_by_string);
9560                log_statement(l_api_name, 'con', 'consist:' || v_current_row.consist_string);
9561             END IF;
9562 
9563           END IF;
9564 
9565           IF l_debug = 1 THEN
9566              log_statement(l_api_name, 'valid_sub', 'Validating sub');
9567           END IF;
9568 
9569           --validate from/to sub/loc
9570           --if fail, goto next output record
9571           --first check to make sure picking from dest sub is not allowed;
9572           --then, based on type code, compare src sub to dest sub;
9573           --next, check to see if sub and item are locator controlled;
9574           --if loc control, go to next record only if src loc = dest loc;
9575           --if not loc control, go to next records (since subs are equal);
9576           --all of the global variables are set in
9577           --wms_engine_pvt.create_suggestions
9578           IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
9579               AND v_current_row.subinventory_code = l_to_subinventory_code
9580              ) THEN
9581              IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
9582                  OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
9583                  OR (wms_engine_pvt.g_sub_loc_control = 5
9584                      AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
9585                    )
9586                ) THEN
9587               IF (v_current_row.locator_id = l_to_locator_id) THEN
9588 
9589                 IF l_debug = 1 THEN
9590                    log_event(
9591                      l_api_name
9592                      ,  'sub_loc_same'
9593                      , 'Cannot use this ' || 'location since source subinventory and locator are' || ' same as destination subinventory and locator'
9594                     );
9595                 END IF;
9596 
9597                 IF l_debug_on THEN
9598                   g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'N';
9599                 END IF;
9600 
9601                 GOTO nextoutputrecord2;
9602               END IF;
9603             ELSE
9604 
9605               IF l_debug = 1 THEN
9606                  log_event(
9607                  l_api_name
9608                  , 'sub_same'
9609                  , 'Cannot use this ' || 'location since source subinventory is ' || 'same as destination subinventory'
9610                  );
9611               END IF;
9612 
9613               IF l_debug_on THEN
9614                 g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'N';
9615               END IF;
9616 
9617               GOTO nextoutputrecord2;
9618             END IF;
9619           END IF;
9620 
9621           IF l_debug_on THEN
9622             g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'Y';
9623           END IF;
9624 
9625           --If consistency restrictions
9626           IF l_consist_exists THEN
9627 
9628             IF l_debug = 1 THEN
9629                log_statement(l_api_name, 'query_tree', 'Querying the quantity tree' || ' to find availability for consist record');
9630             END IF;
9631             -- BUG 3609380 :  Removing l_to_subinevntory_code.
9632             --Validate available quantity
9633             inv_quantity_tree_pvt.query_tree
9634                  (
9635                      p_api_version_number         =>     g_qty_tree_api_version
9636                    , p_init_msg_lst               =>     fnd_api.g_false -- p_init_msg_lst
9637                    , x_return_status              =>     x_return_status
9638                    , x_msg_count                  =>     x_msg_count
9639                    , x_msg_data                   =>     x_msg_data
9640                    , p_tree_id                    =>     p_tree_id
9641                    , p_revision                   =>     v_current_row.revision
9642                    , p_lot_number                 =>     v_current_row.lot_number
9643                    , p_subinventory_code          =>     v_current_row.subinventory_code
9644                    , p_locator_id                 =>     v_current_row.locator_id
9645                    , x_qoh                        =>   l_qoh
9646                    , x_sqoh                       =>   l_sqoh
9647                    , x_rqoh                       =>   l_rqoh
9648                    , x_srqoh                      =>   l_srqoh
9649                    , x_qr                         =>   l_qr
9650                    , x_sqr                        =>   l_sqr
9651                    , x_qs                         =>   l_qs
9652                    , x_sqs                        =>   l_sqs
9653                    , x_att                        =>   l_att
9654                    , x_satt                       =>   l_satt
9655                    , x_atr                        =>   l_atr
9656                    , x_satr                       =>   l_satr
9657                    , p_transfer_subinventory_code =>     chk_for_passing_xfer_sub ( p_transaction_temp_id , l_to_subinventory_code) -- Bug# 4099907
9658                    , p_cost_group_id              =>     v_current_row.cost_group_id
9659                    , p_lpn_id                     =>     v_current_row.lpn_id
9660                  );
9661 
9662             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9663               IF l_debug = 1 THEN
9664                  log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
9665               END IF;
9666               RAISE fnd_api.g_exc_unexpected_error;
9667             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9668               IF l_debug = 1 THEN
9669                  log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
9670               END IF;
9671               RAISE fnd_api.g_exc_error;
9672             END IF;
9673 
9674             IF l_debug = 1 THEN
9675                log_statement(l_api_name, 'att', 'ATT : ' || l_att);
9676             END IF;
9677 
9678             --If att<=0, goto next output rec
9679             IF l_att <= 0 THEN
9680 
9681               IF l_debug = 1 THEN
9682                  log_statement(l_api_name, 'no_att', 'No ATT for this record. ' || 'Getting next record');
9683               END IF;
9684 
9685               IF l_debug_on THEN
9686                 g_trace_recs(g_locs_index).att_qty                 := l_att;
9687                 g_trace_recs(g_locs_index).secondary_att_qty       := l_satt;
9688                 g_trace_recs(g_locs_index).att_qty_flag            := 'N';
9689               END IF;
9690 
9691               GOTO nextoutputrecord2;
9692             END IF;
9693 
9694             IF l_debug_on THEN
9695               g_trace_recs(g_locs_index).att_qty                 := l_att;
9696               g_trace_recs(g_locs_index).secondary_att_qty       := l_satt;
9697               g_trace_recs(g_locs_index).att_qty_flag            := 'Y';
9698             END IF;
9699 
9700             IF l_att < v_current_row.quantity THEN
9701 
9702               IF l_debug = 1 THEN
9703                  log_statement(l_api_name, 'less_att', 'ATT is less than onhand ' || 'quantity. Reducing quantity');
9704               END IF;
9705 
9706               g_locs(g_locs_index).quantity  := l_att;
9707             END IF;
9708 
9709              IF l_debug = 1 THEN
9710                --Insert_consist_record
9711                log_statement(l_api_name, 'insert_consist', 'Calling Insert_Consist_Record');
9712              END IF;
9713 
9714             --init consist flag to N.  It gets set to yes in Alloc. Consist. Group
9715             IF l_debug_on THEN
9716               g_trace_recs(g_locs_index).consist_string_flag  := 'N';
9717             END IF;
9718 
9719             insert_consist_record(
9720               x_return_status              => x_return_status
9721             , x_msg_count                  => x_msg_count
9722             , x_msg_data                   => x_msg_data
9723             , p_record_id                  => g_locs_index
9724             , p_needed_quantity            => l_needed_quantity
9725             , p_use_pick_uom               => l_use_pick_uom
9726             , p_organization_id            => p_organization_id
9727             , p_inventory_item_id          => p_inventory_item_id
9728             , p_to_subinventory_code       => l_to_subinventory_code
9729             , p_to_locator_id              => l_to_locator_id
9730             , p_to_cost_group_id           => l_to_cost_group_id
9731             , p_primary_uom                => p_primary_uom
9732             , p_transaction_uom            => p_transaction_uom
9733             , p_transaction_temp_id        => p_transaction_temp_id
9734             , p_type_code                  => p_type_code
9735             , p_rule_id                    => l_rule_id
9736             , p_reservation_id             => l_reservation_id
9737             , p_tree_id                    => p_tree_id
9738             , p_debug_on                   => l_debug_on
9739             , p_order_by_rank              => l_order_by_rank
9740             , p_needed_sec_quantity        => l_sec_needed_quantity
9741             , p_secondary_uom              => p_secondary_uom
9742             , p_grade_code                 => p_grade_code
9743             , x_finished                   => l_finished
9744             , x_remaining_quantity         => l_remaining_quantity
9745             );
9746 
9747             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9748               IF l_debug = 1 THEN
9749                  log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
9750               END IF;
9751               RAISE fnd_api.g_exc_unexpected_error;
9752             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9753               IF l_debug = 1 THEN
9754                  log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
9755               END IF;
9756               RAISE fnd_api.g_exc_error;
9757             END IF;
9758 
9759             --if finished, needed qty = 0
9760             IF l_finished THEN
9761               IF l_debug = 1 THEN
9762                  log_statement(l_api_name, 'finished', 'Successfully allocated ' || 'consistency group');
9763               END IF;
9764               l_needed_quantity  := 0;
9765               l_sec_needed_quantity  := 0;
9766               EXIT;
9767             END IF;
9768           --else no consist
9769           ELSE
9770             IF l_debug = 1 THEN
9771                log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_insert');
9772             END IF;
9773             --call validate and insert
9774             validate_and_insert(
9775               x_return_status              => x_return_status
9776             , x_msg_count                  => x_msg_count
9777             , x_msg_data                   => x_msg_data
9778             , p_record_id                  => g_locs_index
9779             , p_needed_quantity            => l_needed_quantity
9780             , p_use_pick_uom               => l_use_pick_uom
9781             , p_organization_id            => p_organization_id
9782             , p_inventory_item_id          => p_inventory_item_id
9783             , p_to_subinventory_code       => l_to_subinventory_code
9784             , p_to_locator_id              => l_to_locator_id
9785             , p_to_cost_group_id           => l_to_cost_group_id
9786             , p_primary_uom                => p_primary_uom
9787             , p_transaction_uom            => p_transaction_uom
9788             , p_transaction_temp_id        => p_transaction_temp_id
9789             , p_type_code                  => p_type_code
9790             , p_rule_id                    => l_rule_id
9791             , p_reservation_id             => l_reservation_id
9792             , p_tree_id                    => p_tree_id
9793             , p_debug_on                   => l_debug_on
9794             , p_needed_sec_quantity        => l_sec_needed_quantity
9795             , p_secondary_uom              => p_secondary_uom
9796             , p_grade_code                 => p_grade_code
9797             , x_inserted_record            => l_inserted_record
9798             , x_allocated_quantity         => l_allocated_quantity
9799             , x_remaining_quantity         => l_remaining_quantity
9800             , x_sec_allocated_quantity     => l_sec_allocated_quantity
9801             , x_sec_remaining_quantity     => l_sec_remaining_quantity
9802             );
9803 
9804             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9805               IF l_debug = 1 THEN
9806                  log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9807               END IF;
9808               RAISE fnd_api.g_exc_unexpected_error;
9809             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9810               IF l_debug = 1 THEN
9811                  log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9812               END IF;
9813               RAISE fnd_api.g_exc_error;
9814             END IF;
9815 
9816             --if returns true, decrease needed qty
9817             IF l_inserted_record THEN
9818               l_needed_quantity  := l_needed_quantity - l_allocated_quantity;
9819               l_sec_needed_quantity  := l_sec_needed_quantity - l_sec_allocated_quantity;
9820               IF l_debug = 1 THEN
9821                  log_statement(l_api_name, 'inserted_rec', 'Inserted record.  New needed quantity: ' || l_needed_quantity);
9822 		 log_statement(l_api_name, 'inserted_rec', 'Inserted record.  sec New needed quantity: ' || l_sec_needed_quantity);
9823               END IF;
9824             END IF;
9825           END IF; -- no consist restrictions
9826 
9827 	  -- Just comment here for R12.1 replenishment project, no code change here
9828 	  -- In case of allocation_mode= 5 we do not need to keep track of left out qty at locations because
9829 	  -- we will not be using them in the next round. We strictly pick based on the pick UOM code and we
9830 	  -- do not break. So we do not need to add anything in the following code.
9831 
9832 
9833 	  --If remaining qty >0 and allocation mode in 3,4
9834           IF  l_allocation_mode IN (3, 4)
9835               AND l_remaining_quantity > 0 THEN
9836             IF l_debug = 1 THEN
9837                log_statement(l_api_name, 'remain_qty', 'Remaining quantity: ' || l_remaining_quantity || '.  Creating pick UOM rec');
9838             END IF;
9839             l_cur_rec  := g_locs_index;
9840 
9841             IF l_remaining_quantity < g_locs(g_locs_index).quantity THEN
9842               --create new location record for remaining quantity
9843               g_locs_index                   := g_locs_index + 1;
9844               g_locs(g_locs_index)           := g_locs(l_cur_rec);
9845               g_locs(g_locs_index).quantity  := l_remaining_quantity;
9846               g_locs(l_cur_rec).quantity     := g_locs(l_cur_rec).quantity - l_remaining_quantity;
9847               l_cur_uom_rec                  := g_locs_index;
9848             ELSE
9849               l_cur_uom_rec  := l_cur_rec;
9850             END IF;
9851 
9852             -- new record is first record in table
9853             IF l_first_uom_rec = 0 THEN
9854               l_first_uom_rec                 := l_cur_uom_rec;
9855               l_last_uom_rec                  := l_cur_uom_rec;
9856               g_locs(l_cur_uom_rec).next_rec  := 0;
9857               IF l_debug = 1 THEN
9858                  log_statement(l_api_name, 'first_rec', 'The saved uom record is the first record in table');
9859               END IF;
9860             -- new record is first record with that uom code
9861             ELSIF g_locs(l_first_uom_rec).uom_code <> g_locs(l_cur_uom_rec).uom_code THEN
9862               g_locs(l_cur_uom_rec).next_rec  := l_first_uom_rec;
9863               l_first_uom_rec                 := l_cur_uom_rec;
9864               l_last_uom_rec                  := l_cur_uom_rec;
9865               IF l_debug = 1 THEN
9866                  log_statement(l_api_name, 'first_rec_uom', 'The saved uom record is the first record for uom in table');
9867               END IF;
9868             -- records with this uom code already exist in table
9869             ELSE
9870               g_locs(l_cur_uom_rec).next_rec   := g_locs(l_last_uom_rec).next_rec;
9871               g_locs(l_last_uom_rec).next_rec  := l_cur_uom_rec;
9872               l_last_uom_rec                   := l_cur_uom_rec;
9873               IF l_debug = 1 THEN
9874                  log_statement(l_api_name, 'not_first_rec_uom', 'The saved record is not first record for uom in table');
9875               END IF;
9876             END IF;
9877 
9878             IF l_debug = 1 THEN
9879                log_statement(l_api_name, 'saving_loc', 'Storing record in uom table');
9880             END IF;
9881 
9882             IF l_debug_on THEN
9883               --determine if we created a new record or not
9884               IF l_cur_uom_rec = g_locs_index THEN
9885                 g_trace_recs(g_locs_index)                := g_trace_recs(l_cur_rec);
9886                 g_trace_recs(l_cur_rec).quantity          := g_trace_recs(l_cur_rec).quantity - l_remaining_quantity;
9887                 g_trace_recs(g_locs_index).quantity       := l_remaining_quantity;
9888                 g_trace_recs(g_locs_index).suggested_qty  := 0;
9889                 g_trace_recs(l_cur_rec).pick_uom_flag     := 'P';
9890                 g_trace_recs(g_locs_index).pick_uom_flag  := 'N';
9891               ELSE
9892                 g_trace_recs(l_cur_rec).pick_uom_flag  := 'N';
9893               END IF;
9894             END IF;
9895           ELSE
9896             IF l_debug_on THEN
9897               g_trace_recs(g_locs_index).pick_uom_flag  := 'Y';
9898             END IF;
9899           END IF; --allocation mode in 3,4
9900 
9901           --if needed qty = 0 , exit outermost loop
9902           --IF l_needed_quantity <= 0 THEN
9903           IF l_needed_quantity >= 0 and l_needed_quantity <= l_max_tolerance THEN
9904             IF l_debug = 1 THEN
9905                log_statement(l_api_name, 'finished_alloc', 'The requested quantity has been allocated.  Exiting loop.');
9906             END IF;
9907             EXIT;
9908           END IF;
9909 
9910           <<nextoutputrecord2>>
9911           NULL;
9912         --end outermost loop
9913         END LOOP;
9914       --PUT AWAY
9915       ELSIF (p_type_code = 1) THEN --put away
9916         l_capacity_updated  := FALSE;
9917         l_locs_index        := 0;
9918 
9919         --Loop through each record from the Rule cursor
9920         WHILE TRUE LOOP
9921           IF l_debug = 1 THEN
9922              log_event(l_api_name, 'Loop through each record  putaway from the Rule cursor ', 'Start ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
9923           END IF;
9924           --l_locs_index        := l_locs_index + 1; --bug3673962 moving this assignment as when no rows are returned by fetchputaway
9925                                                      --the index gets incremented unncessarily and fails in WMSSOGBB.pls
9926           fetchputaway(
9927             x_return_status
9928           , x_msg_count
9929           , x_msg_data
9930           , v_put_cursor
9931           , l_rule_id
9932           , l_osubinventory_code
9933           , l_olocator_id
9934           , l_oproject_id
9935           , l_otask_id
9936           , l_rows
9937           );
9938 
9939           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9940             IF l_debug = 1 THEN
9941                log_statement(l_api_name, 'uerr_fetch_cursor',
9942                           'Unexpected error in FetchCursor');
9943             END IF;
9944             RAISE fnd_api.g_exc_unexpected_error;
9945           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9946             IF l_debug = 1 THEN
9947                log_statement(l_api_name,'err_fetch_cursor','Error in FetchCursor');
9948             END IF;
9949             RAISE fnd_api.g_exc_error;
9950           END IF;
9951 
9952           -- Exit if no more records from rule cursor
9953           EXIT WHEN  nvl(l_rows, 0)  = 0 ;  -- [ Added to to exit , if the rule is not returning any rows
9954 
9955           l_locs_index        := l_locs_index + 1; --bug3673962
9956           log_statement(l_api_name, 'org_loc_ctl ', 'org: ' ||wms_engine_pvt.g_org_loc_control);
9957           log_statement(l_api_name, 'sub_loc_ctl ', 'org: ' ||wms_engine_pvt.g_sub_loc_control);
9958           log_statement(l_api_name, 'itm_loc_ctl ', 'org: ' ||wms_engine_pvt.g_item_loc_control);
9959           /* bug 3972784, remove locator_id if no locator control */
9960           IF (  wms_engine_pvt.g_org_loc_control in (1,4)                   -- no loc ctl org level
9961                AND ( wms_engine_pvt.g_sub_loc_control = 1                  -- no loc ctl sub level
9962                   OR (wms_engine_pvt.g_sub_loc_control = 5
9963                          AND wms_engine_pvt.g_item_loc_control = 1           -- no loc ctl item level
9964                      )
9965                    )
9966              )
9967           THEN
9968               l_olocator_id := null;
9969               log_statement(l_api_name, 'non locator controled',' Non locator controled');
9970           END IF;
9971 
9972           IF l_debug = 1 THEN
9973             log_statement(l_api_name, 'put_sub', 'Subinventory: ' || l_osubinventory_code);
9974              log_statement(l_api_name, 'put_loc', 'Locator: ' || l_olocator_id);
9975              log_statement(l_api_name, 'put_proj', 'Project: ' || l_oproject_id);
9976              log_statement(l_api_name, 'put_task', 'Task: ' || l_otask_id);
9977           END IF;
9978 
9979           IF l_debug_on THEN
9980             g_trace_recs(l_locs_index).revision             := l_revision;
9981             g_trace_recs(l_locs_index).lot_number           := l_lot_number;
9982             g_trace_recs(l_locs_index).lot_expiration_date  := l_lot_expiration_date;
9983             g_trace_recs(l_locs_index).subinventory_code    := l_osubinventory_code;
9984             g_trace_recs(l_locs_index).locator_id           := l_olocator_id;
9985             g_trace_recs(l_locs_index).cost_group_id        := l_to_cost_group_id;
9986             g_trace_recs(l_locs_index).uom_code             := NULL;
9987             g_trace_recs(l_locs_index).lpn_id               := l_input_lpn_id;
9988             g_trace_recs(l_locs_index).quantity             := NULL;
9989             g_trace_recs(l_locs_index).serial_number        := l_serial_number;
9990             --init to 0, in case of error
9991             g_trace_recs(l_locs_index).suggested_qty        := 0;
9992           END IF;
9993 
9994 
9995           --bug 2589499
9996           --if reservation exists for WIP assembly completion, put away
9997           --   to reservable sub only;
9998           --we know if sub has to be reservable based on global value set in
9999           --  create_suggestions
10000           IF wms_engine_pvt.g_reservable_putaway_sub_only THEN
10001              OPEN c_subinventory;
10002              FETCH c_subinventory INTO l_lpn_controlled_flag,
10003                                      l_sub_rsv_type;
10004              If c_subinventory%NOTFOUND or l_sub_rsv_type IS NULL Then
10005                l_sub_rsv_type := 1;
10006                l_lpn_controlled_flag := 1;
10007              End If;
10008              CLOSE c_subinventory;
10009 
10010              If l_sub_rsv_type <> 1 Then
10011                IF l_debug = 1 THEN
10012                   log_statement(l_api_name, 'non_rsv_dest_sub',
10013                     'This material cannot be putaway in a non-reservable sub. ' ||
10014                     'Getting next record');
10015                END IF;
10016                --set trace flag
10017                GOTO NextOutputRecord;
10018              End If;
10019           END IF;
10020 
10021 
10022 
10023           --3/13/02 - To support PJM, check project and task if supplied.
10024           -- Case 1) Project and Task not supplied do nothing
10025           --      2) Project and Task Supplied and current record has same
10026           --     project and task continue processing.
10027           --      3) Project and Task supplied, not in current record
10028           --     then create a new entry in MTL_ITEM_LOCATIONS with
10029           --     properties of current record but with require project and task
10030           --  <This assumes that the results are ordered by Project and Task>
10031           IF p_project_id IS NOT NULL THEN
10032             IF NVL(l_oproject_id, -9999) <> p_project_id
10033                OR NVL(l_otask_id, -9999) <> nvl(p_task_id,-9999) THEN
10034               --bug 2400549 - for WIP backflush transfer putaway,
10035               --always use the locator specified on the move order line, even
10036               --if that locator is from common stock (not project)
10037               -- Bug 2666620: BackFlush MO Type Removed. It is now 5.
10038               -- Moreover Txn Action ID is 2  which is already handled.
10039              IF NOT (wms_engine_pvt.g_move_order_type = 5 AND
10040                  wms_engine_pvt.g_transaction_action_id = 2) THEN
10041                  IF l_debug = 1 THEN
10042                    log_statement(l_api_name, 'do_project2', 'Calling do project check');
10043                  END IF;
10044                 IF doprojectcheck(l_return_status,
10045                                   l_olocator_id,
10046                                   p_project_id,
10047                                   p_task_id,
10048                                   l_olocator_id_new,l_dummy_loc) THEN
10049                    IF l_debug = 1 THEN
10050                      log_statement(l_api_name, 'do_project_success', 'Do project check returned new locator');
10051                    END IF;
10052                    l_olocator_id_prev  := l_olocator_id;
10053                    l_olocator_id       := l_olocator_id_new;
10054                 ELSE
10055                   -- Current locator does not have required project/task
10056                               -- but it exists
10057                   IF l_debug = 1 THEN
10058                      log_statement(l_api_name, 'do_project_fail', 'Do project check failed. Getting next record.');
10059                   END IF;
10060                   GOTO nextoutputrecord;
10061                 END IF; --do project check
10062               END IF; -- not wip backflush
10063             END IF; -- allocated project <> needed project
10064           END IF; -- needed project <> -9999
10065 
10066                 --2/21/02 - Now check available capacity in here in the Pl/Sql
10067           --instead of calling the APIs from the rule sql.  This is to
10068           --improve performance.  If there are 10000 eligible locators, you
10069           --don't want to check capacity for all of them.  You only want to
10070           --check capacity on the one or two that you'll end up allocating
10071           IF l_debug = 1 THEN
10072              log_statement(l_api_name, 'qty_function', 'qty function code: ' || l_quantity_function);
10073           END IF;
10074        IF l_consider_staging_capacity THEN --Added bug3237702
10075           IF l_quantity_function = 530003 THEN
10076             l_possible_quantity  := wms_parameter_pvt.getavailableunitcapacity(
10077                                       p_organization_id            => p_organization_id
10078                                     , p_subinventory_code          => l_osubinventory_code
10079                                     , p_locator_id                 => l_olocator_id
10080                                     );
10081           ELSIF l_quantity_function = 530007 THEN
10082             l_possible_quantity  := wms_parameter_pvt.getavailablevolumecapacity(
10083                                       p_organization_id            => p_organization_id
10084                                     , p_subinventory_code          => l_osubinventory_code
10085                                     , p_locator_id                 => l_olocator_id
10086                                     , p_inventory_item_id          => p_inventory_item_id
10087                                     , p_unit_volume                => p_unit_volume
10088                                     , p_unit_volume_uom_code       => p_volume_uom_code
10089                                     , p_primary_uom                => p_primary_uom
10090                                     , p_transaction_uom            => p_transaction_uom
10091                                     , p_base_uom                   => p_base_uom_code
10092                                     );
10093           ELSIF l_quantity_function = 530011 THEN
10094             l_possible_quantity  := wms_parameter_pvt.getavailableweightcapacity(
10095                                       p_organization_id            => p_organization_id
10096                                     , p_subinventory_code          => l_osubinventory_code
10097                                     , p_locator_id                 => l_olocator_id
10098                                     , p_inventory_item_id          => p_inventory_item_id
10099                                     , p_unit_weight                => p_unit_weight
10100                                     , p_unit_weight_uom_code       => p_weight_uom_code
10101                                     , p_primary_uom                => p_primary_uom
10102                                     , p_transaction_uom            => p_transaction_uom
10103                                     , p_base_uom                   => p_base_uom_code
10104                                     );
10105           ELSIF l_quantity_function = 530015 THEN
10106             l_possible_quantity  := wms_parameter_pvt.getminimumavailablevwcapacity(
10107                                       p_organization_id            => p_organization_id
10108                                     , p_subinventory_code          => l_osubinventory_code
10109                                     , p_locator_id                 => l_olocator_id
10110                                     , p_inventory_item_id          => p_inventory_item_id
10111                                     , p_unit_volume                => p_unit_volume
10112                                     , p_unit_volume_uom_code       => p_volume_uom_code
10113                                     , p_unit_weight                => p_unit_weight
10114                                     , p_unit_weight_uom_code       => p_weight_uom_code
10115                                     , p_primary_uom                => p_primary_uom
10116                                     , p_transaction_uom            => p_transaction_uom
10117                                     , p_base_uom                   => p_base_uom_code
10118                                     );
10119           ELSIF l_quantity_function = 530019 THEN
10120             l_possible_quantity  := wms_parameter_pvt.getminimumavailableuvwcapacity(
10121                                       p_organization_id            => p_organization_id
10122                                     , p_subinventory_code          => l_osubinventory_code
10123                                     , p_locator_id                 => l_olocator_id
10124                                     , p_inventory_item_id          => p_inventory_item_id
10125                                     , p_unit_volume                => p_unit_volume
10126                                     , p_unit_volume_uom_code       => p_volume_uom_code
10127                                     , p_unit_weight                => p_unit_weight
10128                                     , p_unit_weight_uom_code       => p_weight_uom_code
10129                                     , p_primary_uom                => p_primary_uom
10130                                     , p_transaction_uom            => p_transaction_uom
10131                                     , p_base_uom                   => p_base_uom_code
10132                                     );
10133           ELSIF l_quantity_function = 530023 THEN
10134             l_possible_quantity  := wms_re_custom_pub.getavailablelocationcapacity(
10135                                       p_organization_id            => p_organization_id
10136                                     , p_subinventory_code          => l_osubinventory_code
10137                                     , p_locator_id                 => l_olocator_id
10138                                     , p_inventory_item_id          => p_inventory_item_id
10139                                     , p_transaction_quantity       => l_needed_quantity
10140                                     , p_transaction_uom            => p_transaction_uom
10141                                     );
10142           ELSE
10143             l_possible_quantity  := 0;
10144             IF l_debug = 1 THEN
10145                log_statement(l_api_name, 'bad_qtyf', 'Invalid Quantity Function');
10146             END IF;
10147           --raise error message!!!
10148           END IF;
10149        ELSE
10150           -- capacity should not be considered
10151           l_possible_quantity := 1e125;
10152           l_sec_possible_quantity := 1e125;
10153        END IF;
10154 
10155        IF l_debug = 1 THEN
10156              log_statement(l_api_name, 'capacity', 'avail. capacity: ' || l_possible_quantity);
10157        END IF;
10158 
10159        --bug 2778814
10160        --For serial controlled items, we should not suggest the putaway
10161        --  of decimal quantities
10162        IF wms_engine_pvt.g_serial_number_control_code > 1 THEN
10163          l_possible_quantity := floor(l_possible_quantity);
10164          IF l_debug = 1 THEN
10165             log_statement(l_api_name, 'no_decimals',
10166                 'Cannot putaway a decimal quantity on a serial controlled item.'||
10167                 ' New available capacity: ' || l_possible_quantity);
10168          END IF;
10169        END IF;
10170 
10171           IF l_debug_on THEN
10172             g_trace_recs(l_locs_index).quantity  := l_possible_quantity;
10173           --g_trace_recs(l_locs_index).secondary_quantity  := l_sec_possible_quantity;
10174           END IF;
10175 
10176          -- [LOT_INDIV
10177 	 --  For lot indiv item, check if entire line qty can be dropped
10178 	 --  If not skip the current locator and go to next available locator
10179 	 --
10180 	 --  Default behavior is to split the qty and drop the partially
10181          --  and  go to the next locator for the remaining qty.
10182 
10183            IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1 and p_type_code = 1 THEN
10184               IF l_possible_quantity < l_needed_quantity THEN
10185                  IF l_debug = 1 THEN
10186                     log_event(l_api_name, 'Required Capacity  = ', l_needed_quantity);
10187                     log_event(l_api_name, 'Available capacity =',  l_possible_quantity);
10188                     log_event(l_api_name, 'Capacity check for Lot indiv item', 'Capacity is not enough !');
10189                  END IF;
10190               GOTO nextoutputrecord;
10191               END IF;
10192            END IF;
10193           -- If no quantity for this record, get next record
10194           IF l_possible_quantity <= 0 OR l_possible_quantity IS NULL THEN
10195             IF l_debug = 1 THEN
10196                log_event(l_api_name, 'no_rec_qty_put', 'No available capacity in putaway location');
10197             END IF;
10198             --
10199             -- Patchset 'J' error_message
10200             WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_LOC_CAPACITY_FULL' ;
10201             --
10202             --
10203             GOTO nextoutputrecord;
10204           END IF;
10205 
10206           --check to see if from sub/loc = to sub/loc
10207           --this is okay if pick wave move order.
10208           --if not pick wave move order and src = dest,
10209           -- skip results
10210 
10211           --first check to make sure picking from dest sub is not allowed;
10212           --then, based on type code, compare src sub to dest sub;
10213           --next, check to see if sub and item are locator controlled;
10214           --if loc control, go to next record only if src loc = dest loc
10215           --if not loc control, go to next records (since subs are equal)
10216                 --all of the global variables are set in
10217           --wms_engine_pvt.create_suggestions
10218           IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
10219               AND l_osubinventory_code = l_from_subinventory_code
10220              ) THEN
10221             IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
10222                 OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
10223                 OR (wms_engine_pvt.g_sub_loc_control = 5
10224                     AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
10225                    )
10226                ) THEN
10227               IF (l_olocator_id = l_from_locator_id) THEN
10228 
10229                 IF l_debug = 1 THEN
10230                    log_event(
10231                      l_api_name
10232                    , 'same_sub_loc_put'
10233                    ,    'Destination '
10234                   || 'subinventory and locator for this record are the '
10235                   || 'same as the source subinventory and locator. '
10236                   || 'Using next record'
10237                   );
10238                 END IF;
10239 
10240                 IF l_debug_on THEN
10241                   g_trace_recs(l_locs_index).same_subinv_loc_flag  := 'N';
10242                 END IF;
10243 
10244                 --
10245                 -- Patchset 'J' error_message
10246                 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_SAME_SUB_LOC' ;
10247                 --
10248                 --
10249                 GOTO nextoutputrecord;
10250               END IF; -- from loc = to loc
10251             ELSE -- not loc controlled
10252               IF l_debug = 1 THEN
10253                  log_event(
10254                     l_api_name
10255                     , 'same_sub_put'
10256                     , 'Destination ' || 'subinventory for this record is the ' || 'same as the source subinventory. ' || 'Using next record'
10257                    );
10258                END IF;
10259 
10260               IF l_debug_on THEN
10261                 g_trace_recs(l_locs_index).same_subinv_loc_flag  := 'N';
10262               END IF;
10263 
10264               GOTO nextoutputrecord;
10265             END IF;
10266           END IF;
10267 
10268           IF l_debug_on THEN
10269             g_trace_recs(l_locs_index).same_subinv_loc_flag  := 'Y';
10270           END IF;
10271 
10272           --check status to see if putting away to this location is allowed
10273           -- for this transaction type
10274           -- This API checks the status for the subinventory, locator,
10275           -- and lot
10276           IF l_debug = 1 THEN
10277              log_statement(l_api_name, 'checking_status', 'calling is_sub_loc_lot_trx_allowed to check status');
10278           END IF;
10279 
10280           --Bug Number :3457530(cheking for a transaction_type_id)
10281 
10282           IF ( p_transaction_type_id <> 64) THEN
10283           l_allowed           := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
10284                                    p_transaction_type_id        => p_transaction_type_id
10285                                  , p_organization_id            => p_organization_id
10286                                  , p_inventory_item_id          => p_inventory_item_id
10287                                  , p_subinventory_code          => l_osubinventory_code
10288                                  , p_locator_id                 => l_olocator_id
10289                                  , p_lot_number                 => l_lot_number
10290                                  );
10291           END IF;
10292 
10293           IF l_allowed <> 'Y' THEN
10294 
10295             IF l_debug = 1 THEN
10296                log_event(
10297                   l_api_name
10298                   , 'bad_status'
10299                   , 'This transaction type is not allowed by the status ' || 'for the subinventory, locator, or lot. Using ' || 'next record.'
10300                    );
10301              END IF;
10302 
10303             IF l_debug_on THEN
10304               g_trace_recs(l_locs_index).material_status_flag  := 'N';
10305             END IF;
10306 	    --
10307 	    -- Patchset 'J' error_message
10308 	    WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_MAT_STATUS_NOT_ALLOWED' ;
10309 	    --
10310 	    --
10311             GOTO nextoutputrecord;
10312           END IF;
10313 
10314           IF l_debug_on THEN
10315             g_trace_recs(l_locs_index).material_status_flag  := 'Y';
10316           END IF;
10317 
10318           /* Bug 4544717 -Converted l_possible_quantity to primary uom before comparing with
10319                          l_needed_quantity which is in primary uom if the transaction uom and
10320                          primary uom were different */
10321 
10322           IF l_debug = 1 THEN
10323                log_statement(l_api_name, 'poss_put_qty', 'Value of p_transaction_uom:'|| p_transaction_uom);
10324                log_statement(l_api_name, 'poss_put_qty', 'Value of p_primary_uom'|| p_primary_uom);
10325           END IF;
10326 
10327           IF p_transaction_uom <> p_primary_uom THEN
10328              IF l_debug = 1 THEN
10329                log_statement(l_api_name, 'poss_put_qty', 'In the condition for transaction_uom and primary uom different');
10330              END IF;
10331              l_possible_quantity := inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_possible_quantity, p_transaction_uom, p_primary_uom , NULL, NULL);
10332           END IF;
10333 
10334           IF l_debug = 1 THEN
10335              log_statement(l_api_name, 'poss_put_qty', 'Value of l_possible_quantity' || l_possible_quantity);
10336              log_statement(l_api_name, 'poss_put_qty', 'Value of l_needed_quantity' || l_needed_quantity);
10337           END IF;
10338 
10339           /* End of fix for Bug 4544717 */
10340 
10341 
10342           -- correct possible quantity to what is really requested
10343           IF l_possible_quantity > l_needed_quantity THEN
10344             l_possible_quantity  := l_needed_quantity;
10345             l_sec_possible_quantity  := l_sec_needed_quantity;
10346             IF l_debug = 1 THEN
10347                log_statement(l_api_name, 'poss_put_qty', 'Possible quantity > needed quantity. New poss qty:' || l_possible_quantity);
10348             END IF;
10349           END IF;
10350 
10351           --
10352 
10353                 --Determine if putaway sub is LPN controlled.  If it is not,
10354           --then we need to check cost group commingling always;
10355                 -- Check cost group if
10356           -- Cost group is not null AND
10357                 -- (sub is not lpn controlled OR
10358                 --  No lpn on move order line OR
10359             --  not a staging transfer)
10360                 --Never suggest comingling of cost groups, unless we are
10361           -- putting away a LPN.
10362           --When putting away an LPN, we assume that user is putting away
10363           -- whole LPN, which means there will never be comingling.
10364           --bug 1570597 - staging transfers are always put away in an LPN,
10365           -- so we don't need to check for comingling.
10366           --bug 2161565 - need to check for cg commingling if
10367           -- to subinventory is not LPN controlled.
10368           --bug 2492526 - putting away to a project controlled locator
10369           -- will always change the CG.  So no need to worry about CG
10370           -- commingling if the dest. loc is project controlled.
10371           IF l_to_cost_group_id IS NULL THEN
10372             l_check_cg  := FALSE;
10373           ELSIF l_oproject_id IS NOT NULL THEN
10374             l_check_cg  := FALSE;
10375           ELSIF (p_lpn_id IS NOT NULL
10376                  OR p_transaction_type_id IN (52, 53)
10377                 ) THEN
10378 
10379             --only execute query if we did not already find lpn_controlled_flag
10380             -- when determining if sub is reservable
10381             If l_lpn_controlled_flag IS NULL Then
10382               OPEN c_subinventory;
10383               FETCH c_subinventory INTO l_lpn_controlled_flag,
10384                                        l_sub_rsv_type;
10385               -- by default, assume sub is lpn controlled
10386               If c_subinventory%notfound OR
10387                 l_lpn_controlled_flag IS NULL OR
10388                 l_lpn_controlled_flag NOT IN (1,2) Then
10389                   l_lpn_controlled_flag := 1;
10390               End If;
10391               CLOSE c_subinventory;
10392             End If;
10393 
10394             IF l_lpn_controlled_flag = 1 THEN
10395               l_check_cg  := FALSE;
10396             ELSE
10397               l_check_cg  := TRUE;
10398             END IF;
10399           ELSE
10400             l_check_cg  := TRUE;
10401           END IF;
10402 
10403           --Check to see if putaway would comingle cost groups.
10404           IF l_check_cg THEN
10405             inv_comingling_utils.comingle_check(
10406               x_return_status              => x_return_status
10407             , x_msg_count                  => x_msg_count
10408             , x_msg_data                   => x_msg_data
10409             , x_comingling_occurs          => l_comingle
10410             , x_count                      => l_dummy
10411             , p_organization_id            => p_organization_id
10412             , p_inventory_item_id          => p_inventory_item_id
10413             , p_revision                   => l_revision
10414             , p_lot_number                 => l_lot_number
10415             , p_subinventory_code          => l_osubinventory_code
10416             , p_locator_id                 => l_olocator_id
10417             , p_lpn_id                     => NULL
10418             , p_cost_group_id              => l_to_cost_group_id
10419             );
10420 
10421             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10422               IF l_debug = 1 THEN
10423                  log_statement(l_api_name, 'uerr_comingle_check', 'Unexpected error in comingle_check');
10424               END IF;
10425               RAISE fnd_api.g_exc_unexpected_error;
10426             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10427               IF l_debug = 1 THEN
10428                  log_statement(l_api_name, 'err_comingle_check', 'Error in comingle_check');
10429               END IF;
10430               RAISE fnd_api.g_exc_error;
10431             END IF;
10432 
10433             -- Skip record if it would cause comingling
10434             IF l_comingle = 'Y' THEN
10435               IF l_debug = 1 THEN
10436                  log_event(l_api_name, 'comingle_putaway', 'Putaway to this location would comingle cost groups. ' || 'Using next record');
10437               END IF;
10438               IF l_debug_on THEN
10439                 g_trace_recs(l_locs_index).cg_comingle_flag  := 'N';
10440               END IF;
10441                --
10442 	       -- Patchset 'J' error_message
10443 	       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_COST_GROUP_COMINGLE' ;
10444               GOTO nextoutputrecord;
10445             END IF;
10446 
10447             IF l_debug_on THEN
10448               g_trace_recs(l_locs_index).cg_comingle_flag  := 'Y';
10449             END IF;
10450           END IF;
10451 
10452           -- Update locator capacity to reflect quantity we are putting
10453           -- away.  This API executes an autonomous commit.  Thus,
10454           -- if any sort of error occurs, we have to explicitly undo
10455           -- this update (we can't just do a rollback).
10456           IF (l_olocator_id IS NOT NULL) AND l_consider_staging_capacity THEN  --Added bug3237702
10457           --IF l_olocator_id IS NOT NULL THEN Commented bug3237702
10458             IF l_debug = 1 THEN
10459                log_statement(l_api_name, 'update_capacity', 'Updating suggested capacity');
10460              END IF;
10461             inv_loc_wms_utils.update_loc_suggested_capacity(
10462               x_return_status              => x_return_status
10463             , x_msg_count                  => x_msg_count
10464             , x_msg_data                   => x_msg_data
10465             , p_organization_id            => p_organization_id
10466             , p_inventory_location_id      => l_olocator_id
10467             , p_inventory_item_id          => p_inventory_item_id
10468             , p_primary_uom_flag           => 'Y'
10469             , p_transaction_uom_code       => NULL
10470             , p_quantity                   => l_possible_quantity
10471             );
10472 
10473             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10474               IF l_debug = 1 THEN
10475                  log_statement(l_api_name, 'uerr_update_capacity', 'Unexpected error in update_loc_suggested_capacity');
10476               END IF;
10477               RAISE fnd_api.g_exc_unexpected_error;
10478             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10479               IF l_debug = 1 THEN
10480                  log_statement(l_api_name, 'err_update_capacity', 'Error in update_loc_suggested_capacity');
10481               END IF;
10482               RAISE fnd_api.g_exc_error;
10483             ELSE
10484               l_capacity_updated  := TRUE;
10485             END IF;
10486           END IF;
10487 
10488           IF l_debug_on THEN
10489             g_trace_recs(l_locs_index).suggested_qty  := l_possible_quantity;
10490             g_trace_recs(l_locs_index).secondary_suggested_qty  := l_sec_possible_quantity;
10491           END IF;
10492 
10493           -- no detail for serial numbers
10494           -- get the transaction quantity
10495           IF p_transaction_uom = p_primary_uom THEN
10496             l_possible_trx_qty  := l_possible_quantity;
10497           ELSE
10498             l_possible_trx_qty  :=
10499                    inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_possible_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
10500           END IF;
10501 
10502           IF l_debug = 1 THEN
10503             log_statement(l_api_name, 'insert_put_wtt_recs', 'Before insert values of l_possible_trx_qty'|| l_possible_trx_qty);
10504             log_statement(l_api_name, 'insert_put_wtt_recs', 'Before insert values of l_possible_quantity'|| l_possible_quantity);
10505           END IF;
10506 
10507           IF l_debug = 1 THEN
10508              log_statement(l_api_name, 'insert_put_wtt_recs', 'Inserting putaway records in wtt');
10509           END IF;
10510           -- insert temporary suggestion
10511           INSERT INTO wms_transactions_temp
10512                       (
10513                       pp_transaction_temp_id
10514                     , transaction_temp_id
10515                     , type_code
10516                     , line_type_code
10517                     , transaction_quantity
10518                     , primary_quantity
10519                     , secondary_quantity
10520                     , grade_code
10521                     , revision
10522                     , lot_number
10523                     , lot_expiration_date
10524                     , from_subinventory_code
10525                     , from_locator_id
10526                     , rule_id
10527                     , reservation_id
10528                     , to_subinventory_code
10529                     , to_locator_id
10530                     , from_cost_group_id
10531                     , to_cost_group_id
10532                     , lpn_id
10533                       )
10534                VALUES (
10535                       wms_transactions_temp_s.NEXTVAL
10536                     , p_transaction_temp_id
10537                     , p_type_code
10538                     , 2 -- line type code is output
10539                     , l_possible_trx_qty
10540                     , l_possible_quantity
10541                     , l_sec_possible_quantity
10542                     , l_grade_code
10543                     , l_revision
10544                     , l_lot_number
10545                     , l_lot_expiration_date
10546                     , l_from_subinventory_code
10547                     , l_from_locator_id
10548                     , l_rule_id
10549                     , l_reservation_id
10550                     , l_osubinventory_code
10551                     , l_olocator_id
10552                     , l_from_cost_group_id
10553                     , l_to_cost_group_id
10554                     , l_input_lpn_id
10555                       );
10556 
10557           --
10558           l_capacity_updated  := FALSE;
10559           --END IF;
10560 
10561           IF l_debug = 1 THEN
10562              log_event(l_api_name, 'putaway_loc_found', 'Found put away location for quantity ' || l_possible_quantity);
10563           END IF;
10564 
10565           -- keep track of the remaining transaction quantity
10566           IF l_needed_quantity > l_possible_quantity THEN
10567             l_needed_quantity  := l_needed_quantity - l_possible_quantity;
10568             l_sec_needed_quantity  := l_sec_needed_quantity - l_sec_possible_quantity;
10569           ELSE
10570             l_needed_quantity  := 0;
10571             l_sec_needed_quantity  := 0;
10572             IF l_debug = 1 THEN
10573                log_event(l_api_name, 'finished_putaway', 'Found put away locations for all quantity in this input record');
10574             END IF;
10575           END IF;
10576 
10577           --
10578           <<nextoutputrecord>>
10579           EXIT WHEN l_needed_quantity = 0;
10580         END LOOP; -- output records
10581       END IF; -- type_code = 1
10582 
10583       -- finally close the rule cursor
10584       IF l_debug = 1 THEN
10585          log_statement(l_api_name, 'close_curs', 'Calling close_curs');
10586       END IF;
10587 
10588       -- Bug# 4738161: Close the putaway cursors after each line is allocated if necessary
10589       IF p_type_code = 1 THEN
10590          close_put_rule(l_rule_id, v_put_cursor);
10591       ELSE
10592          close_pick_rule(l_rule_id, v_pick_cursor);
10593       END IF;
10594 
10595       IF l_debug = 1 THEN
10596          log_statement(l_api_name, 'finish_close_curs', 'Finished close_curs');
10597       END IF;
10598 
10599       IF ((g_over_allocation = 'N'
10600          OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
10601          OR WMS_Engine_PVT.g_move_order_type <> 3 or p_type_code <> 2)
10602         AND (l_needed_quantity > 0 OR l_needed_quantity > l_max_tolerance)
10603        )
10604     OR
10605        (g_over_allocation = 'Y' AND NOT (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
10606         AND WMS_Engine_PVT.g_move_order_type = 3 and  p_type_code = 2
10607         AND ((l_max_tolerance >= 0 AND (l_needed_quantity > l_max_tolerance)
10608               AND (l_initial_pri_quantity - l_needed_quantity < WMS_RULE_PVT.g_min_qty_to_allocate))
10609              OR (l_max_tolerance < 0
10610                  AND l_initial_pri_quantity - l_needed_quantity < WMS_RULE_PVT.g_min_qty_to_allocate)
10611             )
10612        )
10613     THEN
10614         -- notice, that at least one input record couldn't get satisfied
10615         x_finished  := fnd_api.g_false;
10616 
10617         IF l_needed_quantity = l_initial_pri_quantity THEN
10618            -- Bug #3396532
10619            IF WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE IS NULL THEN
10620              WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
10621            END IF;
10622            IF l_debug = 1 THEN
10623               log_event(l_api_name, 'no_success', 'Found no locations for this rule');
10624            END IF;
10625         ELSE
10626           IF l_debug = 1 THEN
10627              log_event(l_api_name, 'partial_success', 'Successfully allocated some of the transaction ' || 'quantity with this rule.');
10628           END IF;
10629         END IF;
10630 
10631         -- if partials are not allowed, exit after rolling back everything
10632         IF p_partial_success_allowed_flag = 'N' THEN
10633           -- restore qty tree
10634           IF l_debug = 1 THEN
10635              log_event(l_api_name, 'no_partials_allowed', 'Partial success is not allowed for this rule - rolling back');
10636           END IF;
10637           IF p_type_code = 2 THEN
10638             IF l_debug = 1 THEN
10639                log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
10640             END IF;
10641             inv_quantity_tree_pvt.restore_tree(x_return_status, p_tree_id);
10642 
10643 	    /*Start of fix for Bug 5251221 */
10644 
10645 	    OPEN l_get_serial;
10646 	    LOOP
10647 	    FETCH l_get_serial INTO l_serial_number;
10648                 IF l_get_serial%NOTFOUND THEN
10649                    IF l_debug = 1 THEN
10650                       inv_log_util.trace('Serial not found', 'delete_serial_numbers', 9);
10651                    END IF;
10652   	           exit;
10653                 ELSE
10654         	   IF (inv_detail_util_pvt.g_serial_tbl_ptr > 0) THEN
10655 		       IF l_debug = 1 THEN
10656                           inv_log_util.trace('Org: ' || p_organization_id, 'delete_serial_numbers', 9);
10657 	                  inv_log_util.trace('Item: ' || p_inventory_item_id, 'delete_serial_numbers', 9);
10658 	                  inv_log_util.trace('Serial: ' || l_serial_number, 'delete_serial_numbers', 9);
10659 			  inv_log_util.trace('inv_detail_util_pvt.g_serial_tbl_ptr ' || inv_detail_util_pvt.g_serial_tbl_ptr, 'delete_serial_numbers', 9);
10660                        END IF;
10661 
10662 		       FOR i IN 1..inv_detail_util_pvt.g_serial_tbl_ptr LOOP
10663 		           IF (inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id = p_inventory_item_id) AND
10664                               (inv_detail_util_pvt.g_output_serial_rows(i).organization_id   = p_organization_id)   AND
10665                               (inv_detail_util_pvt.g_output_serial_rows(i).serial_number     = l_serial_number) THEN
10666 
10667 		      	      IF (inv_detail_util_pvt.g_serial_tbl_ptr > 1) THEN
10668                                   inv_detail_util_pvt.g_output_serial_rows(i).organization_id := inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).organization_id;
10669 		                  inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id := inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).inventory_item_id;
10670 			          inv_detail_util_pvt.g_output_serial_rows(i).serial_number := inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).serial_number;
10671 
10672 			          inv_detail_util_pvt.g_output_serial_rows.DELETE(inv_detail_util_pvt.g_serial_tbl_ptr);
10673 			          inv_detail_util_pvt.g_serial_tbl_ptr := inv_detail_util_pvt.g_serial_tbl_ptr-1;
10674 			          IF l_debug = 1 THEN
10675 				     inv_log_util.trace('inv_detail_util_pvt.g_serial_tbl_ptr ' || inv_detail_util_pvt.g_serial_tbl_ptr, 'delete_serial_numbers', 9);
10676 			          END IF;
10677 
10678                               ELSE
10679 			         inv_detail_util_pvt.g_output_serial_rows.delete;
10680 				 inv_detail_util_pvt.g_serial_tbl_ptr := inv_detail_util_pvt.g_serial_tbl_ptr-1;
10681 			         IF l_debug = 1 THEN
10682                                     inv_log_util.trace('Array cleared', 'delete_serial_numbers', 9);
10683 			         END IF;
10684 
10685                               END IF;--End of IF (inv_detail_util_pvt.g_serial_tbl_ptr > 1)
10686 			      exit; --if a serial has been deleted, needn't check other serials present in g_output_serial_rows
10687                           END IF; --End of  IF (inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id = p_inventory_item_id)
10688                         END LOOP; --End of FOR loop
10689                     END IF;--End of IF (inv_detail_util_pvt.g_serial_tbl_ptr > 0)
10690                 END IF;-- End of IF l_get_serial%NOTFOUND
10691 	    END LOOP;--End of LOOP for CURSOR
10692 	    CLOSE l_get_serial;
10693 	    /*End of fix for Bug 5251221 */
10694 
10695 
10696             --
10697             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10698               IF l_debug = 1 THEN
10699                  log_statement(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
10700               END IF;
10701               RAISE fnd_api.g_exc_unexpected_error;
10702             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10703               IF l_debug = 1 THEN
10704                  log_statement(l_api_name, 'err_restore_tree', 'Error in restore_tree');
10705               END IF;
10706               RAISE fnd_api.g_exc_error;
10707             END IF;
10708           ELSE --for put away, restore capacity
10709             --this function reduces the suggested units in the location
10710             -- for each record inserted in wms_transaction_temp as a
10711             -- putaway output record
10712             rollback_capacity_update(
10713               x_return_status              => x_return_status
10714             , x_msg_count                  => x_msg_count
10715             , x_msg_data                   => x_msg_data
10716             , p_organization_id            => p_organization_id
10717             , p_inventory_item_id          => p_inventory_item_id
10718             );
10719 
10720             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10721               IF l_debug = 1 THEN
10722                  log_statement(l_api_name, 'uerr_rollback_cap', 'Unexpected error in rollback_capacity_update');
10723               END IF;
10724               RAISE fnd_api.g_exc_unexpected_error;
10725             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10726               IF l_debug = 1 THEN
10727                  log_statement(l_api_name, 'err_rollback_cap', 'Error in rollback_capacity_update');
10728               END IF;
10729               RAISE fnd_api.g_exc_error;
10730             END IF;
10731 
10732             --if error occurred after capacity got updated but before
10733             -- insertion into WTT, fix the capacity for that record
10734             IF l_capacity_updated THEN
10735               IF l_debug = 1 THEN
10736                  log_statement(l_api_name, 'revert_capacity', 'Calling revert_loc_suggested_capacity');
10737               END IF;
10738               inv_loc_wms_utils.revert_loc_suggested_capacity(
10739                 x_return_status              => x_return_status
10740               , x_msg_count                  => x_msg_count
10741               , x_msg_data                   => x_msg_data
10742               , p_organization_id            => p_organization_id
10743               , p_inventory_location_id      => l_olocator_id
10744               , p_inventory_item_id          => p_inventory_item_id
10745               , p_primary_uom_flag           => 'Y'
10746               , p_transaction_uom_code       => NULL
10747               , p_quantity                   => l_possible_quantity
10748               );
10749 
10750               IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10751                 IF l_debug = 1 THEN
10752                    log_statement(l_api_name, 'uerr_revert_capacity', 'Unexpected error in revert_loc_suggested_capacity');
10753                 END IF;
10754                 RAISE fnd_api.g_exc_unexpected_error;
10755               ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10756                 IF l_debug = 1 THEN
10757                    log_statement(l_api_name, 'err_revert_capacity', 'Error in revert_loc_suggested_capacity');
10758                 END IF;
10759                 RAISE fnd_api.g_exc_error;
10760               END IF;
10761 
10762               l_capacity_updated  := FALSE;
10763             END IF;
10764           END IF;
10765 
10766           --needs to set the trace flag for partial pick to N.
10767           IF l_debug_on THEN
10768             --first record in g_trace_recs always at index 1
10769             l_cur_rec  := 1;
10770 
10771             LOOP
10772               EXIT WHEN NOT g_trace_recs.EXISTS(l_cur_rec);
10773 
10774               IF g_trace_recs(l_cur_rec).suggested_qty > 0 THEN
10775                 g_trace_recs(l_cur_rec).suggested_qty      := 0;
10776                 g_trace_recs(l_cur_rec).partial_pick_flag  := 'N';
10777               END IF;
10778 
10779               l_cur_rec  := l_cur_rec + 1;
10780             END LOOP;
10781 
10782             wms_search_order_globals_pvt.insert_trace_lines(
10783               p_api_version                => 1.0
10784             , p_init_msg_list              => fnd_api.g_false
10785             , p_validation_level           => fnd_api.g_valid_level_full
10786             , x_return_status              => l_return_status
10787             , x_msg_count                  => x_msg_count
10788             , x_msg_data                   => x_msg_data
10789             , p_header_id                  => wms_engine_pvt.g_trace_header_id
10790             , p_rule_id                    => l_rule_id
10791             , p_pre_suggestions            => g_trace_recs
10792             );
10793           END IF;
10794 
10795           --
10796           ROLLBACK TO applyrulesp;
10797           EXIT;
10798         ELSE
10799           IF l_needed_quantity <> l_initial_pri_quantity THEN
10800             IF l_debug = 1 THEN
10801                log_statement(l_api_name, 'updating_input_rec', 'Updating the input line in WTT and pl/sql table');
10802             END IF;
10803 
10804             l_needed_quantity := l_needed_quantity - l_max_tolerance;
10805 	    UPDATE wms_transactions_temp
10806                SET primary_quantity = l_needed_quantity
10807                 ,  secondary_quantity = l_sec_needed_quantity
10808              WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
10809 
10810             wms_re_common_pvt.updateinputline(l_needed_quantity,l_sec_needed_quantity);
10811           END IF;
10812         END IF;
10813       ELSE
10814         x_finished  := fnd_api.g_true;
10815         -- if input line could get satisfied
10816         -- delete the input line in the wms_transactions_temp table
10817         IF l_debug = 1 THEN
10818            log_statement(l_api_name, 'deleting_input_rec', 'Deleting the input line in WTT and pl/sql table');
10819         END IF;
10820 
10821         DELETE FROM wms_transactions_temp
10822               WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
10823 
10824         --
10825         -- and delete input record in PL/SQL table, too
10826         wms_re_common_pvt.deleteinputline;
10827       END IF;
10828 
10829       IF l_debug_on THEN
10830         wms_search_order_globals_pvt.insert_trace_lines(
10831           p_api_version                => 1.0
10832         , p_init_msg_list              => fnd_api.g_false
10833         , p_validation_level           => fnd_api.g_valid_level_full
10834         , x_return_status              => l_return_status
10835         , x_msg_count                  => x_msg_count
10836         , x_msg_data                   => x_msg_data
10837         , p_header_id                  => wms_engine_pvt.g_trace_header_id
10838         , p_rule_id                    => l_rule_id
10839         , p_pre_suggestions            => g_trace_recs
10840         );
10841       END IF;
10842 
10843      <<NextINputRecord>>
10844      NULL;
10845     END LOOP; -- input records
10846 
10847     --
10848     -- Standard check of p_commit
10849     IF fnd_api.to_boolean(p_commit) THEN
10850       COMMIT WORK;
10851     END IF;
10852 
10853     -- end of debugging section
10854     IF l_debug = 1 THEN
10855        log_procedure(l_api_name, 'end', 'End Apply');
10856     END IF;
10857   --
10858   EXCEPTION
10859     WHEN fnd_api.g_exc_error THEN
10860       --
10861       --if l_pack_exists <>2, then open_curs was never called, so no need to
10862       --   close the cursor
10863       IF (l_pack_exists = 2) THEN
10864         close_pick_rule(l_rule_id, v_pick_cursor);
10865       END IF;
10866 
10867       --this function reduces the suggested units in the location
10868       -- for each record inserted in wms_transaction_temp as a
10869       -- putaway output record
10870       rollback_capacity_update(
10871         x_return_status              => l_return_status
10872       , x_msg_count                  => l_msg_count
10873       , x_msg_data                   => l_msg_data
10874       , p_organization_id            => p_organization_id
10875       , p_inventory_item_id          => p_inventory_item_id
10876       );
10877 
10878       --if error occurred after capacity got updated but before
10879       -- insertion into WTT, fix the capacity for that record
10880       IF l_capacity_updated THEN
10881         inv_loc_wms_utils.revert_loc_suggested_capacity(
10882           x_return_status              => l_return_status
10883         , x_msg_count                  => l_msg_count
10884         , x_msg_data                   => l_msg_data
10885         , p_organization_id            => p_organization_id
10886         , p_inventory_location_id      => l_olocator_id
10887         , p_inventory_item_id          => p_inventory_item_id
10888         , p_primary_uom_flag           => 'Y'
10889         , p_transaction_uom_code       => NULL
10890         , p_quantity                   => l_possible_quantity
10891         );
10892         l_capacity_updated  := FALSE;
10893       END IF;
10894 
10895       ROLLBACK TO applyrulesp;
10896       freeglobals;
10897       x_return_status  := fnd_api.g_ret_sts_error;
10898       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
10899       IF l_debug = 1 THEN
10900          log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
10901       END IF;
10902     --
10903     WHEN fnd_api.g_exc_unexpected_error THEN
10904       --if l_pack_exists <>2, then open_curs was never called, so no need to
10905       --   close the cursor
10906       IF (l_pack_exists = 2) THEN
10907         close_put_rule(l_rule_id, v_put_cursor);
10908       END IF;
10909 
10910       --this function reduces the suggested units in the location
10911       -- for each record inserted in wms_transaction_temp as a
10912       -- putaway output record
10913       rollback_capacity_update(
10914         x_return_status              => l_return_status
10915       , x_msg_count                  => l_msg_count
10916       , x_msg_data                   => l_msg_data
10917       , p_organization_id            => p_organization_id
10918       , p_inventory_item_id          => p_inventory_item_id
10919       );
10920 
10921       --if error occurred after capacity got updated but before
10922       -- insertion into WTT, fix the capacity for that record
10923       IF l_capacity_updated THEN
10924         inv_loc_wms_utils.revert_loc_suggested_capacity(
10925           x_return_status              => l_return_status
10926         , x_msg_count                  => l_msg_count
10927         , x_msg_data                   => l_msg_data
10928         , p_organization_id            => p_organization_id
10929         , p_inventory_location_id      => l_olocator_id
10930         , p_inventory_item_id          => p_inventory_item_id
10931         , p_primary_uom_flag           => 'Y'
10932         , p_transaction_uom_code       => NULL
10933         , p_quantity                   => l_possible_quantity
10934         );
10935         l_capacity_updated  := FALSE;
10936       END IF;
10937 
10938       ROLLBACK TO applyrulesp;
10939       freeglobals;
10940       x_return_status  := fnd_api.g_ret_sts_unexp_error;
10941       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
10942       IF l_debug = 1 THEN
10943          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
10944       END IF;
10945     --
10946     WHEN OTHERS THEN
10947       --if l_pack_exists <>2, then open_curs was never called, so no need to
10948       --   close the cursor
10949       IF (l_pack_exists = 2) THEN
10950         close_put_rule(l_rule_id, v_put_cursor);
10951       END IF;
10952 
10953       --this function reduces the suggested units in the location
10954       -- for each record inserted in wms_transaction_temp as a
10955       -- putaway output record
10956       rollback_capacity_update(
10957         x_return_status              => l_return_status
10958       , x_msg_count                  => l_msg_count
10959       , x_msg_data                   => l_msg_data
10960       , p_organization_id            => p_organization_id
10961       , p_inventory_item_id          => p_inventory_item_id
10962       );
10963 
10964       --if error occurred after capacity got updated but before
10965       -- insertion into WTT, fix the capacity for that record
10966       IF l_capacity_updated THEN
10967         inv_loc_wms_utils.revert_loc_suggested_capacity(
10968           x_return_status              => l_return_status
10969         , x_msg_count                  => l_msg_count
10970         , x_msg_data                   => l_msg_data
10971         , p_organization_id            => p_organization_id
10972         , p_inventory_location_id      => l_olocator_id
10973         , p_inventory_item_id          => p_inventory_item_id
10974         , p_primary_uom_flag           => 'Y'
10975         , p_transaction_uom_code       => NULL
10976         , p_quantity                   => l_possible_quantity
10977         );
10978         l_capacity_updated  := FALSE;
10979       END IF;
10980 
10981       ROLLBACK TO applyrulesp;
10982       freeglobals;
10983       x_return_status  := fnd_api.g_ret_sts_unexp_error;
10984 
10985       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
10986         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
10987       END IF;
10988 
10989       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
10990       IF l_debug = 1 THEN
10991          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
10992       END IF;
10993   END apply;
10994 
10995 
10996   --
10997   -- --------------------------------------------------------------------------
10998   -- What does it do:
10999   -- Determines final location control based on location controls defined at
11000   -- organization, subinventory and item level.
11001   -- --------------------------------------------------------------------------
11002   --
11003   FUNCTION loc_control
11004     ( p_org_control      IN    NUMBER
11005      ,p_sub_control      IN    NUMBER
11006      ,p_item_control     IN    NUMBER DEFAULT NULL
11007      ,x_return_status    OUT   NOCOPY VARCHAR2
11008      ,x_msg_count        OUT   NOCOPY NUMBER
11009      ,x_msg_data         OUT   NOCOPY VARCHAR2
11010      ) RETURN NUMBER
11011     IS
11012         --
11013         -- constants
11014         l_api_name        CONSTANT VARCHAR(30) := 'loc_control';
11015         --
11016         -- return variable
11017         l_locator_control NUMBER;
11018         --
11019         -- exception
11020         invalid_loc_control_exception EXCEPTION;
11021         --
11022   BEGIN
11023      IF (p_org_control = 1) THEN
11024          l_locator_control := 1;
11025       ELSIF (p_org_control = 2) THEN
11026          l_locator_control := 2;
11027       ELSIF (p_org_control = 3) THEN
11028          l_locator_control := 2 ;
11029       ELSIF (p_org_control = 4) THEN
11030         IF (p_sub_control = 1) THEN
11031            l_locator_control := 1;
11032         ELSIF (p_sub_control = 2) THEN
11033            l_locator_control := 2;
11034         ELSIF (p_sub_control = 3) THEN
11035            l_locator_control := 2;
11036         ELSIF (p_sub_control = 5) THEN
11037           IF (p_item_control = 1) THEN
11038              l_locator_control := 1;
11039           ELSIF (p_item_control = 2) THEN
11040              l_locator_control := 2;
11041           ELSIF (p_item_control = 3) THEN
11042              l_locator_control := 2;
11043           ELSIF (p_item_control IS NULL) THEN
11044              l_locator_control := p_sub_control;
11045           ELSE
11046             RAISE invalid_loc_control_exception;
11047           END IF;
11048         ELSE
11049             RAISE invalid_loc_control_exception;
11050         END IF;
11051       ELSE
11052             RAISE invalid_loc_control_exception;
11053       END IF;
11054       --
11055       x_return_status := fnd_api.g_ret_sts_success;
11056       RETURN l_locator_control;
11057   EXCEPTION
11058      WHEN invalid_loc_control_exception THEN
11059         fnd_message.set_name('INV','INV_INVALID_LOC_CONTROL');
11060         fnd_msg_pub.ADD;
11061         --
11062         x_return_status := fnd_api.g_ret_sts_error ;
11063         l_locator_control := -1 ;
11064         RETURN l_locator_control ;
11065         --
11066      WHEN fnd_api.g_exc_error THEN
11067         x_return_status := fnd_api.g_ret_sts_error ;
11068         l_locator_control := -1 ;
11069         RETURN l_locator_control ;
11070         --
11071      WHEN fnd_api.g_exc_unexpected_error THEN
11072           x_return_status := fnd_api.g_ret_sts_unexp_error ;
11073           l_locator_control := -1 ;
11074           RETURN l_locator_control ;
11075           --
11076      WHEN OTHERS THEN
11077         x_return_status := fnd_api.g_ret_sts_unexp_error ;
11078         --
11079         IF (fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error)) THEN
11080               fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
11081         END IF;
11082         --
11083         l_locator_control := -1 ;
11084         RETURN l_locator_control ;
11085         --
11086   END loc_control;
11087   --
11088   -- --------------------------------------------------------------------------
11089   -- What does it do:
11090   -- Fetches default putaway sub/locations.
11091   -- they are retained as putaway sub/locations
11092   -- The following call will be used for Non WMS enabled org where default putaway rules
11093   -- are not used and If the input sub/loc are not null,
11094   -- This Procedure called from Applydef()
11095   -- --------------------------------------------------------------------------
11096   --
11097   PROCEDURE get_putaway_defaults
11098     ( p_organization_id           IN  NUMBER,
11099       p_inventory_item_id         IN  NUMBER,
11100       p_to_subinventory_code      IN  VARCHAR2,
11101       p_to_locator_id             IN  NUMBER,
11102       p_to_cost_group_id		IN  NUMBER,
11103       p_org_locator_control_code  IN  NUMBER,
11104       p_item_locator_control_code IN  NUMBER,
11105       p_transaction_type_id	IN  NUMBER,
11106       x_putaway_sub          	OUT NOCOPY VARCHAR2,
11107       x_putaway_loc          	OUT NOCOPY NUMBER,
11108       x_putaway_cost_group_id    	OUT NOCOPY NUMBER,
11109       x_return_status        	OUT NOCOPY VARCHAR2,
11110       x_msg_count            	OUT NOCOPY NUMBER,
11111       x_msg_data             	OUT NOCOPY VARCHAR2
11112      )
11113     IS
11114        -- constants
11115        l_api_name          CONSTANT VARCHAR(30) := 'get_putaway_defaults';
11116        l_return_status     VARCHAR2(1) :=  fnd_api.g_ret_sts_success;
11117        --
11118        -- variable
11119        l_sub_loc_control   NUMBER;
11120        l_loc_control       NUMBER;
11121        l_putaway_sub       VARCHAR2(30);
11122        l_putaway_loc       NUMBER;
11123        l_putaway_cg	 NUMBER := NULL;
11124        l_putaway_cg_org	 NUMBER;
11125        l_inventory_item_id NUMBER;
11126        l_organization_id   NUMBER;
11127        l_sub_status	 NUMBER;
11128        l_loc_status	 NUMBER;
11129        l_allowed		 VARCHAR2(1);
11130        l_primary_cost_method NUMBER;
11131        l_sub_found	 BOOLEAN;
11132 
11133        l_debug NUMBER;
11134        --
11135        CURSOR l_subinventory_code_csr IS
11136           SELECT  subinventory_code
11137             FROM  mtl_item_sub_defaults
11138             WHERE inventory_item_id = l_inventory_item_id
11139               AND organization_id   = l_organization_id
11140               AND default_type      = 3;  -- default transfer order sub
11141 
11142        CURSOR l_locator_status_csr IS
11143           SELECT  status_id
11144             FROM  mtl_item_locations
11145             WHERE inventory_location_id = l_putaway_loc
11146               AND organization_id  = l_organization_id ;
11147        --
11148        CURSOR l_locator_csr IS
11149           SELECT  locator_id
11150             FROM  mtl_item_loc_defaults mtld,
11151                   mtl_item_locations mil
11152             WHERE mtld.locator_id        = mil.inventory_location_id
11153               AND mtld.organization_id   = mil.organization_id
11154               AND mtld.inventory_item_id = l_inventory_item_id
11155               AND mtld.organization_id   = l_organization_id
11156               AND mtld.subinventory_code = l_putaway_sub
11157               AND mtld.default_type      = 3
11158               AND nvl(mil.disable_date,sysdate + 1) > sysdate;
11159 
11160 
11161   BEGIN
11162      l_organization_id   := p_organization_id;
11163      l_inventory_item_id := p_inventory_item_id;
11164 
11165      IF  g_debug IS NOT NULL  THEN
11166           g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
11167      END IF;
11168      l_debug := g_debug;
11169 
11170      IF l_debug = 1  THEN
11171            log_procedure(l_api_name, 'start', 'Start get_putaway_defaults');
11172      END IF;
11173 
11174      -- search for default sub if to_sub in input row is null
11175      IF p_to_subinventory_code IS NULL THEN
11176         OPEN l_subinventory_code_csr;
11177         FETCH l_subinventory_code_csr INTO l_putaway_sub;
11178         IF l_subinventory_code_csr%notfound OR
11179        	   l_putaway_sub IS NULL  THEN
11180   	   CLOSE l_subinventory_code_csr;
11181            fnd_message.set_name('INV','INV_NO_DEFAULT_SUB');
11182   	   fnd_msg_pub.ADD;
11183   	   RAISE fnd_api.g_exc_error;
11184         END IF;
11185         CLOSE l_subinventory_code_csr;
11186       ELSE
11187         l_putaway_sub := p_to_subinventory_code ;
11188      END IF;
11189 
11190      l_sub_found := INV_CACHE.set_tosub_rec(l_organization_id, l_putaway_sub);
11191 
11192      -- now get the locator control and then determine if
11193      -- default locator needs to be selected from item defaults
11194      --
11195     IF NOT l_sub_found THEN
11196         fnd_message.set_name('INV','INV_NO_SUB_LOC_CONTROL');
11197         fnd_msg_pub.ADD;
11198         RAISE fnd_api.g_exc_error;
11199      END if;
11200 
11201      l_sub_loc_control := INV_CACHE.tosub_rec.locator_type;
11202 
11203      IF l_debug = 1  THEN
11204         log_statement(l_api_name, 'p_org_locator_control_code',  p_org_locator_control_code);
11205         log_statement(l_api_name, 'l_sub_loc_control '        ,  l_sub_loc_control);
11206         log_statement(l_api_name, 'p_item_locator_control_code'    ,  p_item_locator_control_code);
11207      END IF;
11208 
11209      -- find out the real locator control
11210 
11211      l_loc_control := loc_control
11212        ( p_org_locator_control_code
11213         ,l_sub_loc_control
11214         ,p_item_locator_control_code
11215         ,l_return_status
11216         ,x_msg_count
11217         ,x_msg_data);
11218 
11219      IF l_debug = 1  THEN
11220          log_statement(l_api_name, 'l_sub_loc_control ',  l_sub_loc_control);
11221          log_statement(l_api_name, 'l_loc_control '    ,  l_loc_control);
11222      END IF;
11223 
11224      IF l_return_status = fnd_api.g_ret_sts_error THEN
11225         RAISE fnd_api.g_exc_error ;
11226       ELSIF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
11227         RAISE fnd_api.g_exc_unexpected_error;
11228      END IF;
11229 
11230     --
11231     IF l_loc_control = 2 THEN -- has locator control
11232         -- if no to_loc was supplied then get from defaults
11233         IF p_to_locator_id IS NULL THEN
11234            OPEN l_locator_csr;
11235            FETCH l_locator_csr INTO l_putaway_loc;
11236            IF l_locator_csr%notfound OR l_putaway_loc IS NULL THEN
11237               CLOSE l_locator_csr;
11238               fnd_message.set_name('INV','INV_NO_DEFAULT_LOC');
11239               fnd_msg_pub.ADD;
11240 
11241              RAISE fnd_api.g_exc_error;
11242            END IF;
11243          ELSE
11244            l_putaway_loc := p_to_locator_id ;
11245            IF l_debug = 1  THEN
11246 	      log_statement(l_api_name, 'l_putaway_loc'    ,  l_putaway_loc);
11247             END IF;
11248         END IF;
11249 
11250      END IF;
11251 
11252      -- Now get the cost group.  If the to_cost_group is specified
11253      -- on the move order, then use that.  If not, query the default
11254      -- cost group for the subinventory if in a standard costing org.
11255      -- If not defined there, or if avg. costing org
11256      -- try to get the default cost group from the organization
11257 
11258      IF p_to_cost_group_id IS NULL THEN
11259         IF INV_CACHE.set_org_rec(l_organization_id) THEN
11260            l_primary_cost_method := INV_CACHE.org_rec.primary_cost_method;
11261            l_putaway_cg_org := INV_CACHE.org_rec.default_cost_group_id;
11262         ELSE
11263   	 l_primary_cost_method := 2;
11264   	 l_putaway_cg_org := NULL;
11265         End If;
11266 
11267         If l_primary_cost_method = 1 Then
11268   	 IF l_sub_found THEN
11269   	    l_putaway_cg := INV_CACHE.tosub_rec.default_cost_group_id;
11270            ELSE
11271   	    l_putaway_cg := NULL;
11272            end if;
11273         End If;
11274 
11275         If l_putaway_cg IS NULL Then
11276            l_putaway_cg := l_putaway_cg_org;
11277   	 if l_putaway_cg IS NULL then
11278               fnd_message.set_name('INV','INV_NO_DEFAULT_COST_GROUP');
11279   	    fnd_msg_pub.ADD;
11280   	    RAISE fnd_api.g_exc_error;
11281   	 end if;
11282         End If;
11283       ELSE
11284         l_putaway_cg := p_to_cost_group_id;
11285      END IF;
11286 
11287      x_putaway_sub 		:= l_putaway_sub;
11288      x_putaway_loc 		:= l_putaway_loc;
11289      x_putaway_cost_group_id 	:= l_putaway_cg;
11290      x_return_status 		:= l_return_status;
11291      /*
11292      IF l_putaway_loc is NULL THEN
11293         x_return_status   := 'N' ;
11294      END IF;
11295      */
11296 
11297      If l_debug = 1  THEN
11298         log_statement(l_api_name, 'Default Putaway values l_putaway_sub ', l_putaway_sub);
11299         log_statement(l_api_name, 'Default Putaway values l_putaway_loc ', l_putaway_loc);
11300         log_statement(l_api_name, 'Default Putaway values l_putaway_cg ',  l_putaway_cg);
11301         log_statement(l_api_name, 'Default Putaway values l_return_status ',  l_return_status);
11302      END IF;
11303 
11304 
11305   EXCEPTION
11306      WHEN fnd_api.g_exc_error THEN
11307           x_return_status := fnd_api.g_ret_sts_error ;
11308           x_putaway_loc   := NULL;
11309           x_putaway_sub   := NULL;
11310           x_putaway_cost_group_id := NULL;
11311           --
11312      WHEN fnd_api.g_exc_unexpected_error THEN
11313           x_return_status := fnd_api.g_ret_sts_unexp_error ;
11314           x_putaway_loc   := NULL;
11315           x_putaway_sub   := NULL;
11316           x_putaway_cost_group_id := NULL;
11317           --
11318      WHEN OTHERS THEN
11319         x_return_status := fnd_api.g_ret_sts_unexp_error ;
11320           x_putaway_loc   := NULL;
11321           x_putaway_sub   := NULL;
11322           x_putaway_cost_group_id := NULL;
11323           --
11324           IF (fnd_msg_pub.check_msg_level
11325               (fnd_msg_pub.g_msg_lvl_unexp_error)) THEN
11326              fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
11327           END IF;
11328   --
11329 
11330 END get_putaway_defaults ;
11331 --
11332 -- API name    : ApplyDefLoc
11333 -- Type        : Private
11334 -- Function    : Verifies a Putaway location with the given transaction
11335 --               input parameters and creates recommendations
11336 --               This API does not utlize the rules and should only be
11337 --               called when the Inventory Locator is specified on
11338 --               the input transaction and there is no requirement
11339 --               to check capacity.
11340 -- Pre-reqs    :
11341 --
11342 -- Parameters  :
11343 --   p_api_version          Standard Input Parameter
11344 --   p_init_msg_list        Standard Input Parameter
11345 --   p_commit               Standard Input Parameter
11346 --   p_validation_level     Standard Input Parameter
11347 --   p_transaction_temp_id  Identifier for the record in view
11348 --                          wms_strategy_mat_txn_tmp_v that represents
11349 --                          the request for detailing
11350 --   p_organization_id      Organization identifier
11351 --   p_inventory_item_id    Inventory item identifier
11352 --   p_transaction_uom      Transaction UOM code
11353 --   p_primary_uom          Primary UOM code
11354 --   p_project_id           Project associated with transaction
11355 --   p_task_id              Task associated with transaction
11356 --
11357 -- Output Parameters
11358 --   x_return_status        Standard Output Parameter
11359 --   x_msg_count            Standard Output Parameter
11360 --   x_msg_data             Standard Output Parameter
11361 --   x_finished             whether the rule has found enough quantity to
11362 --                          find a location that completely satisfy
11363 --                          the requested quantity (value is 'Y' or 'N')
11364 --
11365 -- Version
11366 --   Currently version is 1.0
11367 --
11368 -- Notes       : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
11369 --               This API must be called internally by
11370 --               WMS_Strategy_PVT.Apply only !
11371 --APPLY
11372 PROCEDURE applydefloc(
11373    p_api_version                  IN   NUMBER   ,
11374    p_init_msg_list                IN   VARCHAR2 ,
11375    p_commit                       IN   VARCHAR2 ,
11376    p_validation_level             IN   NUMBER   ,
11377    x_return_status                OUT NOCOPY VARCHAR2 ,
11378    x_msg_count                    OUT NOCOPY NUMBER   ,
11379    x_msg_data                     OUT NOCOPY VARCHAR2 ,
11380    p_transaction_temp_id          IN   NUMBER   ,
11381    p_organization_id              IN   NUMBER   ,
11382    p_inventory_item_id            IN   NUMBER   ,
11383    p_subinventory_code            IN   VARCHAR2 ,
11384    p_locator_id                   IN   NUMBER   ,
11385    p_transaction_uom              IN   VARCHAR2 ,
11386    p_primary_uom                  IN   VARCHAR2 ,
11387    p_transaction_type_id          IN   NUMBER   ,
11388    x_finished                     OUT NOCOPY VARCHAR2 ,
11389    p_lpn_id                       IN   NUMBER   ,
11390    p_simulation_mode              IN   NUMBER   ,
11391    p_project_id                   IN   NUMBER   ,
11392    p_task_id                      IN   NUMBER
11393   )
11394   IS
11395 
11396   -- API standard variables
11397   l_api_version          constant number       := 1.0;
11398   l_api_name             constant varchar2(30) := 'ApplyDefLoc';
11399   -- variables needed for dynamic SQL
11400   l_cursor               integer;
11401   l_rows                 integer;
11402   -- rule dynamic SQL input variables
11403   l_pp_transaction_temp_id
11404                          WMS_TRANSACTIONS_TEMP.PP_TRANSACTION_TEMP_ID%TYPE;
11405   l_revision             WMS_TRANSACTIONS_TEMP.REVISION%TYPE;
11406   l_lot_number           WMS_TRANSACTIONS_TEMP.LOT_NUMBER%TYPE;
11407   l_lot_expiration_date  WMS_TRANSACTIONS_TEMP.LOT_EXPIRATION_DATE%TYPE;
11408   l_from_subinventory_code WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
11409   l_to_subinventory_code WMS_TRANSACTIONS_TEMP.TO_SUBINVENTORY_CODE%TYPE;
11410   l_from_locator_id      WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11411   l_to_locator_id        WMS_TRANSACTIONS_TEMP.TO_LOCATOR_ID%TYPE;
11412   l_from_cost_group_id   WMS_TRANSACTIONS_TEMP.FROM_COST_GROUP_ID%TYPE;
11413   l_to_cost_group_id     WMS_TRANSACTIONS_TEMP.TO_COST_GROUP_ID%TYPE;
11414   l_lpn_id               WMS_TRANSACTIONS_TEMP.LPN_ID%TYPE;
11415   l_initial_pri_quantity WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
11416   -- rule dynamic SQL output variables
11417   l_osubinventory_code   WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
11418   l_olocator_id          WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11419   l_olocator_id_prev     WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11420   l_olocator_id_new      WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11421   l_olocator_id_exist    WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11422   l_possible_quantity    WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
11423   l_possible_trx_qty     WMS_TRANSACTIONS_TEMP.TRANSACTION_QUANTITY%TYPE;
11424   l_sec_possible_quantity    WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
11425   l_sec_possible_trx_qty     WMS_TRANSACTIONS_TEMP.TRANSACTION_QUANTITY%TYPE;
11426   l_reservation_id       WMS_TRANSACTIONS_TEMP.RESERVATION_ID%TYPE;
11427   l_grade_code           VARCHAR2(150);
11428 
11429   l_needed_quantity     NUMBER;
11430   l_sec_needed_quantity NUMBER;
11431   l_locs_index          NUMBER;
11432   l_return_status       VARCHAR2(1);
11433   l_allowed             VARCHAR2(1);
11434   l_debug_on            BOOLEAN;
11435   l_check_cg            BOOLEAN;
11436   l_lpn_controlled_flag NUMBER;
11437   l_comingle            VARCHAR2(1);
11438   l_dummy               NUMBER;
11439 
11440   --added to support pjm
11441   l_project_id          NUMBER;
11442   l_task_id             NUMBER;
11443   l_input_lpn_id        NUMBER;
11444   l_debug               NUMBER;
11445   l_serial_number       NUMBER; -- [ new code ]
11446   use_supplied_loc      BOOLEAN;
11447 
11448   l_locator_type        NUMBER;
11449   x_subinventory_code   WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
11450   x_locator_id          WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11451   x_cost_group_id       WMS_TRANSACTIONS_TEMP.FROM_COST_GROUP_ID%TYPE;
11452 
11453    --cursor to get lpn controlled flag from subinventory
11454    CURSOR l_lpn_controlled IS
11455         SELECT lpn_controlled_flag
11456           FROM mtl_secondary_inventories
11457          WHERE organization_id = p_organization_id
11458            AND secondary_inventory_name = l_osubinventory_code;
11459 
11460 
11461 BEGIN
11462 
11463   IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
11464      g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
11465   END IF;
11466   l_debug := g_debug;
11467 
11468   If (l_debug = 1) then
11469     log_procedure(l_api_name, 'start', 'Start ApplyDefLoc');
11470   End if;
11471   -- end of debugging section
11472 
11473   -- Standard start of API savepoint
11474   SAVEPOINT ApplyRuleSP;
11475   --
11476 
11477 
11478   -- Standard call to check for call compatibility
11479   IF NOT fnd_api.compatible_api_call( l_api_version
11480                                      ,p_api_version
11481                                      ,l_api_name
11482                                      ,g_pkg_name ) THEN
11483     RAISE fnd_api.g_exc_unexpected_error;
11484   END IF;
11485 
11486   -- Initialize message list if p_init_msg_list is set to TRUE
11487   IF fnd_api.to_boolean( p_init_msg_list ) THEN
11488     fnd_msg_pub.initialize;
11489   END IF;
11490   --
11491   -- Initialize API return status to success
11492   x_return_status := fnd_api.g_ret_sts_success;
11493   --
11494   -- Initialize functional return status to completed
11495   x_finished := fnd_api.g_true;
11496   --
11497   -- Validate input parameters and pre-requisites, if validation level
11498   -- requires this
11499   IF p_validation_level <> fnd_api.g_valid_level_none THEN
11500     IF p_transaction_temp_id IS NULL OR
11501        p_transaction_temp_id = fnd_api.g_miss_num  THEN
11502       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
11503         fnd_message.set_name('WMS','WMS_TRX_REQ_LINE_ID_MISS');
11504         If (l_debug = 1) then
11505           log_error_msg(l_api_name, 'trx_req_line_id_missing');
11506         End if;
11507         fnd_msg_pub.add;
11508       END IF;
11509       RAISE fnd_api.g_exc_error;
11510     END IF;
11511     IF p_organization_id IS NULL OR
11512        p_organization_id = fnd_api.g_miss_num  THEN
11513       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
11514         fnd_message.set_name('INV','INV_NO_ORG_INFORMATION');
11515         If (l_debug = 1) then
11516           log_error_msg(l_api_name, 'org_id_missing');
11517         End if;
11518         fnd_msg_pub.add;
11519       END IF;
11520       RAISE fnd_api.g_exc_error;
11521     END IF;
11522     IF p_inventory_item_id IS NULL OR
11523        p_inventory_item_id = fnd_api.g_miss_num  THEN
11524       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
11525         fnd_message.set_name('INV','INV_ITEM_ID_REQUIRED');
11526         If (l_debug = 1) then
11527           log_error_msg(l_api_name, 'item_id_missing');
11528         End if;
11529         fnd_msg_pub.add;
11530       END IF;
11531       RAISE fnd_api.g_exc_error;
11532     END IF;
11533   END IF;
11534   --inv_pp_debug.send_message_to_pipe('finished validations');
11535 
11536   --
11537   -- make sure, everything is clean
11538   FreeGlobals;
11539   wms_parameter_pvt.ClearCache;
11540   --
11541   g_trace_recs.DELETE;
11542   l_debug_on := IsRuleDebugOn(p_simulation_mode);
11543 
11544   if (l_debug = 1) then
11545     log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
11546     log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
11547   End if;
11548 
11549   -- Initialize the pointer to the first trx detail input line
11550   wms_re_common_pvt.InitInputPointer;
11551   --
11552   If (l_debug = 1) then
11553     log_statement(l_api_name, 'start_input_loop',
11554        'Starting loop through input lines');
11555   End if;
11556 
11557   -- Set the output locator and Sub to the supplied parameters
11558   l_osubinventory_code := p_subinventory_code;
11559   l_olocator_id        := p_locator_id;
11560 
11561 -- Loop through all the trx detail input lines
11562 -- Bug # 4637357
11563  use_supplied_loc := TRUE;
11564  WHILE use_supplied_loc LOOP
11565     If (l_debug = 1) then
11566          log_statement(l_api_name, 'getting input line',
11567            'calling wms_re_common_pvt.GetNextInputLine to get input line');
11568     End if;
11569 
11570          --
11571          -- Get the next trx detail input line
11572          wms_re_common_pvt.GetNextInputLine ( l_pp_transaction_temp_id
11573                                              ,l_revision
11574                                              ,l_lot_number
11575                                              ,l_lot_expiration_date
11576                                              ,l_from_subinventory_code
11577                                              ,l_from_locator_id
11578                                              ,l_from_cost_group_id
11579                                              ,l_to_subinventory_code
11580                                              ,l_to_locator_id
11581                                              ,l_to_cost_group_id
11582                                              ,l_needed_quantity
11583                                              ,l_sec_needed_quantity
11584                                              ,l_grade_code
11585                                              ,l_reservation_id
11586                                              ,l_serial_number -- [ new code ]
11587                                              ,l_lpn_Id);
11588          EXIT WHEN l_pp_transaction_temp_id IS NULL;
11589 
11590 
11591          IF  ( p_subinventory_code is NULL  AND  p_locator_id is NULL ) THEN
11592                 -- Set the output locator and Sub to the inlput line sub/loc
11593 	        l_osubinventory_code := l_to_subinventory_code;
11594                 l_olocator_id        := l_to_locator_id;
11595 
11596          END IF;
11597 
11598 
11599          If (l_debug = 1) then
11600            log_statement(l_api_name, 'input_rec', 'Got next input line');
11601            log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
11602            log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
11603            log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
11604            log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
11605            log_statement(l_api_name, 'input_cg',  'cg:'  || l_from_cost_group_id);
11606            log_statement(l_api_name, 'input_tsub','tsub:'|| l_to_subinventory_code);
11607            log_statement(l_api_name, 'input_tloc','tloc:'|| l_to_locator_id);
11608            log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
11609            log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
11610            log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
11611            log_statement(l_api_name, 'input_sec_qty', 'sec qty:' || l_sec_needed_quantity);
11612      End if;
11613     --- Bug#4729564
11614     --- Populate default dest. loct for non-wms org if it is null and raise error if locator is null for dynamic loc controlled.
11615 
11616     get_putaway_defaults ( p_organization_id ,
11617   			   p_inventory_item_id,
11618   			   l_to_subinventory_code,
11619   			   l_to_locator_id,
11620   			   l_to_cost_group_id,
11621   			   inv_cache.org_rec.stock_locator_control_code,
11622   			   inv_cache.item_rec.location_control_code,
11623   			   p_transaction_type_id,
11624   			   x_subinventory_code ,
11625   			   x_locator_id,
11626   			   x_cost_group_id,
11627   			   x_return_status,
11628   			   x_msg_count,
11629   			   x_msg_data );
11630 
11631     -- log_statement(l_api_name, 'Default Putaway values l_return_status ',  l_return_status);
11632 
11633     IF l_return_status = fnd_api.g_ret_sts_error THEN
11634          RAISE fnd_api.g_exc_error ;
11635          -- log_statement(l_api_name, 'ApplyDef()', 'Dest Loct is NUll' );
11636          -- GOTO NextOutputRecord;
11637     ELSIF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
11638          RAISE fnd_api.g_exc_unexpected_error;
11639     END IF;
11640 
11641    --log_statement(l_api_name, 'l_to_locator_id',nvl(l_to_locator_id, -9999) );
11642    IF  (l_osubinventory_code is NULL AND x_subinventory_code is not NULL ) then
11643        l_osubinventory_code := x_subinventory_code;
11644        If (l_debug = 1 ) then
11645           log_statement(l_api_name, 'Setting default SUB ',  l_osubinventory_code);
11646        End if;
11647    END IF;
11648 
11649    IF (l_olocator_id is NULL and x_locator_id is not NULL) THEN
11650        l_osubinventory_code := x_subinventory_code;
11651        l_olocator_id := x_locator_id;
11652        If (l_debug = 1 ) then
11653           log_statement(l_api_name, 'Setting default SUB / LOC ',  l_osubinventory_code);
11654           log_statement(l_api_name, 'Setting default LOC ',  l_olocator_id);
11655        End if;
11656    END IF;
11657 
11658    IF (l_to_cost_group_id is NULL and x_cost_group_id is NOT NULL ) THEN
11659        l_to_cost_group_id :=  x_cost_group_id;
11660    END IF;
11661    -- Bug 5682045 Changed l_to_locator_id to l_olocator_id
11662    IF l_olocator_id  is NULL THEN
11663       l_locator_type := NULL;
11664 
11665      -- log_statement(l_api_name, 'p_organization_id :', p_organization_id);
11666         log_statement(l_api_name, 'To check dynamic loc : l_to_subinventory_code', l_to_subinventory_code);
11667 
11668       select locator_type into l_locator_type
11669         from mtl_secondary_inventories
11670        where organization_id = p_organization_id
11671          and SECONDARY_INVENTORY_NAME  = l_to_subinventory_code;
11672 
11673       -- log_statement(l_api_name, 'l_locator_type' , l_locator_type);
11674 
11675       IF l_locator_type = 3 or l_locator_type = 2 THEN  -- Dynamic / Prespecified Loc Control
11676           If (l_debug = 1 ) then
11677             log_statement(l_api_name, 'Default Putaway values l_return_status ',  l_return_status);
11678             log_statement(l_api_name, 'ApplyDef()', 'Dest Loct is NUll / Go to Next record ' );
11679           End if;
11680 
11681          GOTO NextOutputRecord;
11682       END if;
11683   END IF;
11684   -- end of Bug#4729564
11685   --
11686 
11687   -- use_supplied_loc := TRUE;
11688   -- To support PJM, check project and task if supplied.
11689   -- Case 1) Project and Task not supplied do nothing
11690   --      2) Project and Task Supplied and current record has same
11691   --         project and task continue processing.
11692   --      3) Project and Task supplied, not in current record
11693   --         then create a new entry in MTL_ITEM_LOCATIONS with
11694   --         properties of current record but with require project and task
11695   --      <This assumes that the results are ordered by Project and Task>
11696   IF p_project_id IS NOT NULL THEN
11697 
11698       --bug 2400549 - for WIP backflush transfer putaway,
11699       --always use the locator specified on the move order line, even
11700       --if that locator is from common stock (not project)
11701       IF NOT(wms_engine_pvt.g_move_order_type = 7 and
11702          wms_engine_pvt.g_transaction_action_id = 2) THEN
11703         If (l_debug = 1) then
11704           log_statement(l_api_name, 'do_project2',
11705               'Calling do project check');
11706         End if;
11707         IF DoProjectCheck(l_return_status, l_olocator_id,
11708                   p_project_id, p_task_id, l_olocator_id_new, l_olocator_id_exist)
11709         THEN
11710           If (l_debug = 1) then
11711             log_statement(l_api_name, 'do_project_success',
11712               'Do project check returned new locator');
11713           End if;
11714           l_olocator_id_prev := l_olocator_id;
11715           l_olocator_id := l_olocator_id_new;
11716         ELSE
11717           -- Current locator does not have required project/task
11718           -- If it exists use it
11719           If l_olocator_id_exist IS NOT NULL THEN
11720              l_olocator_id := l_olocator_id_exist;
11721           ELSE
11722              use_supplied_loc := false;
11723              x_finished := fnd_api.g_false;
11724              If (l_debug = 1) then
11725                log_statement(l_api_name, 'do_project_fail',
11726                  'Do project check failed. Cannot use supplied locator with this Project and Task.');
11727              End if;
11728           End if;
11729         END IF; --do project check
11730       END IF;  -- not wip backflush
11731   END IF; -- needed project <> -9999
11732 
11733 
11734   --check status to see if putting away to this location is allowed
11735   -- for this transaction type
11736   -- This API checks the status for the subinventory, locator,
11737   -- and lot
11738 
11739   -- Pass in NULL for lot number as this was checked during Pick
11740   If (l_debug = 1) then
11741        log_statement(l_api_name, 'checking_status',
11742          'calling is_sub_loc_lot_trx_allowed to check status');
11743   End if;
11744   If g_transaction_type_id = p_transaction_type_id AND
11745      g_organization_id = p_organization_id AND
11746      g_inventory_item_id = p_inventory_item_id AND
11747      g_subinventory_code = l_osubinventory_code AND
11748      g_st_locator_id = l_olocator_id  THEN
11749      l_allowed := g_allowed;
11750   ELSE
11751 
11752      l_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
11753               p_transaction_type_id  => p_transaction_type_id
11754              ,p_organization_id      => p_organization_id
11755              ,p_inventory_item_id    => p_inventory_item_id
11756              ,p_subinventory_code    => l_osubinventory_code
11757              ,p_locator_id           => l_olocator_id
11758              ,p_lot_number           => NULL);
11759 
11760 
11761      -- When changing SUB value set lpn_controlled_flag to null
11762      IF (g_organization_id = p_organization_id) OR (g_subinventory_code <> l_osubinventory_code) THEN
11763         g_lpn_controlled_flag := NULL;
11764      END IF;
11765 
11766      g_transaction_type_id := p_transaction_type_id;
11767      g_organization_id := p_organization_id;
11768      g_inventory_item_id := p_inventory_item_id;
11769      g_subinventory_code := l_osubinventory_code;
11770      g_st_locator_id := l_olocator_id;
11771      g_allowed := l_allowed;
11772    END IF;
11773 
11774    IF l_allowed <> 'Y' THEN
11775       use_supplied_loc := false;
11776       x_finished := fnd_api.g_false;
11777       If (l_debug = 1) then
11778          log_event(l_api_name, 'bad_status',
11779              'This transaction type is not allowed by the status ' ||
11780              'for the subinventory, locator. ');
11781       End if;
11782    END IF;
11783 
11784 /* Commented and moved the following code above
11785    Check the tag  bug # 4637357
11786 
11787   -- Loop through all the trx detail input lines
11788   WHILE use_supplied_loc LOOP
11789      If (l_debug = 1) then
11790        log_statement(l_api_name, 'getting input line',
11791          'calling wms_re_common_pvt.GetNextInputLine to get input line');
11792      End if;
11793 
11794      --
11795      -- Get the next trx detail input line
11796      wms_re_common_pvt.GetNextInputLine ( l_pp_transaction_temp_id
11797                                          ,l_revision
11798                                          ,l_lot_number
11799                                          ,l_lot_expiration_date
11800                                          ,l_from_subinventory_code
11801                                          ,l_from_locator_id
11802                                          ,l_from_cost_group_id
11803                                          ,l_to_subinventory_code
11804                                          ,l_to_locator_id
11805                                          ,l_to_cost_group_id
11806                                          ,l_needed_quantity
11807                                          ,l_sec_needed_quantity
11808                                          ,l_grade_code
11809                                          ,l_reservation_id
11810                                          ,l_serial_number -- [ new code ]
11811                                          ,l_lpn_Id);
11812      EXIT WHEN l_pp_transaction_temp_id IS NULL;
11813 
11814      If (l_debug = 1) then
11815        log_statement(l_api_name, 'input_rec', 'Got next input line');
11816        log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
11817        log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
11818        log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
11819        log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
11820        log_statement(l_api_name, 'input_cg',  'cg:'  || l_from_cost_group_id);
11821        log_statement(l_api_name, 'input_tsub','tsub:'|| l_to_subinventory_code);
11822        log_statement(l_api_name, 'input_tloc','tloc:'|| l_to_locator_id);
11823        log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
11824        log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
11825        log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
11826        log_statement(l_api_name, 'input_sec_qty', 'sec qty:' || l_sec_needed_quantity);
11827      End if;
11828 */
11829      -- Save the initial input qty for later usage
11830      l_initial_pri_quantity := l_needed_quantity;
11831      --
11832      l_input_lpn_id := l_lpn_id;
11833 
11834      l_locs_index := 0;
11835 
11836      IF l_debug_on THEN
11837           g_trace_recs(l_locs_index).revision := l_revision;
11838           g_trace_recs(l_locs_index).lot_number := l_lot_number;
11839           g_trace_recs(l_locs_index).lot_expiration_date := l_lot_expiration_date;
11840           g_trace_recs(l_locs_index).subinventory_code := l_osubinventory_code;
11841           g_trace_recs(l_locs_index).locator_id := l_olocator_id;
11842           g_trace_recs(l_locs_index).cost_group_id := l_to_cost_group_id;
11843           g_trace_recs(l_locs_index).uom_code := NULL;
11844           g_trace_recs(l_locs_index).lpn_id := l_input_lpn_id;
11845           g_trace_recs(l_locs_index).quantity := NULL;
11846           --init to 0, in case of error
11847           g_trace_recs(l_locs_index).suggested_qty := 0;
11848           g_trace_recs(l_locs_index).Material_status_flag := 'Y';
11849 
11850           log_statement(l_api_name, 'fetch_put_sub',
11851                'Subinventory: ' || l_osubinventory_code);
11852           log_statement(l_api_name, 'fetch_put_loc',
11853                'Locator: ' || l_olocator_id);
11854           log_statement(l_api_name, 'fetch_put_proj',
11855                'Project: ' || l_project_id);
11856           log_statement(l_api_name, 'fetch_put_task',
11857                'Task: ' || l_task_id);
11858 
11859 
11860      END IF;
11861 
11862      --Determine if putaway sub is LPN controlled.  If it is not,
11863      --then we need to check cost group commingling always;
11864      -- Check cost group if
11865      -- Cost group is not null AND
11866      -- (sub is not lpn controlled OR
11867      --  No lpn on move order line OR
11868      --  not a staging transfer)
11869      --Never suggest comingling of cost groups, unless we are
11870      -- putting away a LPN.
11871      --When putting away an LPN, we assume that user is putting away
11872      -- whole LPN, which means there will never be comingling.
11873      --bug 1570597 - staging transfers are always put away in an LPN,
11874      -- so we don't need to check for comingling.
11875      --bug 2161565 - need to check for cg commingling if
11876      -- to subinventory is not LPN controlled.
11877      --bug 2492526 - putting away to a project controlled locator
11878      -- will always change the CG.  So no need to worry about CG
11879      -- commingling if the dest. loc is project controlled.
11880      If (l_debug = 1) then
11881        log_statement(l_api_name, 'Check LPN Controlled',
11882          'Check if cost group or project supplied and lpn controlled');
11883      End if;
11884      IF l_to_cost_group_id IS NULL THEN
11885         l_check_cg := FALSE;
11886      ELSIF l_project_id IS NOT NULL THEN
11887         l_check_cg := FALSE;
11888      ELSIF (p_lpn_id IS NOT NULL OR
11889         p_transaction_type_id IN (52,53)) THEN
11890 
11891         If (nvl(g_subinventory_code,'-9999') <> l_osubinventory_code OR
11892              g_lpn_controlled_flag IS NULL) THEN
11893            OPEN l_lpn_controlled;
11894            FETCH l_lpn_controlled INTO g_lpn_controlled_flag;
11895            g_subinventory_code := l_osubinventory_code;
11896 
11897            -- by default, assume sub is lpn controlled
11898            If l_lpn_controlled%notfound OR
11899              g_lpn_controlled_flag IS NULL OR
11900              g_lpn_controlled_flag NOT IN (1,2) Then
11901                 g_lpn_controlled_flag := 1;
11902            End If;
11903            CLOSE l_lpn_controlled;
11904         End If;
11905         l_lpn_controlled_flag := g_lpn_controlled_flag;
11906 
11907         If (l_debug = 1) then
11908            log_statement(l_api_name, 'Check LPN Controlled',
11909             'lpn_control_flag : ' || l_lpn_controlled_flag);
11910         End if;
11911 
11912         If l_lpn_controlled_flag = 1 Then
11913            l_check_cg := FALSE;
11914         Else
11915            l_check_cg := TRUE;
11916         End If;
11917      ELSE
11918         l_check_cg := TRUE;
11919      END IF;
11920      --Check to see if putaway would comingle cost groups.
11921      IF l_check_cg THEN
11922         If (l_debug = 1) then
11923           log_statement(l_api_name, 'Check comingling',
11924              'calling inv_comingling_utils.comingle_check');
11925         End if;
11926         inv_comingling_utils.comingle_check(
11927               x_return_status => x_return_status
11928              ,x_msg_count => x_msg_count
11929              ,x_msg_data  => x_msg_data
11930              ,x_comingling_occurs => l_comingle
11931              ,x_count     => l_dummy
11932              ,p_organization_id => p_organization_id
11933              ,p_inventory_item_id => p_inventory_item_id
11934              ,p_revision => l_revision
11935              ,p_lot_number => l_lot_number
11936              ,p_subinventory_code => l_osubinventory_code
11937              ,p_locator_id => l_olocator_id
11938              ,p_lpn_id => NULL
11939              ,p_cost_group_id => l_to_cost_group_id
11940           );
11941         if x_return_status = fnd_api.g_ret_sts_unexp_error then
11942           If (l_debug = 1) then
11943             log_statement(l_api_name, 'uerr_comingle_check',
11944               'Unexpected error in comingle_check');
11945           End if;
11946           RAISE fnd_api.g_exc_unexpected_error;
11947         elsif x_return_status = fnd_api.g_ret_sts_error then
11948           If (l_debug = 1) then
11949             log_statement(l_api_name, 'err_comingle_check',
11950               'Error in comingle_check');
11951           End if;
11952           RAISE fnd_api.g_exc_error;
11953         end if;
11954 
11955         -- Skip record if it would cause comingling
11956         if l_comingle = 'Y' then
11957           If (l_debug = 1) then
11958             log_event(l_api_name, 'comingle_putaway',
11959               'Putaway to this location would comingle cost groups. ');
11960           End if;
11961           if l_debug_on then
11962              g_trace_recs(l_locs_index).CG_comingle_flag := 'N';
11963           end if;
11964           GOTO NextOutputRecord;
11965         end if;
11966 
11967         if l_debug_on then
11968              g_trace_recs(l_locs_index).CG_comingle_flag := 'Y';
11969         end if;
11970 
11971      END IF;
11972 
11973      l_possible_quantity := l_needed_quantity;
11974      l_sec_possible_quantity := l_sec_needed_quantity;
11975 
11976      IF l_debug_on THEN
11977         g_trace_recs(l_locs_index).suggested_qty := l_possible_quantity;
11978      END IF;
11979 
11980      -- get the transaction quantity
11981      IF p_transaction_uom = p_primary_uom THEN
11982         l_possible_trx_qty := l_possible_quantity;
11983       ELSE
11984         l_possible_trx_qty :=
11985              inv_convert.inv_um_convert(
11986                                         p_inventory_item_id
11987                                         ,NULL
11988                                         ,l_possible_quantity
11989                                         ,p_primary_uom
11990                                         ,p_transaction_uom
11991                                         ,NULL
11992                                         ,NULL);
11993      END IF;
11994      l_sec_possible_trx_qty := l_sec_possible_quantity;
11995      If (l_debug = 1) then
11996         log_statement(l_api_name, 'insert_put_wtt_recs',
11997          'Inserting putaway records in wtt');
11998      End if;
11999      -- insert temporary suggestion
12000      INSERT
12001        INTO WMS_TRANSACTIONS_TEMP
12002        ( PP_TRANSACTION_TEMP_ID
12003         ,TRANSACTION_TEMP_ID
12004         ,TYPE_CODE
12005         ,LINE_TYPE_CODE
12006         ,TRANSACTION_QUANTITY
12007         ,PRIMARY_QUANTITY
12008         ,SECONDARY_QUANTITY
12009         ,GRADE_CODE
12010         ,REVISION
12011         ,LOT_NUMBER
12012         ,LOT_EXPIRATION_DATE
12013         ,FROM_SUBINVENTORY_CODE
12014         ,FROM_LOCATOR_ID
12015         ,RULE_ID
12016         ,RESERVATION_ID
12017         ,TO_SUBINVENTORY_CODE
12018         ,TO_LOCATOR_ID
12019         ,FROM_COST_GROUP_ID
12020         ,TO_COST_GROUP_ID
12021         ,LPN_ID
12022         ) VALUES
12023        ( wms_transactions_temp_s.NEXTVAL
12024         ,p_transaction_temp_id
12025         ,1      -- p_type_code
12026         ,2             -- line type code is output
12027         ,l_possible_trx_qty
12028         ,l_possible_quantity
12029         ,l_sec_possible_quantity
12030         ,l_grade_code
12031         ,l_revision
12032         ,l_lot_number
12033         ,l_lot_expiration_date
12034         ,l_from_subinventory_code
12035         ,l_from_locator_id
12036         ,NULL   -- l_rule_id
12037         ,l_reservation_id
12038         ,l_osubinventory_code
12039         ,l_olocator_id
12040         ,l_from_cost_group_id
12041         ,l_to_cost_group_id
12042         ,l_input_lpn_id
12043          );
12044 
12045      If (l_debug = 1) then
12046        log_event(l_api_name, 'putaway_loc_found',
12047           'Found put away location for quantity ' || l_possible_quantity);
12048      End if;
12049 
12050      l_needed_quantity := 0;
12051 
12052      <<NextOutputRecord>>
12053 
12054 
12055 
12056      -- if input line couldn't get satisfied ...
12057      IF l_needed_quantity > 0 THEN
12058          -- notice, that at least one input record couldn't get satisfied
12059          x_finished := fnd_api.g_false;
12060          If (l_debug = 1) then
12061            log_event(l_api_name, 'no_success',
12062                'Locator supplied could not be used');
12063          End if;
12064 
12065      ELSE
12066          x_finished := fnd_api.g_true;
12067          -- if input line could get satisfied
12068          -- delete the input line in the wms_transactions_temp table
12069          If (l_debug = 1) then
12070           log_statement(l_api_name, 'deleting_input_rec',
12071               'Deleting the input line in WTT and pl/sql table');
12072          End if;
12073          DELETE
12074            FROM WMS_TRANSACTIONS_TEMP
12075            WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
12076          --
12077          -- and delete input record in PL/SQL table, too
12078          wms_re_common_pvt.DeleteInputLine;
12079      END IF;
12080      IF l_debug_on THEN
12081         wms_search_order_globals_pvt.insert_trace_lines(
12082            p_api_version => 1.0
12083           ,p_init_msg_list => fnd_api.g_false
12084           ,p_validation_level => fnd_api.g_valid_level_full
12085           ,x_return_status => l_return_status
12086           ,x_msg_count => x_msg_count
12087           ,x_msg_data => x_msg_data
12088           ,p_header_id => wms_engine_pvt.g_trace_header_id
12089           ,p_rule_id => null
12090           ,p_pre_suggestions => g_trace_recs
12091          );
12092      END IF;
12093 
12094   END LOOP;         -- input records
12095   --
12096   -- Standard check of p_commit
12097   IF fnd_api.to_boolean(p_commit) THEN
12098      COMMIT WORK;
12099   END IF;
12100   --
12101   If (l_debug = 1) then
12102     log_procedure(l_api_name, 'end', 'End Apply');
12103   End if;
12104   l_debug := NULL;
12105   --
12106 EXCEPTION
12107    WHEN fnd_api.g_exc_error THEN
12108 
12109     ROLLBACK TO ApplyRuleSP;
12110     FreeGlobals;
12111     x_return_status := fnd_api.g_ret_sts_error;
12112     fnd_msg_pub.count_and_get( p_count => x_msg_count
12113                                ,p_data  => x_msg_data );
12114     If (l_debug = 1) then
12115       log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
12116     End if;
12117     l_debug := NULL;
12118    --
12119    WHEN fnd_api.g_exc_unexpected_error THEN
12120     ROLLBACK TO ApplyRuleSP;
12121     FreeGlobals;
12122     x_return_status := fnd_api.g_ret_sts_unexp_error;
12123     fnd_msg_pub.count_and_get( p_count => x_msg_count
12124                               ,p_data  => x_msg_data );
12125     If (l_debug = 1) then
12126       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
12127     End if;
12128     l_debug := NULL;
12129    --
12130    WHEN OTHERS THEN
12131 
12132     ROLLBACK TO ApplyRuleSP;
12133     FreeGlobals;
12134     x_return_status := fnd_api.g_ret_sts_unexp_error;
12135     IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12136        fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
12137     END IF;
12138     fnd_msg_pub.count_and_get( p_count => x_msg_count
12139                                ,p_data  => x_msg_data );
12140     If (l_debug = 1) then
12141       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
12142     End if;
12143     l_debug := NULL;
12144 
12145 END applydefloc;
12146 
12147 
12148 
12149   --
12150   --
12151   -- API name    : CheckSyntax
12152   -- Type        : Private
12153   -- Function    : This wrapper on Generate_Rule_Package is
12154   --     called from the WMS_RULES form
12155   -- Pre-reqs    : one record in WMS_RULES_B uniquely identified by parameter
12156   --                p_rule_id
12157   -- Input Parameters  :
12158   --   p_api_version       Standard Input Parameter
12159   --   p_init_msg_list     Standard Input Parameter
12160   --   p_validation_level  Standard Input Parameter
12161   --   p_rule_id           Identifier of the rule to check
12162   --
12163   -- Output Parameters  :
12164   --   x_return_status     Standard Output Parameter
12165   --   x_msg_count         Standard Output Parameter
12166   --   x_msg_data          Standard Output Parameter
12167   --
12168   -- Version     :
12169   --   Current version 1.0
12170   --
12171   -- Notes       : calls API's of WMS_RE_Common_PVT
12172   --
12173   PROCEDURE checksyntax(
12174     p_api_version      IN            NUMBER
12175   , p_init_msg_list    IN            VARCHAR2
12176   , p_validation_level IN            NUMBER
12177   , x_return_status    OUT NOCOPY    VARCHAR2
12178   , x_msg_count        OUT NOCOPY    NUMBER
12179   , x_msg_data         OUT NOCOPY    VARCHAR2
12180   , p_rule_id          IN            NUMBER
12181   ) IS
12182     PRAGMA AUTONOMOUS_TRANSACTION;
12183     -- API standard variables
12184     l_api_version CONSTANT NUMBER       := 1.0;
12185     l_api_name    CONSTANT VARCHAR2(30) := 'CheckSyntax';
12186   --
12187   --
12188   BEGIN
12189      --
12190     -- Standard call to check for call compatibility
12191     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
12192       RAISE fnd_api.g_exc_unexpected_error;
12193     END IF;
12194 
12195     -- Initialize message list if p_init_msg_list is set to TRUE
12196     IF fnd_api.to_boolean(p_init_msg_list) THEN
12197       fnd_msg_pub.initialize;
12198     END IF;
12199 
12200     --
12201     -- Initialize API return status to success
12202     x_return_status  := fnd_api.g_ret_sts_success;
12203     generaterulepackage(p_api_version, p_init_msg_list, p_validation_level, x_return_status, x_msg_count, x_msg_data, p_rule_id);
12204 
12205     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12206       RAISE fnd_api.g_exc_unexpected_error;
12207     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12208       RAISE fnd_api.g_exc_error;
12209     END IF;
12210 
12211   EXCEPTION
12212     WHEN fnd_api.g_exc_error THEN
12213       --
12214       x_return_status  := fnd_api.g_ret_sts_error;
12215       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12216     --
12217     WHEN fnd_api.g_exc_unexpected_error THEN
12218       x_return_status  := fnd_api.g_ret_sts_unexp_error;
12219       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12220     --
12221     WHEN OTHERS THEN
12222       freeglobals;
12223       x_return_status  := fnd_api.g_ret_sts_unexp_error;
12224 
12225       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12226         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
12227       END IF;
12228 
12229       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12230   --
12231   END checksyntax;
12232 
12233   --
12234   -- API name    : Find_Rule
12235   -- Type        : Private
12236   -- Function    : find a rule by id
12237   -- Input Parameters  :
12238   --   p_api_version     Standard Input Parameter
12239   --   p_init_msg_list   Standard Input Parameter
12240   --   p_rule_id         Identifier of the rule
12241   --
12242   -- Output Parameters:
12243   --   x_return_status   Standard Output Parameter
12244   --   x_msg_count       Standard Output Parameter
12245   --   x_msg_data        Standard Output Parameter
12246   --   x_found           true if found ; else false
12247   --   x_rule_rec        info of the rule if found
12248 
12249   -- Version     :
12250   --   Current version 1.0
12251   --
12252   -- Notes       : calls API's of WMS_RE_Common_PVT
12253   --
12254   PROCEDURE find_rule(
12255     p_api_version   IN            NUMBER
12256   , p_init_msg_list IN            VARCHAR2
12257   , x_return_status OUT NOCOPY    VARCHAR2
12258   , x_msg_count     OUT NOCOPY    NUMBER
12259   , x_msg_data      OUT NOCOPY    VARCHAR2
12260   , p_rule_id       IN            NUMBER
12261   , x_found         OUT NOCOPY    BOOLEAN
12262   , x_rule_rec      OUT NOCOPY    rule_rec
12263   ) IS
12264     -- API standard variables
12265     l_api_version CONSTANT NUMBER       := 1.0;
12266     l_api_name    CONSTANT VARCHAR2(30) := 'Find_Rule';
12267 
12268     --
12269     CURSOR l_cur IS
12270       SELECT rule_id
12271            , organization_id
12272            , type_code
12273            , NAME
12274            , description
12275            , qty_function_parameter_id
12276            , enabled_flag
12277            , user_defined_flag
12278            , attribute_category
12279            , attribute1
12280            , attribute2
12281            , attribute3
12282            , attribute4
12283            , attribute5
12284            , attribute6
12285            , attribute7
12286            , attribute8
12287            , attribute9
12288            , attribute10
12289            , attribute11
12290            , attribute12
12291            , attribute13
12292            , attribute14
12293            , attribute15
12294         FROM wms_rules_vl
12295        WHERE rule_id = p_rule_id;
12296 
12297     --
12298     l_rule_rec             rule_rec;
12299   BEGIN
12300     OPEN l_cur;
12301     FETCH l_cur INTO l_rule_rec;
12302 
12303     --
12304     IF l_cur%NOTFOUND THEN
12305       x_found  := FALSE;
12306     ELSE
12307       x_found     := TRUE;
12308       x_rule_rec  := l_rule_rec;
12309     END IF;
12310 
12311     CLOSE l_cur;
12312   --
12313   EXCEPTION
12314     WHEN fnd_api.g_exc_error THEN
12315       x_return_status  := fnd_api.g_ret_sts_error;
12316       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12317     --
12318     WHEN fnd_api.g_exc_unexpected_error THEN
12319       x_return_status  := fnd_api.g_ret_sts_unexp_error;
12320       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12321     --
12322     WHEN OTHERS THEN
12323       x_return_status  := fnd_api.g_ret_sts_unexp_error;
12324 
12325       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12326         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
12327       END IF;
12328 
12329       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12330   --
12331   END find_rule;
12332 
12333   --GetPackageName
12334   --
12335   --This function establishes the naming standard for the rule packages.
12336   --Currently, the naming standard is WMS_RULE_## , where ## is rule id
12337   PROCEDURE getpackagename(p_rule_id IN NUMBER, x_package_name OUT NOCOPY VARCHAR2) IS
12338   BEGIN
12339     x_package_name  := 'WMS_RULE_' || p_rule_id;
12340   END getpackagename;
12341 
12342   -- InitBuildPackage
12343   --    Called from GenerateRulePackage. Initializes
12344   -- the global variables needed to dynamically build the
12345   -- rule package.
12346   PROCEDURE initbuildpackage IS
12347   BEGIN
12348     g_build_package_row  := 0;
12349     g_build_package_tbl.DELETE;
12350   END initbuildpackage;
12351 
12352   --Build Package
12353   --This API takes a VARCHAR of undetermined length
12354   -- and breaks it up into varchars of length 255.  These
12355   -- smaller strings are stored in the g_build_package_tbl,
12356   -- and compose the sql statement to create the
12357   -- Rules package.
12358   PROCEDURE buildpackage(p_package_string IN VARCHAR2) IS
12359     l_cur_start      NUMBER;
12360     l_package_length NUMBER;
12361     l_num_chars      NUMBER := 255;
12362     l_row            NUMBER;
12363   BEGIN
12364     l_cur_start          := 1;
12365     -- get last filled row of table
12366     l_row                := g_build_package_row;
12367     l_package_length     := LENGTH(p_package_string);
12368     inv_log_util.trace( l_package_length ,'l_package_length' , 9);
12369     inv_log_util.trace( p_package_string ,'p_package_string' , 9);
12370     -- return if string is null
12371     IF l_package_length IS NULL
12372        OR l_package_length = 0 THEN
12373       RETURN;
12374     END IF;
12375 
12376     --Loop through string, reading off l_num_chars bytes at a time
12377     LOOP
12378       --When at end of varchar, exit loop;
12379       EXIT WHEN l_cur_start > l_package_length;
12380       l_row                       := l_row + 1;
12381       --Get substring from package_string
12382       g_build_package_tbl(l_row)  := SUBSTR(p_package_string, l_cur_start, l_num_chars);
12383       --Call build package to add row
12384       -- We may need to call this API for AOL standards.
12385       --ad_ddl.build_package(l_cur_string, l_row);
12386 
12387       --increment pointers
12388       l_cur_start                 := l_cur_start + l_num_chars;
12389 
12390       IF l_cur_start + l_num_chars > l_package_length THEN
12391         l_num_chars  := l_package_length - l_cur_start + 1;
12392       END IF;
12393     END LOOP;
12394 
12395     g_build_package_row  := l_row;
12396   END buildpackage;
12397 
12398   --CreatePackage
12399   -- This API calls dynamic SQL to build the package
12400   -- currently sitting in the g_build_package_tbl.
12401   --   p_package_body = TRUE if the package to be created is a body
12402   PROCEDURE createpackage(x_return_status OUT NOCOPY VARCHAR2, p_package_name IN VARCHAR2, p_package_body IN BOOLEAN) IS
12403     l_schema     VARCHAR2(30);
12404     l_status     VARCHAR2(1);
12405     l_industry   VARCHAR2(1);
12406     l_comp_error VARCHAR2(40);
12407     l_return     BOOLEAN;
12408     l_cursor     INTEGER;
12409     l_error      VARCHAR2(10);
12410 
12411     CURSOR c_package_status IS
12412       SELECT status
12413       FROM   user_objects
12414       WHERE  object_name = UPPER(p_package_name)
12415       AND    object_type='PACKAGE'
12416       AND    status <> 'VALID'
12417       AND    rownum = 1;
12418 
12419     CURSOR c_package_body_status IS
12420       SELECT status
12421       FROM   user_objects
12422       WHERE  object_name = UPPER(p_package_name)
12423       AND    object_type = 'PACKAGE BODY'
12424       AND    status <> 'VALID'
12425       AND    rownum = 1;
12426 
12427   BEGIN
12428     x_return_status  := fnd_api.g_ret_sts_unexp_error;
12429     --open cursor
12430     l_cursor         := DBMS_SQL.open_cursor;
12431     --parse cursor
12432     DBMS_SQL.parse(l_cursor, g_build_package_tbl, 1, g_build_package_row, FALSE, DBMS_SQL.native);
12433     --close cursor
12434     DBMS_SQL.close_cursor(l_cursor);
12435 
12436     /* We may need to call this API for AOL standards
12437        --get schema info
12438        l_return := fnd_installation.get_app_info(
12439        application_short_name => 'FND'
12440       ,status => l_status
12441       ,industry => l_industry
12442       ,oracle_schema => l_schema
12443            );
12444        IF l_return = FALSE THEN
12445       RAISE fnd_api.g_exc_error;
12446        END IF;
12447 
12448        --Call create package
12449        ad_ddl.create_plsql_object(
12450       applsys_schema => l_schema
12451            ,application_short_name => 'WMS'
12452            ,object_name => p_package_name
12453            ,lb      => 1
12454            ,ub      => g_build_package_row
12455            ,insert_newlines => 'FALSE'
12456            ,comp_error => l_comp_error
12457            );
12458 
12459        IF l_comp_error = 'TRUE' THEN
12460       RAISE fnd_api.g_exc_error;
12461        END IF;
12462     */
12463        --Check status, return error if package that was created
12464        --  is invalid
12465     IF p_package_body THEN
12466       OPEN c_package_body_status;
12467       FETCH c_package_body_status INTO l_error;
12468 
12469       IF c_package_body_status%FOUND THEN
12470         x_return_status  := fnd_api.g_ret_sts_unexp_error;
12471       ELSE
12472         x_return_status  := fnd_api.g_ret_sts_success;
12473       END IF;
12474 
12475       CLOSE c_package_body_status;
12476     ELSE
12477       OPEN c_package_status;
12478       FETCH c_package_status INTO l_error;
12479 
12480       IF c_package_status%FOUND THEN
12481         x_return_status  := fnd_api.g_ret_sts_unexp_error;
12482       ELSE
12483         x_return_status  := fnd_api.g_ret_sts_success;
12484       END IF;
12485 
12486       CLOSE c_package_status;
12487     END IF;
12488   EXCEPTION
12489     WHEN OTHERS THEN
12490       x_return_status  := fnd_api.g_ret_sts_unexp_error;
12491   END createpackage;
12492 
12493   -- API name    : GenerateRulePackage
12494   -- Type        : Private
12495   -- Function    : generate a package for a rule that can be used in
12496   --      picking and put away
12497   -- Input Parameters  :
12498   --   p_api_version     Standard Input Parameter
12499   --   p_init_msg_list   Standard Input Parameter
12500   --   p_validation_level Standard Input Parameter
12501   --   p_rule_id         Identifier of the rule
12502   --
12503   -- Output Parameters:
12504   --   x_return_status   Standard Output Parameter
12505   --   x_msg_count       Standard Output Parameter
12506   --   x_msg_data        Standard Output Parameter
12507   --
12508   --  Called by the WMS Rules form (WMSRULEF.fmb), this function
12509   --  creates a package for the given rule.  The package has three
12510   --  functions, open_curs, fetch_one_row, and close_curs.  Open_curs
12511   --  opens the cursor used by picking/put away to find locations for
12512   --  transactions.  Fetch_one_row returns the next set of results from
12513   --  the cursor. Close_curs closes the cursor.  Much of this function is
12514   --  devoted to building the necessary cursors.  For picking, there are
12515   --  three cursors - one for detailing serials, one for serial controlled
12516   --  items when not detailing, and one for non-serial items.
12517   --  For put away, task type, label, and cost group rules,
12518   --  there is only one cursor
12519 
12520 
12521 
12522   PROCEDURE generaterulepackage(
12523     p_api_version      IN            NUMBER
12524   , p_init_msg_list    IN            VARCHAR2
12525   , p_validation_level IN            NUMBER
12526   , x_return_status    OUT NOCOPY    VARCHAR2
12527   , x_msg_count        OUT NOCOPY    NUMBER
12528   , x_msg_data         OUT NOCOPY    VARCHAR2
12529   , p_rule_id          IN            NUMBER
12530   ) IS
12531     -- API standard variables
12532     l_api_version CONSTANT NUMBER                                              := 1.0;
12533     l_api_name    CONSTANT VARCHAR2(30)                                        := 'GenerateRulePackage';
12534     --
12535     -- variables needed for dynamic SQL
12536     l_cursor               INTEGER;
12537     l_rows                 INTEGER;
12538     --
12539     -- rule dynamic SQL output variables
12540     l_revision             wms_transactions_temp.revision%TYPE;
12541     l_lot_number           wms_transactions_temp.lot_number%TYPE;
12542     l_lot_expiration_date  wms_transactions_temp.lot_expiration_date%TYPE;
12543     l_subinventory_code    wms_transactions_temp.from_subinventory_code%TYPE;
12544     l_locator_id           wms_transactions_temp.from_locator_id%TYPE;
12545     l_cost_group_id        wms_transactions_temp.from_cost_group_id%TYPE;
12546     l_possible_quantity    wms_transactions_temp.primary_quantity%TYPE;
12547     --
12548     -- other variables
12549     l_type_code            wms_rules_b.type_code%TYPE;
12550     l_package_name         VARCHAR2(128);
12551     l_pack_sql             VARCHAR2(32000);
12552     l_pack_body_sql        VARCHAR2(32000);
12553     --
12554     l_subinventory_where   VARCHAR2(100);
12555     l_locator_where        VARCHAR2(100);
12556     l_stmt                 LONG;
12557     l_allocation_mode_id   NUMBER;
12558 
12559     l_rest_sql             VARCHAR2(32000);
12560     -- cursor for validation of input parameters and pre-requisites
12561     CURSOR rule IS
12562       SELECT type_code
12563            , allocation_mode_id
12564         FROM wms_rules_b mpr
12565        WHERE mpr.rule_id = p_rule_id;
12566   --
12567   BEGIN
12568      --
12569     -- Standard call to check for call compatibility
12570     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
12571       RAISE fnd_api.g_exc_unexpected_error;
12572     END IF;
12573 
12574     --
12575     -- Initialize message list if p_init_msg_list is set to TRUE
12576     IF fnd_api.to_boolean(p_init_msg_list) THEN
12577       fnd_msg_pub.initialize;
12578     END IF;
12579 
12580     --
12581     -- Initialize API return status to success
12582     x_return_status  := fnd_api.g_ret_sts_success;
12583 
12584     log_procedure(l_api_name, 'start', 'Start GenerateRulePackage');
12585 
12586     -- end of debugging section
12587     --
12588     -- Validate input parameter, if validation level requires this
12589     IF p_validation_level <> fnd_api.g_valid_level_none THEN
12590       IF p_rule_id IS NULL
12591          OR p_rule_id = fnd_api.g_miss_num THEN
12592         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12593           fnd_message.set_name('WMS', 'WMS_RULE_ID_MISSING');
12594           log_error_msg(l_api_name, 'rule_id_missing');
12595           fnd_msg_pub.ADD;
12596         END IF;
12597 
12598         RAISE fnd_api.g_exc_error;
12599       END IF;
12600     END IF;
12601 
12602     --
12603     -- Get type code of the rule
12604     OPEN rule;
12605     FETCH rule INTO l_type_code, l_allocation_mode_id;
12606 
12607     IF rule%NOTFOUND THEN
12608       CLOSE rule;
12609       RAISE NO_DATA_FOUND;
12610     END IF;
12611 
12612     CLOSE rule;
12613     --
12614 
12615     -- clean up the global variables holding dynamic SQL text
12616     freeglobals;
12617 
12618     --
12619 
12620     /* For Task type rule (TTA) and label rule, calculate initial rule weight*/
12621     --  We don't want to pre-calculate rule weight any more, because
12622     --  of the uniqueness check on rule weight
12623     /*
12624     IF l_type_code = 3 OR l_type_code = 4 THEN
12625        calcRuleWeight(p_rule_id);
12626     END IF;
12627     */
12628 
12629 
12630 
12631     --For pick and put away rules, build the Base and Input portions
12632     -- of the SQL statement.  Not used in task type, label, and cost group
12633     -- rules
12634     IF l_type_code = 1
12635        OR l_type_code = 2 THEN
12636       -- Build the base part of the SQL statement
12637       buildbasesql(x_return_status, x_msg_count, x_msg_data, l_type_code, l_allocation_mode_id);
12638 
12639       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12640         RAISE fnd_api.g_exc_unexpected_error;
12641       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12642         RAISE fnd_api.g_exc_error;
12643       END IF;
12644 
12645       -- Build the input parameter dependent part of the SQL statement
12646       buildinputsql(x_return_status, x_msg_count, x_msg_data, l_type_code);
12647 
12648       --
12649       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12650         RAISE fnd_api.g_exc_unexpected_error;
12651       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12652         RAISE fnd_api.g_exc_error;
12653       END IF;
12654     END IF;
12655 
12656     -- Build the rule dependent part of the SQL statement.
12657     -- Happens for rules of all type
12658     buildrulesql(x_return_status, x_msg_count, x_msg_data, p_rule_id, l_type_code, l_allocation_mode_id);
12659 
12660     --
12661     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12662       RAISE fnd_api.g_exc_unexpected_error;
12663     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12664       RAISE fnd_api.g_exc_error;
12665     END IF;
12666 
12667     --
12668 
12669 
12670     --inv_pp_debug.send_long_to_pipe(g_base_from_serial);
12671 
12672     --build the sql portion of the cursor for lot-controlled items
12673     IF (l_type_code = 2) THEN --pick only
12674       g_stmt_serial         :=    'select '
12675                                || g_base_select
12676                                || g_rule_select_serial
12677                                || ' from '
12678                                || g_rule_from
12679                                || g_base_from_serial
12680                                || ' where '
12681                                || g_input_where
12682                                || g_rule_where
12683                                || ' group by '
12684                                || g_base_group_by
12685                                || g_rule_group_by;
12686 
12687       g_stmt_serial_validate :=    'select '
12688                                || g_base_select
12689                                || g_rule_select_serial
12690                                || ' from '
12691                                || g_rule_from
12692                                || g_base_from_serial_v
12693                                || ' where '
12694                                || g_input_where
12695                                || g_rule_where
12696                                || ' group by '
12697                                || g_base_group_by
12698                                || g_rule_group_by;
12699 
12700       g_stmt_serial_detail  :=    'select '
12701                                || g_base_select
12702                                || g_rule_select
12703                                || ' from '
12704                                || g_rule_from
12705                                || g_base_from_serial
12706                                || ' where '
12707                                || g_input_where
12708                                || g_rule_where;
12709 
12710      g_stmt_serial_detail_new  :=    'select '
12711                                || g_base_select
12712                                || g_rule_select
12713                                || ' from '
12714                                || g_rule_from
12715                                || g_base_from_serial_detail
12716                                || ' where '
12717                                || g_input_where
12718                                || g_rule_where;
12719 
12720       IF g_rule_order IS NOT NULL THEN
12721         g_stmt_serial           := g_stmt_serial || ' order by ' || g_rule_order;
12722         g_stmt_serial_validate  := g_stmt_serial_validate || ' order by ' || g_rule_order;
12723         g_stmt_serial_detail    := g_stmt_serial_detail || ' order by ' || g_rule_order;
12724         g_stmt_serial_detail_new := g_stmt_serial_detail_new || ' order by ' || g_rule_order;
12725       END IF;
12726     --    inv_pp_debug.send_long_to_pipe(g_stmt_serial);
12727     --    inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
12728 
12729     ELSE
12730       --if not pick, we don't need these cursors, so we set them to
12731       -- dummy values.  Used only so package will compile.
12732       g_stmt_serial          := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12733       g_stmt_serial_validate := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12734       g_stmt_serial_detail   := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12735       g_stmt_serial_detail_new   := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12736     END IF;
12737 
12738     --get the package name
12739     getpackagename(p_rule_id, l_package_name);
12740     -- Initialize the global variables needed to build package
12741     initbuildpackage;
12742 
12743     -- Generate Package for Label Rules
12744     IF (l_type_code = 4) THEN
12745       g_stmt           :=    'select count(*) '
12746                           || '  from '
12747                           || NVL(g_rule_from, 'WMS_LABEL_REQUESTS wlr')
12748                           || ' where wlr.label_request_id = p_label_request_id '
12749                           || g_rule_where;
12750       --assemble create package statement
12751       l_pack_sql       :=
12752              'CREATE OR REPLACE PACKAGE '
12753           || l_package_name
12754           || ' AS
12755                    procedure Get_label_format (
12756                    p_label_request_id           IN NUMBER,
12757                    x_return_status              OUT NOCOPY NUMBER);
12758 
12759                 end '
12760           || l_package_name
12761           || ';';
12762       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12763       --open cursor
12764       --l_cursor := dbms_sql.open_cursor;
12765       --parse cursor
12766       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12767       --close cursor
12768       --dbms_sql.close_cursor(l_cursor);
12769       buildpackage(l_pack_sql);
12770       --create the package spec
12771       createpackage(x_return_status, l_package_name, FALSE);
12772 
12773       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12774         RAISE fnd_api.g_exc_unexpected_error;
12775       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12776         RAISE fnd_api.g_exc_error;
12777       END IF;
12778 
12779       --re initialize global variables
12780       initbuildpackage;
12781       --inv_pp_debug.send_long_to_pipe(g_stmt);
12782 
12783       --assemble the dynamic package creation statment
12784       l_pack_body_sql  :=
12785              'CREATE OR REPLACE PACKAGE BODY '
12786           || l_package_name
12787           || ' AS
12788      PROCEDURE Get_Label_Format (
12789         p_label_request_id        IN NUMBER,
12790         x_return_status           OUT NOCOPY NUMBER) IS
12791 
12792         CURSOR get_label_rule_curs IS
12793      ';
12794       buildpackage(l_pack_body_sql);
12795       buildpackage(g_stmt);
12796       l_pack_body_sql  :=
12797              ';
12798 
12799   BEGIN
12800            x_return_status := 0;
12801            OPEN get_label_rule_curs;
12802            FETCH get_label_rule_curs into x_return_status;
12803            CLOSE get_label_rule_curs;
12804 
12805         END Get_Label_Format;
12806 
12807    END '
12808           || l_package_name
12809           || ';';
12810     ELSIF (l_type_code = 7) THEN
12811       -- Generate package for Operation Plan Rules
12812       g_stmt           :=    'select count(*) '
12813                           || '  from '
12814                           || NVL(g_rule_from, 'MTL_MATERIAL_TRANSACTIONS_TEMP mmtt')
12815                           || ' where mmtt.transaction_temp_id = p_pp_transaction_temp_id '
12816                           || g_rule_where;
12817       --assemble create package statement
12818       l_pack_sql       :=
12819              'CREATE OR REPLACE PACKAGE '
12820           || l_package_name
12821           || ' AS
12822                     procedure Get_OP (
12823                     p_pp_transaction_temp_id     IN NUMBER,
12824                     x_return_status              OUT NOCOPY NUMBER);
12825 
12826  end '
12827           || l_package_name
12828           || ';';
12829       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12830       --open cursor
12831       --l_cursor := dbms_sql.open_cursor;
12832       --parse cursor
12833       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12834       --close cursor
12835       --dbms_sql.close_cursor(l_cursor);
12836       buildpackage(l_pack_sql);
12837       createpackage(x_return_status, l_package_name, FALSE);
12838 
12839       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12840         RAISE fnd_api.g_exc_unexpected_error;
12841       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12842         RAISE fnd_api.g_exc_error;
12843       END IF;
12844 
12845       initbuildpackage;
12846       --inv_pp_debug.send_long_to_pipe(g_stmt);
12847 
12848       --assemble the dynamic package creation statment
12849       l_pack_body_sql  :=
12850              'CREATE OR REPLACE PACKAGE BODY '
12851           || l_package_name
12852           || ' AS
12853       PROCEDURE Get_OP (
12854           p_pp_transaction_temp_id IN  NUMBER,
12855           x_return_status          OUT NOCOPY NUMBER) IS
12856 
12857           CURSOR g_operation_plan_curs IS
12858        ';
12859       buildpackage(l_pack_body_sql);
12860       buildpackage(g_stmt);
12861       l_pack_body_sql  :=
12862              ';  -- for OP
12863 
12864        BEGIN
12865           x_return_status := 0;
12866           OPEN g_operation_plan_curs;
12867           FETCH g_operation_plan_curs  INTO x_return_status;
12868           CLOSE g_operation_plan_curs;
12869       END Get_OP;
12870 
12871 END '
12872           || l_package_name
12873           || ';';
12874     ELSIF (l_type_code = 3) THEN
12875       -- Generate package for Task Type Rules
12876       g_stmt           :=    'select count(*) '
12877                           || '  from '
12878                           || NVL(g_rule_from, 'MTL_MATERIAL_TRANSACTIONS_TEMP mmtt')
12879                           || ' where nvl(mmtt.parent_line_id,mmtt.transaction_temp_id) = p_pp_transaction_temp_id '  -- Bug Fix 5560849
12880                           || g_rule_where;
12881       --assemble create package statement
12882       l_pack_sql       :=
12883              'CREATE OR REPLACE PACKAGE '
12884           || l_package_name
12885           || ' AS
12886                 procedure Get_Task (
12887                    p_pp_transaction_temp_id     IN NUMBER,
12888                    x_return_status              OUT NOCOPY NUMBER);
12889 
12890  end '
12891           || l_package_name
12892           || ';';
12893       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12894       --open cursor
12895       --l_cursor := dbms_sql.open_cursor;
12896       --parse cursor
12897       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12898       --close cursor
12899       --dbms_sql.close_cursor(l_cursor);
12900       buildpackage(l_pack_sql);
12901       createpackage(x_return_status, l_package_name, FALSE);
12902 
12903       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12904         RAISE fnd_api.g_exc_unexpected_error;
12905       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12906         RAISE fnd_api.g_exc_error;
12907       END IF;
12908 
12909       initbuildpackage;
12910       --inv_pp_debug.send_long_to_pipe(g_stmt);
12911 
12912       --assemble the dynamic package creation statment
12913       l_pack_body_sql  :=
12914              'CREATE OR REPLACE PACKAGE BODY '
12915           || l_package_name
12916           || ' AS
12917      PROCEDURE Get_Task (
12918          p_pp_transaction_temp_id IN  NUMBER,
12919          x_return_status          OUT NOCOPY NUMBER) IS
12920 
12921          CURSOR g_task_type_curs IS
12922       ';
12923       buildpackage(l_pack_body_sql);
12924       buildpackage(g_stmt);
12925       l_pack_body_sql  :=
12926              ';  -- for TTA
12927 
12928       BEGIN
12929          x_return_status := 0;
12930          OPEN g_task_type_curs;
12931          FETCH g_task_type_curs INTO x_return_status;
12932          CLOSE g_task_type_curs;
12933       END Get_Task;
12934 
12935 END '
12936           || l_package_name
12937           || ';';
12938     -- Call CreatePackage after IF statement
12939 
12940     ELSIF (l_type_code = 5) THEN
12941       -- Build package for Cost Group Rules
12942       g_stmt           :=    'select count(*) '
12943                           || '  from '
12944                           || NVL(g_rule_from, 'WMS_COST_GROUPS_INPUT_V wcgiv')
12945                           || ' where wcgiv.line_id = g_line_id '
12946                           || g_rule_where;
12947       --assemble create package statement
12948       l_pack_sql       :=
12949              'CREATE OR REPLACE PACKAGE '
12950           || l_package_name
12951           || ' AS
12952 
12953                    PROCEDURE Get_CostGroup(
12954                        p_line_id        IN NUMBER,
12955                        x_return_status  OUT NOCOPY NUMBER);
12956 
12957     end '
12958           || l_package_name
12959           || ';';
12960       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12961       --open cursor
12962       --l_cursor := dbms_sql.open_cursor;
12963       --parse cursor
12964       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12965       --close cursor
12966       --dbms_sql.close_cursor(l_cursor);
12967       buildpackage(l_pack_sql);
12968       createpackage(x_return_status, l_package_name, FALSE);
12969 
12970       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12971         RAISE fnd_api.g_exc_unexpected_error;
12972       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12973         RAISE fnd_api.g_exc_error;
12974       END IF;
12975 
12976       initbuildpackage;
12977       --inv_pp_debug.send_long_to_pipe(g_stmt);
12978 
12979       --assemble the dynamic package creation statment
12980       l_pack_body_sql  :=
12981              'CREATE OR REPLACE PACKAGE BODY '
12982           || l_package_name
12983           || ' AS
12984          PROCEDURE Get_CostGroup(
12985                   p_line_id IN  NUMBER,
12986                   x_return_status OUT NOCOPY NUMBER) IS
12987 
12988            g_line_id  NUMBER;
12989 
12990                  CURSOR g_cursor_cost_group IS
12991                  ';
12992       buildpackage(l_pack_body_sql);
12993       buildpackage(g_stmt);
12994       l_pack_body_sql  :=
12995              ';
12996 
12997              BEGIN
12998                    g_line_id := p_line_id;
12999 
13000              OPEN g_cursor_cost_group;
13001 
13002              IF g_cursor_cost_group%isopen THEN
13003 
13004                 FETCH g_cursor_cost_group INTO
13005                 x_return_status;
13006 
13007              ELSE
13008                 x_return_status := 0;
13009              END IF;
13010 
13011              IF(g_cursor_cost_group%isopen) THEN
13012 
13013                 CLOSE g_cursor_cost_group;
13014 
13015              END IF;
13016 
13017               END Get_CostGroup;
13018   END '
13019           || l_package_name
13020           || ';';
13021     ELSIF l_type_code = 1 THEN
13022       -- Build for Put Away
13023       l_subinventory_where  := g_base_table_alias || '.subinventory_code = g_subinventory_code' || g_line_feed;
13024       l_locator_where       := g_base_table_alias || '.locator_id = g_locator_id' || g_line_feed;
13025       --build the sql portion of the cursor for non-serial-controlled items
13026        log_procedure(l_api_name, '=>', '*********************   200');
13027       g_stmt                :=
13028                               'select ' || g_base_select || ' from ' || g_rule_from || g_base_from || ' where ' || g_input_where || g_rule_where;
13029       --inv_pp_debug.send_long_to_pipe('g_base_from : ' || g_base_from);
13030 
13031      log_procedure(l_api_name, '=>', '*********************   199');
13032 
13033       --assemble create package statement
13034       l_pack_sql            :=
13035              'CREATE OR REPLACE PACKAGE '
13036           || l_package_name
13037           || ' AS
13038                    procedure open_curs (
13039                    p_cursor                     IN OUT NOCOPY WMS_RULE_PVT.CV_PUT_TYPE,
13040                    p_organization_id            IN NUMBER,
13041                    p_inventory_item_id          IN NUMBER,
13042        p_transaction_type_id        IN NUMBER,
13043                    p_subinventory_code          IN VARCHAR2,
13044                    p_locator_id                 IN NUMBER,
13045                    p_pp_transaction_temp_id     IN NUMBER,
13046        p_restrict_subs_code   IN NUMBER,
13047        p_restrict_locs_code   IN NUMBER,
13048        p_project_id     IN NUMBER,
13049        p_task_id      IN NUMBER,
13050                    x_result                     OUT NOCOPY NUMBER);
13051 
13052                    PROCEDURE fetch_one_row  (
13053                       p_cursor              IN  WMS_RULE_PVT.CV_PUT_TYPE,
13054                       x_subinventory_code   OUT NOCOPY VARCHAR2,
13055                       x_locator_id          OUT NOCOPY NUMBER,
13056                       x_project_id          OUT NOCOPY NUMBER,
13057                       x_task_id             OUT NOCOPY NUMBER,
13058                       x_return_status       OUT NOCOPY NUMBER);
13059 
13060                    PROCEDURE close_curs(p_cursor IN  WMS_RULE_PVT.CV_PUT_TYPE );
13061 
13062     end '
13063           || l_package_name
13064           || ';';
13065      log_procedure(l_api_name, '=>', '*********************   198');
13066       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
13067       --open cursor
13068       --l_cursor := dbms_sql.open_cursor;
13069       --parse cursor
13070       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
13071       --close cursor
13072       --dbms_sql.close_cursor(l_cursor);
13073       buildpackage(l_pack_sql);
13074       createpackage(x_return_status, l_package_name, FALSE);
13075 
13076       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13077         RAISE fnd_api.g_exc_unexpected_error;
13078       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13079         RAISE fnd_api.g_exc_error;
13080       END IF;
13081 
13082       initbuildpackage;
13083       --   inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
13084        --  inv_pp_debug.send_long_to_pipe(g_stmt_serial);
13085          --assemble the dynamic package creation statment
13086        log_procedure(l_api_name, '=>', '*********************  197');
13087       l_pack_body_sql       :=
13088              'CREATE OR REPLACE PACKAGE BODY '
13089           || l_package_name
13090           || ' AS
13091 
13092      PROCEDURE open_curs (
13093                 p_cursor                 IN OUT NOCOPY WMS_RULE_PVT.cv_put_type,
13094     p_organization_id   IN NUMBER,
13095     p_inventory_item_id   IN NUMBER,
13096     p_transaction_type_id   IN NUMBER,
13097     p_subinventory_code IN VARCHAR2,
13098     p_locator_id    IN NUMBER,
13099     p_pp_transaction_temp_id IN NUMBER,
13100     p_restrict_subs_code  IN NUMBER,
13101     p_restrict_locs_code  IN NUMBER,
13102     p_project_id    IN NUMBER,
13103     p_task_id   IN NUMBER,
13104     x_result    OUT NOCOPY NUMBER) IS
13105 
13106                 g_organization_id           NUMBER;
13107                 g_inventory_item_id         NUMBER;
13108                 g_transaction_type_id       NUMBER;
13109                 g_subinventory_code         VARCHAR2(10);
13110                 g_locator_id                NUMBER;
13111                 g_pp_transaction_temp_id    NUMBER;
13112                 g_restrict_subs_code        NUMBER;
13113                 g_restrict_locs_code        NUMBER;
13114     g_project_id                NUMBER;
13115     g_task_id                   NUMBER;
13116 
13117     BEGIN
13118     g_organization_id :=p_organization_id;
13119     g_inventory_item_id := p_inventory_item_id;
13120     g_transaction_type_id := p_transaction_type_id;
13121           IF p_subinventory_code = ''-9999'' THEN
13122       g_subinventory_code := NULL;
13123     ELSE
13124       g_subinventory_code := p_subinventory_code;
13125     END IF;
13126           IF p_locator_id = -9999 THEN
13127       g_locator_id := NULL;
13128     ELSE
13129       g_locator_id := p_locator_id;
13130     END IF;
13131     g_pp_transaction_temp_id := p_pp_transaction_temp_id;
13132     g_restrict_subs_code := p_restrict_subs_code;
13133     g_restrict_locs_code := p_restrict_locs_code;
13134     g_project_id := p_project_id;
13135     g_task_id := p_task_id;
13136 
13137     --if no restrictions
13138     IF g_restrict_subs_code = 2 AND
13139        g_restrict_locs_code = 2 THEN
13140 
13141       If g_subinventory_code IS NULL Then
13142       --if nothing passed, OPEN c_no_restrict_no_passed;
13143 
13144         OPEN p_cursor FOR ';
13145       buildpackage(l_pack_body_sql);
13146       --build correct statement
13147       log_procedure(l_api_name, '=>', '*********************   1961');
13148       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
13149       log_procedure(l_api_name, '=> Lenght ', length(l_stmt));
13150       l_rest_sql := l_stmt;
13151       log_procedure(l_api_name, '=> Lenght ', length(l_stmt));
13152       log_procedure(l_api_name, '=>_rest_sql', l_rest_sql);
13153       IF g_rule_order IS NOT NULL THEN
13154         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13155       END IF;
13156        log_procedure(l_api_name, '=>', '*********************   1963');
13157 
13158       buildpackage(l_stmt);
13159        log_procedure(l_api_name, '=>', '*********************   1964');
13160       l_pack_body_sql       :=
13161           ';
13162 
13163       Elsif g_locator_id IS NULL Then
13164 
13165       --if only subinventory passed , OPEN c_no_restrict_sub_passed;
13166 
13167         OPEN p_cursor FOR ';
13168       buildpackage(l_pack_body_sql);
13169       --build correct statement
13170        log_procedure(l_api_name, '=>', '*********************   195');
13171       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
13172       l_stmt                := l_stmt || ' and ' || l_subinventory_where;
13173        log_procedure(l_api_name, '=>', '*********************   194');
13174       IF g_rule_order IS NOT NULL THEN
13175         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13176       END IF;
13177 
13178       buildpackage(l_stmt);
13179       l_pack_body_sql       :=
13180           ';
13181 
13182       Else
13183       --if subinventory and locator passed, OPEN c_no_restrict_loc_passed;
13184         OPEN p_cursor FOR ';
13185       buildpackage(l_pack_body_sql);
13186       --build correct statement
13187       log_procedure(l_api_name, '=>', '*********************   99');
13188       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
13189       log_procedure(l_api_name, '=>', '*********************   98');
13190       l_stmt                := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
13191       log_procedure(l_api_name, '=>', '*********************   97');
13192       IF g_rule_order IS NOT NULL THEN
13193         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13194       END IF;
13195 
13196       buildpackage(l_stmt);
13197       l_pack_body_sql       :=
13198           ';
13199       End If;
13200     ELSIF g_restrict_locs_code = 2 THEN
13201       If g_subinventory_code IS NULL Then
13202       --if nothing passed, OPEN c_sub_restrict_no_passed;
13203         OPEN p_cursor FOR ';
13204       buildpackage(l_pack_body_sql);
13205       --build correct statement
13206       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
13207 
13208       IF g_rule_order IS NOT NULL THEN
13209         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13210       END IF;
13211 
13212       buildpackage(l_stmt);
13213       l_pack_body_sql       :=
13214           ';
13215       Elsif g_locator_id IS NULL Then
13216       --if only subinventory passed, OPEN c_sub_restrict_sub_passed;
13217          OPEN p_cursor FOR ';
13218       buildpackage(l_pack_body_sql);
13219       --build correct statement
13220       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
13221       l_stmt                := l_stmt || ' and ' || l_subinventory_where;
13222 
13223       IF g_rule_order IS NOT NULL THEN
13224         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13225       END IF;
13226 
13227       buildpackage(l_stmt);
13228       l_pack_body_sql       :=
13229               ';
13230 
13231       Else
13232       --if subinventory and locator passed, OPEN c_sub_restrict_loc_passed;
13233         OPEN p_cursor FOR ';
13234       buildpackage(l_pack_body_sql);
13235       --build correct statement
13236       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
13237       l_stmt                := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
13238 
13239       IF g_rule_order IS NOT NULL THEN
13240         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13241       END IF;
13242 
13243       buildpackage(l_stmt);
13244       l_pack_body_sql       :=
13245           ';
13246       End If;
13247     ELSE
13248       If g_subinventory_code IS NULL Then
13249       --if nothing passed, OPEN c_loc_restrict_no_passed;
13250         OPEN p_cursor FOR ';
13251       buildpackage(l_pack_body_sql);
13252       --build correct statement
13253       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
13254 
13255       IF g_rule_order IS NOT NULL THEN
13256         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13257       END IF;
13258 
13259       buildpackage(l_stmt);
13260       l_pack_body_sql       :=
13261           ';
13262 
13263       Elsif g_locator_id IS NULL Then
13264       --if only subinventory passed,OPEN c_loc_restrict_sub_passed;
13265         OPEN p_cursor FOR ';
13266       buildpackage(l_pack_body_sql);
13267       --build correct statement
13268       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
13269       l_stmt                := l_stmt || ' and ' || l_subinventory_where;
13270 
13271       IF g_rule_order IS NOT NULL THEN
13272         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13273       END IF;
13274 
13275       buildpackage(l_stmt);
13276       l_pack_body_sql       :=
13277               ';
13278 
13279       Else
13280       --if subinventory and locator passed, OPEN c_loc_restrict_loc_passed;
13281         OPEN p_cursor FOR ';
13282       buildpackage(l_pack_body_sql);
13283       --build correct statement
13284       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
13285       l_stmt                := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
13286 
13287       IF g_rule_order IS NOT NULL THEN
13288         l_stmt  := l_stmt || ' order by ' || g_rule_order;
13289       END IF;
13290 
13291       buildpackage(l_stmt);
13292       l_pack_body_sql       :=
13293              ';
13294       End If;
13295     END IF;
13296 
13297     x_result :=1;
13298 
13299    END open_curs;
13300 
13301    PROCEDURE fetch_one_row(
13302                         p_cursor  IN WMS_RULE_PVT.cv_put_type,
13303       x_subinventory_code OUT NOCOPY VARCHAR2,
13304       x_locator_id OUT NOCOPY NUMBER,
13305       x_project_id OUT NOCOPY NUMBER,
13306       x_task_id OUT NOCOPY NUMBER,
13307       x_return_status OUT NOCOPY NUMBER) IS
13308 
13309 
13310    BEGIN
13311       if p_cursor%ISOPEN then
13312          FETCH p_cursor INTO
13313                x_subinventory_code, x_locator_id, x_project_id, x_task_id;
13314           IF p_cursor%FOUND THEN
13315                 x_return_status := 1;
13316           ELSE
13317                x_return_status := 0;
13318           END IF;
13319       else
13320               x_return_status := 0;
13321       end if;
13322 
13323    END fetch_one_row;
13324 
13325    PROCEDURE close_curs( p_cursor  IN WMS_RULE_PVT.cv_put_type) IS
13326    BEGIN
13327        if p_cursor%ISOPEN then
13328            CLOSE p_cursor;
13329          end if;
13330    END close_curs;
13331 
13332    END '
13333           || l_package_name
13334           || ';';
13335     ELSE
13336       -- Build for Pick
13337       IF l_allocation_mode_id IN (1, 2) THEN
13338         --build the sql portion of the cursor for non-serial-controlled items
13339         g_stmt  :=
13340              'select ' || g_base_select || g_rule_select || ' from ' || g_rule_from || g_base_from || ' where ' || g_input_where || g_rule_where;
13341       --Ensures that we only get one rec per rev/lot/sub/loc, grouping
13342       -- all recs together regardless of LPN
13343       -- l_allocation_mode_id IN (3,4)
13344       ELSE
13345         g_stmt  :=    'select '
13346                    || g_base_select
13347                    || g_rule_select_serial
13348                    || ' from '
13349                    || g_rule_from
13350                    || g_base_from
13351                    || ' where '
13352                    || g_input_where
13353                    || g_rule_where
13354                    || 'group by '
13355                    || g_base_group_by
13356                    || g_rule_group_by;
13357       END IF;
13358 
13359       --inv_pp_debug.send_long_to_pipe('g_base_from : ' || g_base_from);
13360 
13361       IF g_rule_order IS NOT NULL THEN
13362         g_stmt  := g_stmt || ' order by ' || g_rule_order;
13363       END IF;
13364 
13365       --assemble create package statement
13366       l_pack_sql       :=
13367              'CREATE OR REPLACE PACKAGE '
13368           || l_package_name
13369           || ' AS
13370                    procedure open_curs (
13371                    p_cursor            IN OUT NOCOPY WMS_RULE_PVT.cv_pick_type,
13372                    p_organization_id            IN NUMBER,
13373                    p_inventory_item_id          IN NUMBER,
13374                    p_transaction_type_id        IN NUMBER,
13375                    p_revision                   IN VARCHAR2,
13376                    p_lot_number                 IN VARCHAR2,
13377                    p_subinventory_code          IN VARCHAR2,
13378                    p_locator_id                 IN NUMBER,
13379                    p_cost_group_id          IN NUMBER,
13380                    p_pp_transaction_temp_id     IN NUMBER,
13381                    p_serial_controlled    IN NUMBER,
13382                    p_detail_serial    IN NUMBER,
13383                    p_detail_any_serial    IN NUMBER,
13384                    p_from_serial_number   IN VARCHAR2,
13385                    p_to_serial_number   IN VARCHAR2,
13386                    p_unit_number    IN VARCHAR2,
13387                    p_lpn_id     IN NUMBER,
13388                    p_project_id     IN NUMBER,
13389                    p_task_id      IN NUMBER,
13390                    x_result                     OUT NOCOPY NUMBER);
13391 
13392                    PROCEDURE fetch_one_row  (
13393                       p_cursor                 IN WMS_RULE_PVT.cv_pick_type,
13394                       x_revision               OUT NOCOPY VARCHAR2,
13395                       x_lot_number             OUT NOCOPY VARCHAR2,
13396                       x_lot_expiration_date    OUT NOCOPY DATE,
13397                       x_subinventory_code      OUT NOCOPY VARCHAR2,
13398                       x_locator_id             OUT NOCOPY NUMBER,
13399                       x_cost_group_id          OUT NOCOPY NUMBER,
13400                       x_uom_code               OUT NOCOPY VARCHAR2,
13401                       x_lpn_id                 OUT NOCOPY NUMBER,
13402                       x_serial_number          OUT NOCOPY VARCHAR2,
13403                       x_possible_quantity      OUT NOCOPY NUMBER,
13404                       x_sec_possible_quantity  OUT NOCOPY NUMBER,
13405                       x_grade_code             OUT NOCOPY VARCHAR2,
13406                       x_consist_string         OUT NOCOPY VARCHAR2,
13407                       x_order_by_string        OUT NOCOPY VARCHAR2,
13408                       x_return_status          OUT NOCOPY NUMBER);
13409 
13410             PROCEDURE close_curs( p_cursor  IN WMS_RULE_PVT.cv_pick_type);
13411 
13412             PROCEDURE fetch_available_rows  (
13413                       p_cursor              IN WMS_RULE_PVT.cv_pick_type,
13414                       x_return_status       OUT NOCOPY NUMBER);
13415 
13416 
13417 
13418     end '
13419           || l_package_name
13420           || ';';
13421       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
13422       --open cursor
13423       --l_cursor := dbms_sql.open_cursor;
13424       --parse cursor
13425       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
13426       --close cursor
13427       --dbms_sql.close_cursor(l_cursor);
13428       buildpackage(l_pack_sql);
13429       createpackage(x_return_status, l_package_name, FALSE);
13430 
13431       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13432         RAISE fnd_api.g_exc_unexpected_error;
13433       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13434         RAISE fnd_api.g_exc_error;
13435       END IF;
13436 
13437       initbuildpackage;
13438       --   inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
13439        --  inv_pp_debug.send_long_to_pipe(g_stmt_serial);
13440          --assemble the dynamic package creation statment
13441 
13442       l_pack_body_sql  :=
13443              'CREATE OR REPLACE PACKAGE BODY '
13444           || l_package_name
13445           || ' AS
13446 
13447      PROCEDURE open_curs
13448         (
13449                 p_cursor                IN OUT NOCOPY WMS_RULE_PVT.cv_pick_type,
13450                 p_organization_id   IN NUMBER,
13451                 p_inventory_item_id   IN NUMBER,
13452                 p_transaction_type_id   IN NUMBER,
13453                 p_revision    IN VARCHAR2,
13454                 p_lot_number    IN VARCHAR2,
13455                 p_subinventory_code IN VARCHAR2,
13456                 p_locator_id    IN NUMBER,
13457                 p_cost_group_id   IN NUMBER,
13458                 p_pp_transaction_temp_id IN NUMBER,
13459                 p_serial_controlled IN NUMBER,
13460                 p_detail_serial   IN NUMBER,
13461                 p_detail_any_serial IN NUMBER,
13462                 p_from_serial_number  IN VARCHAR2,
13463                 p_to_serial_number  IN VARCHAR2,
13464                 p_unit_number   IN VARCHAR2,
13465                 p_lpn_id    IN NUMBER,
13466                 p_project_id    IN NUMBER,
13467                 p_task_id   IN NUMBER,
13468                 x_result    OUT NOCOPY NUMBER
13469         ) IS
13470                 g_organization_id             NUMBER;
13471                 g_inventory_item_id           NUMBER;
13472                 g_transaction_type_id         NUMBER;
13473                 g_revision                    VARCHAR2(3);
13474                 g_lot_number                  VARCHAR2(80);
13475                 g_subinventory_code           VARCHAR2(10);
13476                 g_locator_id                  NUMBER;
13477                 g_cost_group_id               NUMBER;
13478                 g_pp_transaction_temp_id      NUMBER;
13479                 g_serial_control              NUMBER;
13480                 g_detail_serial               NUMBER;
13481                 g_detail_any_serial           NUMBER;
13482                 g_from_serial_number          VARCHAR2(30);
13483                 g_to_serial_number            VARCHAR2(30);
13484                 g_unit_number                 VARCHAR2(30);
13485                 g_lpn_id                      NUMBER;
13486                 g_project_id                  NUMBER;
13487                 g_task_id                     NUMBER;
13488 
13489 
13490     BEGIN
13491       g_organization_id :=p_organization_id;
13492       g_inventory_item_id := p_inventory_item_id;
13493       g_transaction_type_id := p_transaction_type_id;
13494       g_revision := p_revision;
13495       g_lot_number := p_lot_number;
13496       g_subinventory_code :=p_subinventory_code;
13497       g_locator_id := p_locator_id;
13498       g_cost_group_id := p_cost_group_id;
13499       g_pp_transaction_temp_id := p_pp_transaction_temp_id;
13500       g_serial_control:= p_serial_controlled;
13501       g_detail_serial := p_detail_serial;
13502       g_detail_any_serial := p_detail_any_serial;
13503       g_from_serial_number := p_from_serial_number;
13504       g_to_serial_number := p_to_serial_number;
13505       g_unit_number := p_unit_number;
13506       g_lpn_id := p_lpn_id;
13507       g_project_id := p_project_id;
13508       g_task_id := p_task_id;
13509 
13510      IF (g_serial_control = 1)    AND (g_detail_serial in (1,2)) THEN
13511          OPEN p_cursor FOR ';
13512               buildpackage(l_pack_body_sql);
13513               buildpackage(g_stmt_serial_detail_new);
13514               l_pack_body_sql  := ';
13515      Elsif (g_serial_control = 1) AND (g_detail_serial = 3) THEN
13516         OPEN p_cursor FOR ';
13517              buildpackage(l_pack_body_sql);
13518              buildpackage(g_stmt_serial_validate);
13519              l_pack_body_sql  := ';
13520      Elsif (g_serial_control = 1) AND  (g_detail_serial = 4) THEN
13521            OPEN p_cursor FOR ';
13522                 buildpackage(l_pack_body_sql);
13523                 buildpackage(g_stmt_serial);
13524                 l_pack_body_sql  := ';
13525 
13526      Elsif ((g_serial_control <> 1) OR (g_detail_serial = 0)) THEN
13527        OPEN p_cursor FOR ';
13528         buildpackage(l_pack_body_sql);
13529         buildpackage(g_stmt);
13530         l_pack_body_sql  :=
13531              ';
13532      END IF;
13533 
13534     x_result :=1;
13535 
13536    END open_curs;
13537 
13538    PROCEDURE fetch_one_row(
13539                         p_cursor   IN WMS_RULE_PVT.cv_pick_type,
13540                         x_revision OUT NOCOPY VARCHAR2,
13541                         x_lot_number OUT NOCOPY VARCHAR2,
13542                         x_lot_expiration_date OUT NOCOPY DATE,
13543                         x_subinventory_code OUT NOCOPY VARCHAR2,
13544                         x_locator_id OUT NOCOPY NUMBER,
13545                         x_cost_group_id OUT NOCOPY NUMBER,
13546                         x_uom_code OUT NOCOPY VARCHAR2,
13547                         x_lpn_id OUT NOCOPY NUMBER,
13548                         x_serial_number OUT NOCOPY VARCHAR2,
13549                         x_possible_quantity OUT NOCOPY NUMBER,
13550                         x_sec_possible_quantity  OUT NOCOPY NUMBER,
13551                         x_grade_code             OUT NOCOPY VARCHAR2,
13552                         x_consist_string  OUT NOCOPY VARCHAR2,
13553                         x_order_by_string OUT NOCOPY VARCHAR2,
13554                         x_return_status OUT NOCOPY NUMBER) IS
13555 
13556 
13557    BEGIN
13558            IF (p_cursor%ISOPEN) THEN
13559 
13560                FETCH p_cursor INTO
13561                x_revision
13562                , x_lot_number
13563                , x_lot_expiration_date
13564                , x_subinventory_code
13565                , x_locator_id
13566                , x_cost_group_id
13567                , x_uom_code
13568                , x_lpn_id
13569                , x_serial_number
13570                , x_possible_quantity
13571                , x_sec_possible_quantity
13572                , x_grade_code
13573                , x_consist_string
13574                , x_order_by_string;
13575                IF p_cursor%FOUND THEN
13576                   x_return_status :=1;
13577                ELSE
13578                   x_return_status :=0;
13579                END IF;
13580             ELSE
13581                x_return_status:=0;
13582             END IF;
13583 
13584 
13585    END fetch_one_row;
13586 
13587    PROCEDURE close_curs( p_cursor IN WMS_RULE_PVT.cv_pick_type) IS
13588    BEGIN
13589         if (p_cursor%ISOPEN) THEN
13590             CLOSE p_cursor;
13591         END IF;
13592    END close_curs;
13593 
13594    -- LG convergence new procedure for the new manual picking select screen
13595    PROCEDURE fetch_available_rows(
13596       p_cursor   IN WMS_RULE_PVT.cv_pick_type,
13597       x_return_status OUT NOCOPY NUMBER) IS
13598 
13599 
13600    BEGIN
13601            IF (p_cursor%ISOPEN) THEN
13602 
13603                FETCH p_cursor bulk collect INTO
13604                  WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl;
13605                IF p_cursor%FOUND THEN
13606                   x_return_status :=1;
13607                ELSE
13608                   x_return_status :=0;
13609                END IF;
13610             ELSE
13611                x_return_status:=0;
13612             END IF;
13613 
13614 
13615    END fetch_available_rows;
13616 
13617    -- end LG convergence
13618 
13619    END '
13620           || l_package_name
13621           || ';';
13622     END IF; -- type_code = 4
13623 
13624     -- Add last part of SQL to the global table, then call
13625     --  CreatePackage to generate package body
13626     buildpackage(l_pack_body_sql);
13627     createpackage(x_return_status, l_package_name, TRUE);
13628 
13629     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13630       RAISE fnd_api.g_exc_unexpected_error;
13631     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13632       RAISE fnd_api.g_exc_error;
13633     END IF;
13634 
13635     initbuildpackage;
13636      -- inv_pp_debug.send_long_to_pipe(l_pack_body_sql);
13637     /*
13638       --open cursor
13639 
13640       l_cursor := dbms_sql.open_cursor;
13641       dbms_out
13642       --parse cursor
13643 
13644       dbms_sql.parse(l_cursor, l_pack_body_sql, dbms_sql.native);
13645 
13646       --close cursor
13647       dbms_sql.close_cursor(l_cursor);
13648     */
13649 
13650 
13651 
13652     --
13653     -- clean up everything again
13654     freeglobals;
13655 
13656     --
13657 
13658     /*
13659     IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_success) THEN
13660         fnd_message.set_name('WMS','WMS_SYNTAX_CHECK_SUCCESS');
13661         fnd_msg_pub.add;
13662       END IF;
13663     */ --
13664     -- end of debugging section
13665     log_procedure(l_api_name, 'end', 'End GenerateRulePackage');
13666   --
13667   EXCEPTION
13668     WHEN fnd_api.g_exc_error THEN
13669       --
13670       -- debugging portion
13671       -- can be commented ut for final code
13672       IF inv_pp_debug.is_debug_mode THEN
13673         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
13674         -- the message retrieved here since it is no longer on the stack
13675         inv_pp_debug.set_last_error_message(SQLERRM);
13676         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
13677         inv_pp_debug.send_last_error_message;
13678       END IF;
13679 
13680       -- end of debugging section
13681       --
13682       IF DBMS_SQL.is_open(l_cursor) THEN
13683         DBMS_SQL.close_cursor(l_cursor);
13684       END IF;
13685 
13686       freeglobals;
13687       x_return_status  := fnd_api.g_ret_sts_error;
13688       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13689       log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
13690     --
13691     WHEN fnd_api.g_exc_unexpected_error THEN
13692       --
13693       -- debugging portion
13694       -- can be commented ut for final code
13695       IF inv_pp_debug.is_debug_mode THEN
13696         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
13697         -- the message retrieved here since it is no longer on the stack
13698         inv_pp_debug.set_last_error_message(SQLERRM);
13699         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
13700         inv_pp_debug.send_last_error_message;
13701       END IF;
13702 
13703       -- end of debugging section
13704       --
13705       IF DBMS_SQL.is_open(l_cursor) THEN
13706         DBMS_SQL.close_cursor(l_cursor);
13707       END IF;
13708 
13709       freeglobals;
13710       fnd_message.set_name('WMS', 'WMS_PACKAGE_GEN_FAILED');
13711       fnd_msg_pub.ADD;
13712       x_return_status  := fnd_api.g_ret_sts_unexp_error;
13713       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13714       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
13715     --
13716     WHEN OTHERS THEN
13717       --
13718       -- debugging portion
13719       -- can be commented ut for final code
13720       IF inv_pp_debug.is_debug_mode THEN
13721         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
13722         -- the message retrieved here since it is no longer on the stack
13723         inv_pp_debug.set_last_error_message(SQLERRM);
13724         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
13725         inv_pp_debug.send_last_error_message;
13726       END IF;
13727 
13728       -- end of debugging section
13729       --
13730       IF rule%ISOPEN THEN
13731         CLOSE rule;
13732       END IF;
13733 
13734       IF DBMS_SQL.is_open(l_cursor) THEN
13735         DBMS_SQL.close_cursor(l_cursor);
13736       END IF;
13737 
13738       freeglobals;
13739       fnd_message.set_name('WMS', 'WMS_PACKAGE_GEN_FAILED');
13740       fnd_msg_pub.ADD;
13741       x_return_status  := fnd_api.g_ret_sts_unexp_error;
13742 
13743       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
13744         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
13745       END IF;
13746 
13747       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13748       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
13749   --
13750   END generaterulepackage;
13751 
13752   -- API name    : Assign_operation_plans
13753   -- Type        : Private
13754   -- Function    : Assign operation plans to records in MMTT
13755   -- Input Parameters  :
13756   --
13757   -- Output Parameters:
13758   -- Version     :
13759   --   Current version 1.0
13760   --
13761   -- Notes       : calls Assign_operation_plan(p_task_id NUMBER)
13762   --
13763   -- This procedure loops through mtl_material_transactions_temp table, assign
13764   -- user defined operation plans to tasks that have not been assigned a operation_plan
13765   -- for the given Move Order Header.
13766   --
13767 
13768 
13769   PROCEDURE assign_operation_plans(
13770     p_api_version          IN            NUMBER
13771   , p_init_msg_list        IN            VARCHAR2
13772   , p_commit               IN            VARCHAR2
13773   , p_validation_level     IN            NUMBER
13774   , x_return_status        OUT NOCOPY    VARCHAR2
13775   , x_msg_count            OUT NOCOPY    NUMBER
13776   , x_msg_data             OUT NOCOPY    VARCHAR2
13777   , p_move_order_header_id IN            NUMBER
13778   ) IS
13779     CURSOR c_tasks IS
13780       SELECT mmtt.transaction_temp_id
13781         FROM mtl_material_transactions_temp mmtt, mtl_txn_request_lines mol
13782        WHERE mmtt.operation_plan_id IS NULL
13783          AND mmtt.move_order_line_id = mol.line_id
13784          AND mol.header_id = p_move_order_header_id;
13785 
13786     l_task_id       NUMBER;
13787     l_return_status VARCHAR2(1);
13788     l_msg_count     NUMBER;
13789     l_msg_data      VARCHAR2(2000);
13790     l_api_name      VARCHAR2(30)   := 'assign_operation_plans';
13791     l_count         NUMBER;
13792   BEGIN
13793     -- Initialize API return status to success
13794     x_return_status  := fnd_api.g_ret_sts_success;
13795 
13796     -- Bug# 4587423
13797     -- See if there are any enabled rules for Operation Plan Selection.
13798     l_count := 0;
13799     BEGIN
13800        SELECT 1 INTO l_count
13801 	 FROM dual
13802 	 WHERE EXISTS (SELECT 1 FROM wms_rules_b rules
13803 		       WHERE  rules.type_code = 7
13804 		       AND    rules.enabled_flag = 'Y'
13805 		       AND    (organization_id = -1
13806 			       OR organization_id IN (SELECT mmtt.organization_id
13807 						      FROM mtl_material_transactions_temp mmtt,
13808 						      mtl_txn_request_lines mol
13809 						      WHERE mmtt.standard_operation_id IS NULL
13810 						      AND mmtt.move_order_line_id = mol.line_id
13811 						      AND mol.header_id = p_move_order_header_id)));
13812     EXCEPTION
13813        WHEN OTHERS THEN
13814 	  l_count := 0;
13815     END;
13816 
13817     -- Bug# 4587423
13818     -- If there is at least one operation plan selection rule enabled,
13819     -- go through the existing logic.
13820     IF (l_count > 0) THEN
13821        OPEN c_tasks;
13822        LOOP
13823 	  FETCH c_tasks INTO l_task_id;
13824 	  EXIT WHEN c_tasks%NOTFOUND;
13825 
13826 	  if (inv_control.g_current_release_level >= inv_release.g_j_release_level
13827 	      and  wms_ui_tasks_apis.g_wms_patch_level >= wms_ui_tasks_apis.g_patchset_j)
13828 	    then
13829 	     -- ### Outbound for patchset 'J'
13830 	     wms_rule_pvt_ext_psetj.assign_operation_plan_psetj
13831 	       (p_api_version      => 1.0,
13832 		x_return_status    => l_return_status,
13833 		x_msg_count        => l_msg_count,
13834 		x_msg_data         => l_msg_data,
13835 		p_task_id          => l_task_id
13836 		);
13837 	   elsif (inv_control.g_current_release_level < inv_release.g_j_release_level
13838 		  or wms_ui_tasks_apis.g_wms_patch_level < wms_ui_tasks_apis.g_patchset_j)
13839 	     then
13840 	     -- ### Outbound for patchset 'I'
13841 	     assign_operation_plan
13842 	       (p_api_version      => 1.0,
13843 		p_task_id          => l_task_id,
13844 		x_return_status    => l_return_status,
13845 		x_msg_count        => l_msg_count,
13846 		x_msg_data         => l_msg_data
13847 		);
13848 	  end if;
13849 
13850 	  IF l_return_status <> fnd_api.g_ret_sts_success THEN
13851 	     x_return_status  := fnd_api.g_ret_sts_error;
13852 	  END IF;
13853        END LOOP;
13854 
13855        CLOSE c_tasks;
13856      ELSE
13857        -- Bug# 4587423
13858        -- No rules exist for outbound operaton plan selection.
13859        -- Just stamp the org default outbound operation plan or the default
13860        -- "Locator and LPN Based Consolidation in Staging Lane" seeded outbound operation plan
13861        -- for the MMTT records associated with the move order header.
13862        UPDATE mtl_material_transactions_temp mmtt
13863 	 SET mmtt.operation_plan_id = (SELECT NVL(default_pick_op_plan_id, 1)
13864 				       FROM mtl_parameters mp
13865 				       WHERE mp.organization_id = mmtt.organization_id)
13866 	 WHERE mmtt.operation_plan_id IS NULL
13867 	   AND mmtt.move_order_line_id IN (SELECT line_id
13868 					   FROM mtl_txn_request_lines mol
13869 					   WHERE mol.header_id = p_move_order_header_id)
13870 	   AND mmtt.transaction_source_type_id in (2, 8);
13871     END IF;
13872 
13873   EXCEPTION
13874      WHEN OTHERS THEN
13875 	x_return_status  := fnd_api.g_ret_sts_unexp_error;
13876   END assign_operation_plans;
13877 
13878   --
13879   -- API name    : Assign Operation Plan
13880   -- Type        : Private
13881   -- Function    : Assign Operation plan to a specific record in MMTT
13882   -- Input Parameters  :
13883   --           p_task_id NUMBER
13884   --
13885   -- Output Parameters:
13886   -- Version     :
13887   --   Current version 1.0
13888   --
13889   -- Notes       :
13890   --
13891   -- This procedure assign user defined operation plan to a specific task in
13892   -- mtl_material_transactions_temp. Operation plan is implemeted by WMS rules.
13893   -- This procedure calls the rule package created for operation plan rules to check
13894   -- which operation plan rule actually matches the task in question.
13895 
13896 
13897   PROCEDURE assign_operation_plan(
13898     p_api_version      IN            NUMBER
13899   , p_init_msg_list    IN            VARCHAR2
13900   , p_commit           IN            VARCHAR2
13901   , p_validation_level IN            NUMBER
13902   , x_return_status    OUT NOCOPY    VARCHAR2
13903   , x_msg_count        OUT NOCOPY    NUMBER
13904   , x_msg_data         OUT NOCOPY    VARCHAR2
13905   , p_task_id          IN            NUMBER
13906   ) IS
13907     l_rule_id              NUMBER;
13908     l_pack_exists          NUMBER;
13909     l_package_name         VARCHAR2(30);
13910     l_count                NUMBER;
13911     l_return_status        NUMBER;
13912     l_found                BOOLEAN      := FALSE;
13913     l_organization_id      NUMBER;
13914     l_wms_task_type        NUMBER;
13915     l_operation_plan_id    NUMBER;
13916     l_api_version CONSTANT NUMBER       := 1.0;
13917     l_api_name    CONSTANT VARCHAR2(30) := 'Assign_operation_plan';
13918 
13919     -- Cursor for task type rule loop
13920     -- Only rules with the same WMS system task type as the task
13921     -- will be selected
13922     -- Rules are ordered by rule weight and creation date
13923 
13924     CURSOR c_rules IS
13925       SELECT   rules.rule_id
13926              , mmtt.organization_id
13927              , mmtt.wms_task_type
13928              , rules.type_hdr_id
13929           FROM wms_rules_b rules, wms_op_plans_b wop, mtl_material_transactions_temp mmtt
13930 	WHERE rules.type_code = 7
13931 	AND rules.enabled_flag = 'Y'
13932 	AND rules.type_hdr_id = wop.operation_plan_id
13933 	AND wop.system_task_type = NVL(mmtt.wms_task_type, wop.system_task_type)
13934 	--AND    mmtt.transaction_source_type_id <> 5 -- exclude wip issue tasks
13935 	AND    mmtt.transaction_source_type_id IN (2, 8) --restrict to sales order and internal order mmtts only
13936 	AND mmtt.transaction_temp_id = p_task_id
13937 	AND rules.organization_id IN (mmtt.organization_id, -1)
13938 	AND NVL(wop.organization_id, mmtt.organization_id) = mmtt.organization_id
13939            AND wop.enabled_flag = 'Y'
13940       ORDER BY rules.rule_weight DESC, rules.creation_date;
13941 
13942     --cursor used to determine if the rule package exists
13943     CURSOR l_pack_gen IS
13944       SELECT COUNT(object_name)
13945         FROM user_objects
13946        WHERE object_name = l_package_name;
13947 
13948     -- Bug# 4587423: If a default outbound operation plan is not defined for the org,
13949     -- default to 1 (Locator and LPN Based Consolidation in Staging Lane)
13950     CURSOR c_default_operation_plan IS
13951       SELECT NVL(default_pick_op_plan_id, 1)
13952         FROM mtl_parameters
13953        WHERE organization_id = l_organization_id;
13954 
13955        l_rule_counter           INTEGER;
13956   BEGIN
13957     SAVEPOINT assign_operation_plan_sp;
13958 
13959     -- Standard call to check for call compatibility
13960     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
13961       RAISE fnd_api.g_exc_unexpected_error;
13962     END IF;
13963 
13964     -- Initialize message list if p_init_msg_list is set to TRUE
13965     IF fnd_api.to_boolean(p_init_msg_list) THEN
13966       fnd_msg_pub.initialize;
13967     END IF;
13968 
13969     --
13970     -- Initialize API return status to success
13971     x_return_status  := fnd_api.g_ret_sts_success;
13972 
13973     -- Validate input parameters and pre-requisites, if validation level
13974     -- requires this
13975     IF p_validation_level <> fnd_api.g_valid_level_none THEN
13976       -- in case further needs for validation
13977       NULL;
13978     END IF;
13979 
13980     OPEN c_rules; -- open the eligible rules cursor
13981 
13982     LOOP -- loop through the rules
13983       FETCH c_rules INTO l_rule_id, l_organization_id, l_wms_task_type, l_operation_plan_id;
13984       EXIT WHEN c_rules%NOTFOUND;
13985 
13986       BEGIN
13987         -- get the pre-generated package name for this rule
13988         getpackagename(l_rule_id, l_package_name);
13989 
13990          --- Execute op Rule
13991         For l_rule_counter IN 1..2  LOOP
13992             execute_op_rule(l_rule_id, p_task_id, l_return_status);
13993 	    IF (l_return_status = -1) and l_rule_counter   = 2 THEN --error
13994 	        fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
13995 	        fnd_message.set_token('RULEID', l_rule_id);
13996 	        fnd_msg_pub.ADD;
13997 	        log_error_msg(l_api_name, 'rule_package_missing');
13998 	        log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
13999 	        RAISE fnd_api.g_exc_unexpected_error;
14000 	    ELSIF l_return_status <> -1 THEN
14001 	        EXIT;
14002 	    END IF;
14003        END LOOP;
14004 
14005        IF l_return_status > 0 THEN -- the rule matches the task
14006           l_found  := TRUE;
14007 
14008           -- update mmtt table to assign the operation plan
14009 
14010 
14011           UPDATE mtl_material_transactions_temp mmtt
14012              SET mmtt.operation_plan_id = l_operation_plan_id
14013            WHERE mmtt.transaction_temp_id = p_task_id;
14014 
14015           EXIT; -- operation plan assigned, jump out of the rule loop
14016         END IF; -- l_return_status > 0
14017       EXCEPTION -- handle exceptions for matching one rule
14018         WHEN fnd_api.g_exc_error THEN
14019           NULL;
14020         WHEN OTHERS THEN
14021           NULL;
14022       END; -- end matching one rule
14023     END LOOP;
14024 
14025     CLOSE c_rules; --close the rule cursor
14026 
14027     -- get default operation plan
14028     IF NOT l_found THEN
14029 
14030       begin
14031             select organization_id
14032              into  l_organization_id
14033              from  mtl_material_transactions_temp
14034 	      where  transaction_temp_id = p_task_id
14035 	      AND transaction_source_type_id IN (2, 8);   -- bug fix 3361560
14036       exception
14037             when others then
14038                 null;
14039       end;
14040 
14041       IF NVL(g_current_organization_id, -1) <> l_organization_id THEN
14042         g_current_organization_id  := l_organization_id;
14043         OPEN c_default_operation_plan;
14044         FETCH c_default_operation_plan INTO g_default_operation_plan_id;
14045 
14046         IF c_default_operation_plan%NOTFOUND THEN
14047           l_operation_plan_id  := NULL;
14048         END IF;
14049 
14050         CLOSE c_default_operation_plan;
14051       END IF;
14052 
14053       l_operation_plan_id  := g_default_operation_plan_id;
14054 
14055       UPDATE mtl_material_transactions_temp mmtt
14056          SET mmtt.operation_plan_id = l_operation_plan_id
14057        WHERE mmtt.transaction_temp_id = p_task_id;
14058     END IF;
14059 
14060     -- Standard check of p_commit
14061     IF fnd_api.to_boolean(p_commit) THEN
14062       COMMIT WORK;
14063     END IF;
14064   EXCEPTION
14065     WHEN fnd_api.g_exc_error THEN
14066       -- if the rule package not created yet, close the rule cursor
14067       IF c_rules%ISOPEN THEN
14068         CLOSE c_rules;
14069       END IF;
14070 
14071       ROLLBACK TO assign_operation_plan_sp;
14072       freeglobals;
14073       x_return_status  := fnd_api.g_ret_sts_error;
14074 
14075       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14076         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14077       END IF;
14078 
14079       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14080     WHEN OTHERS THEN
14081       ROLLBACK TO assign_operation_plan_sp;
14082       freeglobals;
14083       x_return_status  := fnd_api.g_ret_sts_unexp_error;
14084 
14085       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14086         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14087       END IF;
14088 
14089       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14090   END assign_operation_plan;
14091 
14092   --**************************************
14093 
14094   --
14095   -- API name    : AssignTT
14096   -- Type        : Private
14097   -- Function    : Assign task type to records in MMTT
14098   -- Input Parameters  :
14099   --
14100   -- Output Parameters:
14101   -- Version     :
14102   --   Current version 1.0
14103   --
14104   -- Notes       : calls AssignTTs(p_task_id NUMBER)
14105   --
14106   -- This procedure loops through mtl_material_transactions_temp table, assign
14107   -- user defined task type to tasks that have not been assigned a task type
14108   -- for the given Move Order Header.
14109   --
14110 
14111 
14112   PROCEDURE assigntts(
14113     p_api_version          IN            NUMBER
14114   , p_init_msg_list        IN            VARCHAR2
14115   , p_commit               IN            VARCHAR2
14116   , p_validation_level     IN            NUMBER
14117   , x_return_status        OUT NOCOPY    VARCHAR2
14118   , x_msg_count            OUT NOCOPY    NUMBER
14119   , x_msg_data             OUT NOCOPY    VARCHAR2
14120   , p_move_order_header_id IN            NUMBER
14121   ) IS
14122     CURSOR c_tasks IS
14123       SELECT mmtt.transaction_temp_id
14124             ,mmtt.organization_id -- Added new
14125             ,mmtt.wms_task_type   -- Added new
14126         FROM mtl_material_transactions_temp mmtt, mtl_txn_request_lines mol
14127        WHERE mmtt.standard_operation_id IS NULL
14128          AND mmtt.move_order_line_id = mol.line_id
14129          AND mol.header_id = p_move_order_header_id;
14130 
14131     l_task_id           NUMBER;
14132     l_organization_id   NUMBER; -- Added new
14133     l_wms_task_type     NUMBER; -- Added new
14134     l_return_status VARCHAR2(1);
14135     l_msg_count     NUMBER;
14136     l_msg_data      VARCHAR2(2000);
14137     l_api_name      VARCHAR2(30)   := 'assignTTs';
14138     l_count         NUMBER;
14139   BEGIN
14140     -- Initialize API return status to success
14141     x_return_status  := fnd_api.g_ret_sts_success;
14142 
14143     -- Bug# 4587423
14144     -- See if there are any enabled rules for Task Type Assignment for
14145     -- all orgs or for the orgs in the set of MMTT records for the given move order header.
14146     l_count := 0;
14147     BEGIN
14148        SELECT 1 INTO l_count
14149 	 FROM dual
14150 	 WHERE EXISTS (SELECT 1 FROM wms_rules_b rules
14151 		       WHERE  rules.type_code = 3
14152 		       AND    rules.enabled_flag = 'Y'
14153 		       AND    (organization_id = -1
14154 			       OR organization_id IN (SELECT mmtt.organization_id
14155 						      FROM mtl_material_transactions_temp mmtt,
14156 						      mtl_txn_request_lines mol
14157 						      WHERE mmtt.standard_operation_id IS NULL
14158 						      AND mmtt.move_order_line_id = mol.line_id
14159 						      AND mol.header_id = p_move_order_header_id)));
14160     EXCEPTION
14161        WHEN OTHERS THEN
14162 	  l_count := 0;
14163     END;
14164 
14165     -- Bug# 4587423
14166     -- If there is at least one task type assignment rule enabled,
14167     -- go through the existing logic.
14168     IF (l_count > 0) THEN
14169        OPEN c_tasks;
14170        LOOP
14171 	  FETCH c_tasks INTO l_task_id
14172                             ,l_organization_id  -- new
14173                             ,l_wms_task_type;    -- new
14174 	  EXIT WHEN c_tasks%NOTFOUND;
14175 	  assigntt
14176 	    (p_api_version                => 1.0,
14177 	     p_task_id                    => l_task_id,
14178 	     x_return_status              => l_return_status,
14179 	     x_msg_count                  => l_msg_count,
14180 	     x_msg_data                   => l_msg_data
14181 	     );
14182 
14183 	  IF l_return_status <> fnd_api.g_ret_sts_success THEN
14184 	     x_return_status  := fnd_api.g_ret_sts_error;
14185 	  END IF;
14186        END LOOP;
14187 
14188        CLOSE c_tasks;
14189      ELSE
14190        -- Bug# 4587423
14191        -- No valid rules exist for task type assignment so just stamp the org level
14192        -- default task type for the given WMS task type on the MMTT record.
14193        UPDATE mtl_material_transactions_temp mmtt
14194 	 SET standard_operation_id =
14195 	 (SELECT DECODE(mmtt.wms_task_type, 1, default_pick_task_type_id,
14196 			2, default_putaway_task_type_id,
14197 			3, default_cc_task_type_id,
14198 			4, default_repl_task_type_id,
14199 			5, default_moxfer_task_type_id,
14200 			6, default_moissue_task_type_id,
14201 			NULL)
14202 	  FROM mtl_parameters mp WHERE mp.organization_id = mmtt.organization_id)
14203 	 WHERE mmtt.standard_operation_id IS NULL
14204 	   AND mmtt.move_order_line_id IN (SELECT line_id
14205 					   FROM mtl_txn_request_lines mol
14206 					   WHERE mol.header_id = p_move_order_header_id);
14207     END IF;
14208 
14209   EXCEPTION
14210      WHEN OTHERS THEN
14211 	x_return_status  := fnd_api.g_ret_sts_unexp_error;
14212   END assigntts;
14213 
14214   --
14215   -- API name    : AssignTT
14216   -- Type        : Private
14217   -- Function    : Assign task type to a specific record in MMTT
14218   -- Input Parameters  :
14219   --           p_task_id NUMBER
14220   --
14221   -- Output Parameters:
14222   -- Version     :
14223   --   Current version 1.0
14224   --
14225   -- Notes       :
14226   --
14227   -- This procedure assign user defined task types to a specific task in
14228   -- mtl_material_transactions_temp. Task type is implemeted by WMS rules.
14229   -- This procedure calls the rule package created for task type rules to check
14230   -- which task type rule actually matches the task in question.
14231   --
14232 
14233   PROCEDURE assigntt(
14234     p_api_version      IN            NUMBER
14235   , p_init_msg_list    IN            VARCHAR2
14236   , p_commit           IN            VARCHAR2
14237   , p_validation_level IN            NUMBER
14238   , x_return_status    OUT NOCOPY    VARCHAR2
14239   , x_msg_count        OUT NOCOPY    NUMBER
14240   , x_msg_data         OUT NOCOPY    VARCHAR2
14241   , p_task_id          IN            NUMBER
14242    ) IS
14243     l_rule_id                   NUMBER;
14244     l_pack_exists               NUMBER;
14245     l_package_name              VARCHAR2(30);
14246     l_rule_func_sql             LONG;
14247     l_rule_result               NUMBER;
14248     l_cursor                    INTEGER;
14249     l_dummy                     NUMBER;
14250     l_count                     NUMBER;
14251     l_return_status             NUMBER;
14252     l_revision_dummy            VARCHAR2(10);
14253     l_lot_number_dummy          VARCHAR2(80);
14254     l_lot_expiration_date_dummy DATE;
14255     l_subinventory_code_dummy   VARCHAR2(10);
14256     l_locator_id_dummy          NUMBER;
14257     l_possible_qty_dummy        NUMBER;
14258     l_uom_code_dummy            VARCHAR2(3);
14259     l_order_by_string_dummy     VARCHAR2(1000);
14260     l_found                     BOOLEAN        := FALSE;
14261     l_organization_id           NUMBER;
14262     l_wms_task_type             NUMBER;
14263     l_task_type_id              NUMBER;
14264     l_type_hdr_id               NUMBER;
14265 
14266     l_api_version      CONSTANT NUMBER         := 1.0;
14267     l_api_name         CONSTANT VARCHAR2(30)   := 'AssignTT';
14268 
14269     l_debug                     NUMBER;
14270 
14271 
14272     -- Cursor for task type rule loop
14273     -- Only rules with the same WMS system task type as the task
14274     -- will be selected
14275     -- Rules are ordered by rule weight and creation date
14276 
14277     CURSOR c_rules IS
14278       SELECT   rules.rule_id
14279              , rules.type_hdr_id /* Added this Column */
14280              , mmtt.organization_id
14281              , mmtt.wms_task_type
14282           FROM wms_rules_b rules, bom_standard_operations bso , mtl_material_transactions_temp mmtt
14283          WHERE rules.type_code = 3
14284            AND rules.enabled_flag = 'Y'
14285            AND rules.type_hdr_id = bso.standard_operation_id
14286            AND bso.wms_task_type = NVL(mmtt.wms_task_type, bso.wms_task_type)
14287            AND mmtt.transaction_temp_id = p_task_id
14288            AND rules.organization_id IN (mmtt.organization_id, -1)
14289            AND bso.organization_id = mmtt.organization_id
14290       ORDER BY rules.rule_weight DESC, rules.creation_date;
14291 
14292   /*CURSOR c_rules_new IS
14293     SELECT   rules.rule_id ,  rules.type_hdr_id
14294 	FROM wms_rules_b rules, bom_standard_operations bso
14295        WHERE rules.type_code = 3
14296 	 AND rules.enabled_flag = 'Y'
14297 	 AND rules.type_hdr_id = bso.standard_operation_id
14298 	 AND bso.wms_task_type = NVL(p_wms_task_type, bso.wms_task_type)
14299 	 AND rules.organization_id IN (p_organization_id, -1)
14300 	 AND bso.organization_id = p_organization_id
14301     ORDER BY rules.rule_weight DESC, rules.creation_date; */
14302 
14303 
14304     --cursor used to determine if the rule package exists
14305     CURSOR l_pack_gen IS
14306       SELECT COUNT(object_name)
14307         FROM user_objects
14308        WHERE object_name = l_package_name;
14309 
14310     -- Following Code is commented because now we need to get 2 more default task_type..MOISSUE and MOXFER
14311       /*CURSOR c_default_task_type IS
14312       SELECT default_pick_task_type_id
14313             ,default_cc_task_type_id
14314             ,default_putaway_task_type_id
14315             ,default_repl_task_type_id
14316         FROM mtl_parameters
14317        WHERE organization_id = l_organization_id;
14318       */
14319 
14320     CURSOR c_default_task_type IS
14321       SELECT default_pick_task_type_id
14322            , default_cc_task_type_id
14323            , default_putaway_task_type_id
14324            , default_repl_task_type_id
14325            , default_moxfer_task_type_id
14326            , default_moissue_task_type_id
14327            , default_pick_op_plan_id
14328         FROM mtl_parameters
14329        WHERE organization_id =  l_organization_id;
14330 
14331        l_rule_counter           INTEGER;
14332   BEGIN
14333     SAVEPOINT assignttsp;
14334 
14335     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
14336        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
14337      END IF;
14338     l_debug := g_debug;
14339 
14340     -- Standard call to check for call compatibility
14341     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
14342       RAISE fnd_api.g_exc_unexpected_error;
14343     END IF;
14344 
14345     -- Initialize message list if p_init_msg_list is set to TRUE
14346     IF fnd_api.to_boolean(p_init_msg_list) THEN
14347       fnd_msg_pub.initialize;
14348     END IF;
14349 
14350     --
14351     -- Initialize API return status to success
14352     x_return_status  := fnd_api.g_ret_sts_success;
14353 
14354     -- Validate input parameters and pre-requisites, if validation level
14355     -- requires this
14356     IF p_validation_level <> fnd_api.g_valid_level_none THEN
14357       -- in case further needs for validation
14358       NULL;
14359     END IF;
14360 
14361     OPEN c_rules; -- open the eligible rules cursor
14362 
14363     LOOP -- loop through the rules
14364       FETCH c_rules INTO l_rule_id, l_type_hdr_id, l_organization_id, l_wms_task_type;
14365       EXIT WHEN c_rules%NOTFOUND;
14366 
14367       --inv_log_util.TRACE('found the rule', 'RULE_ENGINE', 4);
14368 
14369       BEGIN
14370         -- get the pre-generated package name for this rule
14371         getpackagename(l_rule_id, l_package_name);
14372 
14373         --- Execute Task Rule
14374 
14375        -- execute_task_rule(l_rule_id, p_task_id, l_return_status);
14376         For l_rule_counter IN 1..2  LOOP
14377            IF l_debug = 1 THEN
14378               log_error(l_api_name, 'Assigntt', 'Inside Loop :l_rule_counter         ' || l_rule_counter);
14379               log_error(l_api_name, 'Assigntt', 'Calling execute_Task :l_rul        e_id ' || l_rule_id);
14380               log_error(l_api_name, 'Assigntt', 'Calling execute_Task :p_Tas        k_id ' || p_task_id);
14381            END IF;
14382            execute_task_rule(l_rule_id, p_task_id, l_return_status);
14383              IF (l_return_status = -1) and l_rule_counter   = 2 THEN --error
14384                fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
14385                fnd_message.set_token('RULEID', l_rule_id);
14386                fnd_msg_pub.ADD;
14387                IF l_debug = 1 THEN
14388                   log_error_msg(l_api_name, 'rule_package_missing');
14389                   log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
14390                END IF;
14391                RAISE fnd_api.g_exc_unexpected_error;
14392              ELSIF  l_return_status <> -1 THEN
14393                 EXIT;
14394              END IF;
14395         END LOOP;
14396         If l_debug = 1 THEN
14397            log_error(l_api_name, 'Assigntt', 'After Execute_Task :l_return_s        tatus ' || l_return_status);
14398         END IF;
14399 
14400         IF l_return_status > 0 THEN -- the rule matches the task
14401            l_found  := TRUE;
14402 
14403           -- update mmtt table to assign the task type
14404 
14405           UPDATE mtl_material_transactions_temp mmtt
14406              SET mmtt.standard_operation_id = l_type_hdr_id
14407            WHERE mmtt.transaction_temp_id = p_task_id;
14408            /*
14409            UPDATE mtl_material_transactions_temp mmtt
14410 	                SET mmtt.standard_operation_id = (SELECT type_hdr_id
14411 	                                                    FROM wms_rules_b
14412 	                                                   WHERE rule_id = l_rule_id)
14413            WHERE mmtt.transaction_temp_id = p_task_id
14414            */
14415 
14416           EXIT; -- task assigned, jump out of the rule loop
14417         END IF; -- l_return_status > 0
14418       EXCEPTION -- handle exceptions for matching one rule
14419         WHEN fnd_api.g_exc_error THEN
14420           NULL;
14421         WHEN OTHERS THEN
14422           NULL;
14423       END; -- end matching one rule
14424     END LOOP;
14425 
14426     CLOSE c_rules; --close the rule cursor
14427 
14428     -- get default task type
14429     IF NOT l_found THEN
14430      -- bug 2737846
14431      begin
14432       select organization_id, wms_task_type
14433        into  l_organization_id, l_wms_task_type
14434        from  mtl_material_transactions_temp
14435       where  transaction_temp_id = p_task_id;
14436      exception
14437         when others then
14438           null;
14439      end;
14440 
14441       --inv_log_util.TRACE('NOT found the rule: g_current_organization_id'||g_current_organization_id, 'RULE_ENGINE', 4);
14442       --inv_log_util.TRACE('NOT found the rule: l_organization_id:'||l_organization_id, 'RULE_ENGINE', 4);
14443       IF NVL(g_current_organization_id, -1) <> l_organization_id THEN
14444         g_current_organization_id  := l_organization_id;
14445 
14446 
14447         OPEN c_default_task_type;
14448         /*FETCH c_default_task_type INTO g_default_pick_task_type_id
14449                           ,g_default_cc_task_type_id
14450                           ,g_default_putaway_task_type_id
14451                           ,g_default_repl_task_type_id;
14452          */
14453         FETCH c_default_task_type INTO g_default_pick_task_type_id
14454                                      , g_default_cc_task_type_id
14455                                      , g_default_putaway_task_type_id
14456                                      , g_default_repl_task_type_id
14457                                      , g_default_moxfer_task_type_id
14458                                      , g_default_moissue_task_type_id
14459 				     , g_default_operation_plan_id;
14460 
14461         IF c_default_task_type%NOTFOUND THEN
14462           g_current_organization_id       := NULL;
14463           g_default_pick_task_type_id     := NULL;
14464           g_default_cc_task_type_id       := NULL;
14465           g_default_putaway_task_type_id  := NULL;
14466           g_default_repl_task_type_id     := NULL;
14467           g_default_moxfer_task_type_id   := NULL;
14468           g_default_moissue_task_type_id  := NULL;
14469 	  g_default_operation_plan_id	  := NULL;
14470           --inv_log_util.TRACE('default_task_type not found', 'RULE_ENGINE', 4);
14471         END IF;
14472 
14473         CLOSE c_default_task_type;
14474       END IF;
14475 
14476       --inv_log_util.TRACE('inside cursor c_defualt_task_type', 'RULE_ENGINE', 4);
14477 
14478 
14479       IF l_wms_task_type = 1 THEN
14480          l_task_type_id  := g_default_pick_task_type_id;
14481       ELSIF l_wms_task_type = 2 THEN
14482         l_task_type_id  := g_default_putaway_task_type_id;
14483       ELSIF l_wms_task_type = 3 THEN
14484         l_task_type_id  := g_default_cc_task_type_id; --g_default_repl_task_type_id; --Bug# 3110550
14485       ELSIF l_wms_task_type = 4 THEN
14486         l_task_type_id  := g_default_repl_task_type_id; --g_default_cc_task_type_id; --Bug# 3110550
14487       ELSIF l_wms_task_type = 5 THEN
14488         l_task_type_id  := g_default_moxfer_task_type_id;
14489       ELSIF l_wms_task_type = 6 THEN
14490         l_task_type_id  := g_default_moissue_task_type_id;
14491       ELSE
14492         l_task_type_id  := NULL;
14493       END IF;
14494 
14495       --inv_log_util.TRACE('wms_task_type = 1, task_type_id=:' || l_task_type_id, 'RULE_ENGINE', 4);
14496       --inv_log_util.TRACE('before update statement', 'RULE_ENGINE', 4);
14497 
14498       UPDATE mtl_material_transactions_temp mmtt
14499          SET mmtt.standard_operation_id = l_task_type_id
14500        WHERE mmtt.transaction_temp_id = p_task_id;
14501 
14502        --inv_log_util.TRACE('after update statement: standard_operation_id:'||jxlu_soi, 'RULE_ENGINE', 4);
14503     END IF;
14504 
14505     -- Standard check of p_commit
14506     IF fnd_api.to_boolean(p_commit) THEN
14507       COMMIT WORK;
14508     END IF;
14509   EXCEPTION
14510     WHEN fnd_api.g_exc_error THEN
14511       -- if the rule package not created yet, close the rule cursor
14512       IF c_rules%ISOPEN THEN
14513         CLOSE c_rules;
14514       END IF;
14515 
14516       ROLLBACK TO assignttsp;
14517       freeglobals;
14518       x_return_status  := fnd_api.g_ret_sts_error;
14519 
14520       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14521         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14522       END IF;
14523 
14524       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14525     WHEN OTHERS THEN
14526       ROLLBACK TO assignttsp;
14527       freeglobals;
14528       x_return_status  := fnd_api.g_ret_sts_unexp_error;
14529 
14530       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14531         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14532       END IF;
14533 
14534       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14535   END assigntt;
14536 
14537   --
14538   -- API name    : CalcRuleWeight
14539   -- Type        : Private
14540   -- Function    : Calculate initial rule weight based on number of distinct restriction
14541   --               parameters. This is currently the requirement for task type assignment
14542   --
14543   -- Input Parameters  :
14544   --           p_task_id NUMBER
14545   --
14546   -- Output Parameters:
14547   -- Version     :
14548   --   Current version 1.0
14549   --
14550   -- Notes       :
14551   --
14552   -- This procedure will be called by Define Rule form through generate rule package call
14553 
14554   PROCEDURE calcruleweight(p_rule_id NUMBER) IS
14555   BEGIN
14556 
14557     UPDATE wms_rules_b
14558        SET rule_weight = (SELECT 100 * COUNT(parameter_id)
14559                             FROM (SELECT DISTINCT rules.rule_id
14560                                                 , par.parameter_id
14561                                              FROM wms_rules_b rules, wms_restrictions rest, wms_parameters_b par
14562                                             WHERE rules.rule_id = p_rule_id
14563                                               AND rules.rule_id = rest.rule_id(+)
14564                                               AND rest.parameter_id = par.parameter_id(+)
14565                                               AND (NVL(par.use_for_tt_assn_flag, 'Y') = 'Y'
14566                                                    OR NVL(par.use_for_label_rest_flag, 'Y') = 'Y'
14567                                                   )))
14568      WHERE rule_id = p_rule_id
14569        AND rule_weight IS NULL;
14570 
14571 
14572   EXCEPTION
14573     WHEN OTHERS THEN
14574       NULL;
14575   END calcruleweight;
14576 
14577   --===========================================================================================
14578   --
14579   -- API name    : ApplyLabel
14580   -- Type        : Private
14581   -- Function    : Retrieve Label based on Label request
14582   -- Input Parameters  :
14583   --           p_label_request_id  NUMBER
14584   --           p_document_id       NUMBER
14585   --
14586   -- Output Parameters: x_label_format_id
14587   -- Version     :
14588   -- Current version 1.0
14589   --
14590   -- Notes       :
14591   --
14592   -- This procedure retrieves a specific label for a label request in
14593   -- wms_label_requests.
14594   -- This procedure calls the rule package created for Label rules to check
14595   -- which label rule actually matches the label request in question.
14596   --===========================================================================
14597   PROCEDURE applylabel(
14598     p_api_version       IN            NUMBER
14599   , p_init_msg_list     IN            VARCHAR2
14600   , p_commit            IN            VARCHAR2
14601   , p_validation_level  IN            NUMBER
14602   , p_label_request_id  IN            NUMBER
14603   , x_return_status     OUT NOCOPY    VARCHAR2
14604   , x_msg_count         OUT NOCOPY    NUMBER
14605   , x_msg_data          OUT NOCOPY    VARCHAR2
14606   , x_label_format_id   OUT NOCOPY    NUMBER
14607   , x_label_format_name OUT NOCOPY    VARCHAR2
14608   ) IS
14609     l_rule_id              NUMBER;
14610     l_rule_weight          NUMBER;
14611     l_pack_exists          NUMBER;
14612     l_package_name         VARCHAR2(30);
14613     l_rule_func_sql        LONG;
14614     l_rule_result          NUMBER;
14615     l_cursor               INTEGER;
14616     l_dummy                NUMBER;
14617     l_count                NUMBER;
14618     l_return_status        NUMBER;
14619     l_label_format_id      NUMBER;
14620     l_document_id          NUMBER;
14621     l_label_format_name    wms_label_formats.label_format_name%TYPE;
14622     l_api_version CONSTANT NUMBER                                     := 1.0;
14623     l_api_name    CONSTANT VARCHAR2(30)                               := 'ApplyLabel';
14624     l_msg_data             VARCHAR2(2000);
14625     l_strategy_id          NUMBER                                     := NULL;
14626 
14627 
14628     -- Cursor for label rule loop
14629     -- Only rules with the type_code = 4
14630     -- will be selected
14631     -- Rules are ordered by rule weight and creation date
14632 
14633     CURSOR c_rules IS
14634       SELECT   rules.rule_id
14635              , rules.rule_weight
14636              , rules.type_hdr_id
14637              , wl.label_format_name
14638              , wl.document_id
14639           FROM wms_rules_b rules, wms_label_formats wl, wms_label_requests wlr
14640          WHERE rules.type_code = 4
14641            AND rules.type_hdr_id = wl.label_format_id
14642            AND wl.label_format_id = NVL(wlr.label_format_id, wl.label_format_id)
14643            AND NVL(format_disable_date, SYSDATE + 1) > SYSDATE   --Bug #3452076
14644            AND wlr.document_id = wl.document_id
14645            AND wlr.label_request_id = p_label_request_id
14646            AND rules.enabled_flag = 'Y'
14647            AND (rules.organization_id = wlr.organization_id
14648                 OR rules.organization_id = -1
14649                ) -- Common to All Org.
14650       ORDER BY rules.rule_weight DESC, rules.creation_date;
14651 
14652     --cursor used to determine if the rule package exists
14653     CURSOR l_pack_gen IS
14654       SELECT COUNT(object_name)
14655         FROM user_objects
14656        WHERE object_name = l_package_name;
14657 
14658     CURSOR l_default_label_curs IS
14659       SELECT label_format_id
14660            , label_format_name
14661         FROM wms_label_formats
14662        WHERE document_id = l_document_id
14663          AND default_format_flag IN ('Y', 'y');
14664 
14665     CURSOR l_label_requests_curs IS
14666       SELECT *
14667         FROM wms_label_requests
14668        WHERE label_request_id = p_label_request_id;
14669 
14670     l_label_req_rc         wms_label_requests%ROWTYPE;
14671     l_rule_counter           INTEGER;
14672     l_debug                  NUMBER;
14673     ll_ctr                   NUMBER;
14674   BEGIN
14675     SAVEPOINT assignlabelsp;
14676    ----
14677        SELECT   count(rules.rule_id ) into  ll_ctr
14678        FROM wms_rules_b rules, wms_label_formats wl, wms_label_requests wlr
14679        WHERE rules.type_code = 4
14680                   AND rules.type_hdr_id = wl.label_format_id
14681                   AND wl.label_format_id = NVL(wlr.label_format_id, wl.label_format_id)
14682                   AND NVL(format_disable_date, SYSDATE + 1) > SYSDATE   --Bug #        3452076
14683                   AND wlr.document_id = wl.document_id
14684                   AND wlr.label_request_id = p_label_request_id
14685                   AND rules.enabled_flag = 'Y'
14686                   AND (rules.organization_id = wlr.organization_id
14687                        OR rules.organization_id = -1
14688                   ) ;
14689    ----
14690     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
14691        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
14692     END IF;
14693     l_debug := g_debug;
14694     IF l_debug = 1 THEN
14695        TRACE('Executing ApplyLabel()...Label_request_ID :  '|| p_label_request_id);
14696        TRACE('Number of rules to process(LL_CTR) :' || ll_ctr);
14697     END IF;
14698 
14699     -- Standard call to check for call compatibility
14700     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
14701       RAISE fnd_api.g_exc_unexpected_error;
14702     END IF;
14703 
14704     -- Initialize message list if p_init_msg_list is set to TRUE
14705     IF fnd_api.to_boolean(p_init_msg_list) THEN
14706       fnd_msg_pub.initialize;
14707     END IF;
14708 
14709     --
14710     -- Initialize API return status to success
14711     x_return_status      := fnd_api.g_ret_sts_success;
14712 
14713     -- Validate input parameters and pre-requisites, if validation level
14714     -- requires this
14715     IF p_validation_level <> fnd_api.g_valid_level_none THEN
14716       -- in case further needs for validation
14717       NULL;
14718     END IF;
14719 
14720     -- Retrieve document_id based on P_label_request_id
14721 
14722     OPEN l_label_requests_curs;
14723     FETCH l_label_requests_curs INTO l_label_req_rc;
14724 
14725     --dummy should = 2, one for package, one for package body
14726     IF (l_label_requests_curs%NOTFOUND) THEN
14727       CLOSE l_label_requests_curs;
14728       IF l_debug = 1 THEN
14729          TRACE('Invalid Label Request Id : '|| p_label_request_id);
14730       END IF;
14731       fnd_message.set_name('WMS', 'INVALID_LABEL_REQ');
14732       fnd_msg_pub.ADD;
14733       RAISE fnd_api.g_exc_error;
14734     END IF;
14735 
14736     CLOSE l_label_requests_curs;
14737 
14738     l_document_id        := l_label_req_rc.document_id;
14739     IF l_debug = 1 THEN
14740        TRACE('Label request document Id : '|| l_document_id);
14741     END IF;
14742     l_return_status      := 0; -- Initialize to 0
14743     OPEN c_rules; -- open the eligible rules cursor
14744 
14745     LOOP -- loop through the rules
14746       FETCH c_rules INTO l_rule_id, l_rule_weight, l_label_format_id, l_label_format_name, l_label_req_rc.document_id;
14747       EXIT WHEN c_rules%NOTFOUND;
14748       -- get the pre-generated package name for this rule
14749       getpackagename(l_rule_id, l_package_name);
14750 
14751       FOR l_rule_counter IN 1..2  LOOP
14752            IF l_debug = 1 THEN
14753             log_error(l_api_name, 'AssignLabel', 'Inside Loop :l_rule_counter ' || l_rule_counter);
14754             log_error(l_api_name, 'AssignLabel', 'Calling execute_label :l_rule_id ' || l_rule_id);
14755             log_error(l_api_name, 'AssignLabel', 'p_label_request_id ' || p_label_request_id);
14756            END IF;
14757            execute_label_rule(l_rule_id, p_label_request_id, l_return_status);
14758            IF l_debug = 1 THEN
14759               log_statement(l_api_name, 'Inside Loop', 'l_return_status' || l_return_status);
14760            END IF;
14761            log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
14762            IF (l_return_status = -1) and l_rule_counter   = 2 THEN --error
14763               fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
14764               fnd_message.set_token('RULEID', l_rule_id);
14765               fnd_msg_pub.ADD;
14766               IF l_debug = 1 THEN
14767                  log_error_msg(l_api_name, 'rule_package_missing');
14768                  log_error(l_api_name, 'Rule missing in the list pkg', 'l_rule_id ' || l_rule_id);
14769               END IF;
14770               RAISE fnd_api.g_exc_unexpected_error;
14771             ELSIF l_return_status  <> -1 THEN
14772                EXIT;
14773             END IF;
14774       END LOOP;
14775 
14776       IF l_return_status > 0 THEN -- the rule matches the label request
14777         -- update wms_label_requests table with label_format_id
14778 
14779 
14780         UPDATE wms_label_requests wlr
14781            SET wlr.label_format_id = l_label_format_id
14782              , wlr.rule_id = l_rule_id
14783              , wlr.strategy_id = l_strategy_id
14784              , wlr.rule_weight = l_rule_weight
14785          WHERE wlr.label_request_id = p_label_request_id;
14786         IF l_debug = 1 THEN
14787            TRACE('Rule Match.Update Label Request with format ID :'|| l_label_format_id || ' ' || l_label_format_name);
14788         END IF;
14789 
14790         EXIT; -- label retrieved, jump out of the rule loop
14791       ELSIF (l_return_status = 0) THEN
14792         IF l_debug = 1 THEN
14793           trace('no rows found from procedure execute_label_rule()');
14794         END IF;
14795       END IF;
14796     END LOOP;
14797 
14798     CLOSE c_rules; --close the rule cursor
14799 
14800     -- ===================================================================
14801     -- Retrieve default label if there is no rule match the label request
14802     -- ===================================================================
14803     IF l_debug = 1 THEN
14804       trace('l_return_status : '|| l_return_status);
14805     END IF;
14806 
14807     IF (l_return_status = 0) THEN
14808       IF l_debug = 1 THEN
14809          TRACE('No rule match retrieve the default format ');
14810       END IF;
14811       --Bug: 2646648 Patchset I label cleanup
14812       --Reset l_label_format_id(name) to null
14813       -- before retrieving default format
14814         -- so that if no default format, it will have value null
14815       -- instead of the value from cursor c_rules
14816       l_label_format_id    := NULL;
14817       l_label_format_name  := NULL;
14818       OPEN l_default_label_curs;
14819       FETCH l_default_label_curs INTO l_label_format_id, l_label_format_name;
14820       CLOSE l_default_label_curs;
14821     END IF;
14822 
14823     -- update wms_label_requests table with label_format_id
14824 
14825 
14826     UPDATE wms_label_requests wlr
14827        SET wlr.label_format_id = l_label_format_id
14828      WHERE wlr.label_request_id = p_label_request_id;
14829 
14830     IF l_debug = 1 THEN
14831        TRACE('Update Label Request with label ID :'|| l_label_format_id || '.(' || SQL%ROWCOUNT || ')');
14832     END IF;
14833 
14834     --
14835     -- Assign x_label_format_id with l_label_format_id
14836     --
14837     x_label_format_id    := l_label_format_id;
14838     x_label_format_name  := l_label_format_name;
14839 
14840     -- Standard check of p_commit
14841     IF fnd_api.to_boolean(p_commit) THEN
14842       COMMIT WORK;
14843     END IF;
14844   EXCEPTION
14845     WHEN fnd_api.g_exc_error THEN
14846       -- if the rule package not created yet, close the rule cursor
14847       IF c_rules%ISOPEN THEN
14848         CLOSE c_rules;
14849       END IF;
14850 
14851       ROLLBACK TO assignlabelsp;
14852       freeglobals;
14853       x_return_status  := fnd_api.g_ret_sts_error;
14854       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14855     WHEN OTHERS THEN
14856       l_msg_data       := SQLERRM;
14857       IF l_debug = 1 THEN
14858          TRACE('EXCEPTION OTHERS: '|| l_msg_data);
14859       END IF;
14860       ROLLBACK TO assignlabelsp;
14861       freeglobals;
14862       x_return_status  := fnd_api.g_ret_sts_unexp_error;
14863       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14864   END applylabel;
14865 
14866   PROCEDURE get_wms_sys_task_type(
14867     p_move_order_type            IN            NUMBER
14868   , p_transaction_action_id      IN            NUMBER
14869   , p_transaction_source_type_id IN            NUMBER
14870   , x_wms_sys_task_type          OUT NOCOPY    NUMBER
14871   ) IS
14872   BEGIN
14873     IF p_move_order_type = 2 THEN -- replenishment
14874       x_wms_sys_task_type  := 4; -- replenishment
14875     ELSIF p_move_order_type IN (3,5) THEN -- Bug 2666620: BackFlush MO Type Removed
14876       x_wms_sys_task_type  := 1; -- pick
14877     ELSIF p_move_order_type = 6 THEN -- put away
14878       x_wms_sys_task_type  := 2;
14879     ELSIF (p_move_order_type = 1
14880            AND p_transaction_action_id = 1
14881            AND p_transaction_source_type_id = 4
14882           ) THEN -- MO Issue
14883       x_wms_sys_task_type  := 6;
14884     ELSIF (p_move_order_type = 1
14885            AND p_transaction_action_id = 2
14886            AND p_transaction_source_type_id = 4
14887           ) THEN -- MO Xfer
14888       x_wms_sys_task_type  := 5;
14889     END IF;
14890   END get_wms_sys_task_type;
14891 
14892   --Compile_All_Rule_Packages
14893   --  Concurrent program which generates rule packages
14894   -- for all rules with enabled flag = Y
14895   PROCEDURE compile_all_rule_packages(errbuf OUT NOCOPY VARCHAR2, retcode OUT NOCOPY NUMBER) IS
14896     l_return_status VARCHAR2(1);
14897     l_msg_count     NUMBER;
14898     l_msg_data      VARCHAR2(240);
14899     l_rule_id       NUMBER;
14900     l_error_string  VARCHAR2(240);
14901     l_errbuf        VARCHAR2(240);
14902     l_return_code   NUMBER;
14903 
14904     CURSOR l_enabled_rules IS
14905       SELECT   rule_id
14906           FROM wms_rules_b
14907          WHERE enabled_flag = 'Y'
14908       ORDER BY rule_id;
14909   BEGIN
14910     --fnd_file.put_names('genall.log', 'genall.out', '/home/jcearley/work/');
14911     retcode  := 0;
14912     --fnd_file.put_line(fnd_file.LOG, '===Compiling All Rule Packages===');
14913     OPEN l_enabled_rules;
14914 
14915     LOOP
14916       FETCH l_enabled_rules INTO l_rule_id;
14917       EXIT WHEN l_enabled_rules%NOTFOUND;
14918       --fnd_file.put_line(fnd_file.LOG, 'Compiling Rule ID= ' || l_rule_id);
14919       wms_rule_pvt.generaterulepackage(
14920         p_api_version                => 1.0
14921       , p_init_msg_list              => fnd_api.g_true
14922       , p_validation_level           => fnd_api.g_valid_level_full
14923       , x_return_status              => l_return_status
14924       , x_msg_count                  => l_msg_count
14925       , x_msg_data                   => l_msg_data
14926       , p_rule_id                    => l_rule_id
14927       );
14928 
14929      --
14930      -- kkoothan  Bug Fix:2561401
14931      -- Used FND APIs to check the return status of the called procedure
14932      -- instead of using hard coded values.
14933      --
14934      IF (l_return_status = fnd_api.g_ret_sts_success) THEN
14935         FND_FILE.put_line(FND_FILE.LOG, 'Success from GenerateRulePackage');
14936      ELSE
14937         FND_FILE.put_line(FND_FILE.LOG, 'Error from GenerateRulePackage:');
14938         retcode  := 1;
14939 
14940         FOR i IN 1 .. l_msg_count LOOP
14941           --fnd_file.put_line(fnd_file.LOG, 'Error:');
14942           l_error_string  := fnd_message.get;
14943           --fnd_file.put_line(fnd_file.LOG, l_error_string);
14944           errbuf          := errbuf || ' Error: Rule ' || l_rule_id || '
14945           ' || l_error_string;
14946         END LOOP;
14947       END IF;
14948     END LOOP;
14949 
14950     --- Calling procedure to generate all rule list packages
14951     --- this package should be called stand alone .
14952     buildrulespkg(l_errbuf, l_return_code, l_return_status);
14953 
14954     IF (l_return_status = fnd_api.g_ret_sts_success) THEN
14955       FND_FILE.put_line(FND_FILE.LOG, 'Success from BuildRulesPkg');
14956     ELSE
14957       FND_FILE.put_line(FND_FILE.LOG, 'Error from BuildRulesPkg:');
14958       retcode  := 1;
14959 
14960       FOR i IN 1 .. l_msg_count LOOP
14961         --fnd_file.put_line(fnd_file.LOG, 'Error:');
14962         l_error_string  := fnd_message.get;
14963         --fnd_file.put_line(fnd_file.LOG, l_error_string);
14964         errbuf          := errbuf || ' Error: Creating WMS Rule List Package ' || l_error_string;
14965       END LOOP;
14966     END IF;
14967   EXCEPTION
14968     WHEN OTHERS THEN
14969       retcode  := 2;
14970       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14971         fnd_msg_pub.add_exc_msg(g_pkg_name, 'Compile All Rule Packages');
14972       END IF;
14973 
14974       fnd_msg_pub.count_and_get(p_count => l_msg_count, p_data => l_msg_data);
14975       --fnd_file.put_line(fnd_file.LOG, 'Exception in compile_all_rule_packages');
14976       --fnd_file.put_line(fnd_file.LOG, l_msg_data);
14977       errbuf   := errbuf || 'Error: ' || l_msg_data;
14978   END compile_all_rule_packages;
14979 
14980     --
14981     --
14982     PROCEDURE QuickPick
14983       (p_api_version                  IN   NUMBER                              ,
14984        p_init_msg_list                IN   VARCHAR2 DEFAULT fnd_api.g_false	   ,
14985        p_commit                       IN   VARCHAR2 DEFAULT fnd_api.g_false	   ,
14986        p_validation_level             IN   NUMBER   DEFAULT fnd_api.g_valid_level_full ,
14987        x_return_status                OUT  NOCOPY   VARCHAR2                            ,
14988        x_msg_count                    OUT  NOCOPY   NUMBER 	                           ,
14989        x_msg_data                     OUT  NOCOPY   VARCHAR2                            ,
14990        p_type_code                    IN   NUMBER   DEFAULT NULL ,
14991        p_transaction_temp_id          IN   NUMBER   DEFAULT NULL ,
14992        p_organization_id              IN   NUMBER   DEFAULT NULL ,
14993        p_inventory_item_id            IN   NUMBER   DEFAULT NULL ,
14994        p_transaction_uom              IN   VARCHAR2 DEFAULT NULL,
14995        p_primary_uom                  IN   VARCHAR2 DEFAULT NULL,
14996        p_secondary_uom                IN   VARCHAR2 DEFAULT NULL,                  -- new
14997        p_grade_code                   IN   VARCHAR2 DEFAULT NULL,                  -- new
14998        p_transaction_type_id          IN   NUMBER   DEFAULT NULL ,
14999        p_tree_id                      IN   NUMBER   DEFAULT NULL ,
15000        x_finished                     OUT  NOCOPY   VARCHAR2 			   ,
15001        p_detail_serial                IN   BOOLEAN  DEFAULT FALSE 		   ,
15002        p_from_serial                  IN   VARCHAR2 DEFAULT NULL 		   ,
15003        p_to_serial                    IN   VARCHAR2 DEFAULT NULL 		   ,
15004        p_detail_any_serial            IN   NUMBER   DEFAULT NULL,
15005        p_unit_volume                  IN   NUMBER   DEFAULT NULL,
15006        p_volume_uom_code              IN   VARCHAR2 DEFAULT NULL,
15007        p_unit_weight                  IN   NUMBER   DEFAULT NULL,
15008        p_weight_uom_code              IN   VARCHAR2 DEFAULT NULL,
15009        p_base_uom_code                IN   VARCHAR2 DEFAULT NULL,
15010        p_lpn_id                       IN   NUMBER   DEFAULT NULL,
15011        p_unit_number                  IN   VARCHAR2 DEFAULT NULL,
15012        p_simulation_mode              IN   NUMBER   DEFAULT -1,
15013        p_project_id                   IN   NUMBER   DEFAULT NULL,
15014        p_task_id                      IN   NUMBER   DEFAULT NULL
15015        )
15016         IS
15017 
15018           -- API standard variables
15019             l_api_version   CONSTANT NUMBER              := 1.0;
15020             l_api_name      CONSTANT VARCHAR2(30)        := 'QuickPick';
15021             l_debug_on               BOOLEAN;
15022 
15023             --  input variables
15024 
15025             l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE; --
15026             l_revision               wms_transactions_temp.revision%TYPE;               --
15027             l_lot_number             wms_transactions_temp.lot_number%TYPE;             --
15028             l_lot_expiration_date    wms_transactions_temp.lot_expiration_date%TYPE;    --
15029             l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE; --
15030             l_to_subinventory_code   wms_transactions_temp.to_subinventory_code%TYPE;   --
15031             l_subinventory_code      wms_transactions_temp.to_subinventory_code%TYPE;
15032             l_from_locator_id        wms_transactions_temp.from_locator_id%TYPE;        --
15033             l_to_locator_id          wms_transactions_temp.to_locator_id%TYPE;          --
15034             l_locator_id             wms_transactions_temp.to_locator_id%TYPE;
15035             l_from_cost_group_id     wms_transactions_temp.from_cost_group_id%TYPE;     --
15036             l_to_cost_group_id       wms_transactions_temp.to_cost_group_id%TYPE;       --
15037             l_cost_group_id          wms_transactions_temp.to_cost_group_id%TYPE;
15038             l_lpn_id                 wms_transactions_temp.lpn_id%TYPE;                 --
15039             l_initial_pri_quantity   wms_transactions_temp.primary_quantity%TYPE;
15040 
15041             l_reservation_id         NUMBER; --
15042             l_needed_quantity        NUMBER; --
15043             l_sec_needed_quantity    NUMBER; --           -- new
15044             l_grade_code             VARCHAR2(150); --           -- new
15045             l_cur_rec                NUMBER;
15046 
15047             -- variables needed for qty tree
15048             l_qoh                    NUMBER;
15049             l_rqoh                   NUMBER;
15050             l_qr                     NUMBER;
15051             l_qs                     NUMBER;
15052             l_att                    NUMBER;
15053             l_atr                    NUMBER;
15054             l_tree_mode              NUMBER;
15055             l_tree_id                NUMBER;
15056             l_sqoh                    NUMBER;           -- new
15057             l_srqoh                   NUMBER;           -- new
15058             l_sqr                     NUMBER;           -- new
15059             l_sqs                     NUMBER;           -- new
15060             l_satt                    NUMBER;           -- new
15061             l_satr                    NUMBER;           -- new
15062 
15063             l_inserted_record        BOOLEAN;
15064             l_allocated_quantity     NUMBER;
15065             l_remaining_quantity     NUMBER;
15066             l_finished               VARCHAR2(1);
15067             l_sec_allocated_quantity     NUMBER;           -- new
15068             l_sec_remaining_quantity     NUMBER;           -- new
15069 
15070            --   Variables to check if Item is Lot and serial contriled
15071 
15072             l_lot_status_enabled      VARCHAR2(1);
15073             l_default_lot_status_id   NUMBER := NULL;
15074             l_serial_status_enabled   VARCHAR2(1);
15075             l_default_serial_status_id NUMBER;
15076 
15077 
15078             l_serial_control_code     NUMBER;
15079             l_is_serial_control       NUMBER;
15080 
15081             l_unit_number             VARCHAR2(30);
15082             l_allowed                 VARCHAR2(1) := 'Y';
15083             l_serial_allowed          VARCHAR2(1) := 'Y';
15084 
15085             g_trace_recs              wms_search_order_globals_pvt.pre_suggestions_record_tbl;
15086 
15087             l_debug                  NUMBER;         -- 1 for debug is on , 0 for debug is off
15088             l_progress               VARCHAR2(10);   -- local variable to track program progress,
15089 
15090                                                      -- especially useful when exception occurs
15091             l_serial_number          NUMBER;         -- [ new code ]
15092 
15093 	  -- LPN Status Project
15094              l_onhand_status_trx_allowed VARCHAR2(1);
15095              l_default_status_id        NUMBER ;
15096           -- LPN Status Project
15097 
15098           cursor lpn_serial_cur(l_lpn_id NUMBER ) is
15099           SELECT STATUS_ID FROM MTL_SERIAL_NUMBERS
15100           WHERE INVENTORY_ITEM_ID = P_INVENTORY_ITEM_ID
15101           AND LPN_ID = l_lpn_id;
15102 
15103 
15104   BEGIN
15105 
15106      IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
15107         g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
15108      END IF;
15109      l_debug := g_debug;
15110      l_progress := 10;
15111 
15112      l_tree_id := p_tree_id;
15113 
15114      IF l_debug = 1 THEN
15115         log_procedure(l_api_name, 'QuickPick', 'enter '|| g_pkg_name || '.' || l_api_name);
15116      END IF;
15117      -- end of debugging section
15118      --
15119      -- Standard start of API savepoint
15120      SAVEPOINT  QuickPicksp;
15121 
15122      -- Standard call to check for call compatibility
15123      IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
15124        RAISE fnd_api.g_exc_unexpected_error;
15125      END IF;
15126      -- Initialize message list if p_init_msg_list is set to TRUE
15127      IF fnd_api.to_boolean(p_init_msg_list) THEN
15128        fnd_msg_pub.initialize;
15129      END IF;
15130      -- Initialize API return status to success
15131      x_return_status  := fnd_api.g_ret_sts_success;
15132      -- Initialize functional return status to completed
15133      x_finished       := fnd_api.g_true;
15134      -- Validate input parameters and pre-requisites, if validation level
15135      -- requires this
15136 
15137      IF p_validation_level <> fnd_api.g_valid_level_none THEN
15138        IF l_debug = 1 THEN
15139           log_statement(l_api_name, 'Quick Pick',
15140         'p_validation_level <> fnd_api.g_valid_level_none ');
15141        END IF;
15142 
15143      IF p_type_code IS NULL
15144         OR p_type_code = fnd_api.g_miss_num
15145         OR p_type_code = 1 THEN
15146         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15147            fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
15148            log_error_msg(l_api_name, 'type_code_missing');
15149            fnd_msg_pub.ADD;
15150         END IF;
15151         RAISE fnd_api.g_exc_error;
15152      END IF;
15153 
15154      IF l_debug = 1 THEN
15155         log_statement(l_api_name, 'Quick Pick',
15156                  'p_transaction_temp_id  ' || p_transaction_temp_id );
15157      END IF;
15158 
15159      IF p_transaction_temp_id IS NULL
15160         OR p_transaction_temp_id = fnd_api.g_miss_num THEN
15161         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15162            fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
15163            log_error_msg(l_api_name, 'trx_req_line_id_missing');
15164            fnd_msg_pub.ADD;
15165         END IF;
15166 
15167         RAISE fnd_api.g_exc_error;
15168      END IF;
15169 
15170      IF l_debug = 1 THEN
15171         log_statement(l_api_name, 'Quick Pick',
15172            'p_organization_id   ' ||  p_organization_id  );
15173      END IF;
15174 
15175   	     IF p_organization_id IS NULL
15176   	        OR p_organization_id = fnd_api.g_miss_num THEN
15177   	        IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15178   	           fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
15179   	           log_error_msg(l_api_name, 'org_id_missing');
15180   	           fnd_msg_pub.ADD;
15181   	        END IF;
15182 
15183   	        RAISE fnd_api.g_exc_error;
15184   	     END IF;
15185 
15186              IF l_debug = 1 THEN
15187 	        log_statement(l_api_name, 'Quick Pick',
15188 	       		    'p_Inventory_item_id_id   ' ||  p_inventory_item_id );
15189               END IF;
15190 
15191   	     IF p_inventory_item_id IS NULL
15192   	        OR p_inventory_item_id = fnd_api.g_miss_num THEN
15193   	        IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15194   	           fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
15195   	           log_error_msg(l_api_name, 'item_id_missing');
15196   	           fnd_msg_pub.ADD;
15197   	        END IF;
15198 
15199   	        RAISE fnd_api.g_exc_error;
15200   	      END IF;
15201 
15202             /**  Commented for bug 4006426
15203               IF l_debug = 1 THEN
15204  	        log_statement(l_api_name, 'Quick Pick', 'qty Tree =>' || p_tree_id );
15205               END IF;
15206 
15207   	      IF  (p_tree_id IS NULL
15208   		 OR p_tree_id = fnd_api.g_miss_num
15209   		) THEN
15210   	        IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15211   	           fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
15212   	           log_error_msg(l_api_name, 'qty_tree_id_missing');
15213   	           fnd_msg_pub.ADD;
15214   	         END IF;
15215 
15216   	         RAISE fnd_api.g_exc_error;
15217   	        END IF;
15218 
15219                 IF l_debug = 1 THEN
15220  	           log_statement(l_api_name, 'Quick Pick', 'finished validations and qty tree init' );
15221                 END IF;
15222                 */
15223             END IF;
15224 
15225    -- LPN Status Project
15226             if (inv_cache.set_org_rec(p_organization_id)) then
15227                l_default_status_id :=  nvl(inv_cache.org_rec.default_status_id,-1);
15228             end if;
15229   -- LPN Status Project
15230              --
15231              -- backup qty tree
15232            If p_tree_id IS NOT NULL  THEN  -- Added for bug # 4006426
15233 
15234             IF l_debug = 1 THEN
15235               log_statement(l_api_name, 'backup_tree',
15236                 'Calling inv_quantity_tree_pvt.backup_tree');
15237             END IF;
15238 
15239            inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
15240 
15241            IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15242               IF l_debug = 1 THEN
15243                  log_statement(l_api_name, 'backup_tree_unexp_err',
15244                 'Unexpected error from inv_quantity_tree_pvt.backup_tree');
15245               END IF;
15246               RAISE fnd_api.g_exc_unexpected_error;
15247            ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15248               IF l_debug = 1 THEN
15249                  log_statement(l_api_name, 'backup_tree_err',
15250                 'Error from inv_quantity_tree_pvt.backup_tree');
15251               END IF;
15252               RAISE fnd_api.g_exc_error;
15253            END IF;
15254         END IF;   --- Added for bug # 4006426
15255 
15256            g_locs_index       	:= 0;
15257            g_locs.DELETE;
15258            l_cur_rec      	:= 0; 	 --initialize pointer to next rec
15259 
15260            IF l_debug = 1 THEN
15261  	      log_statement(l_api_name, 'Quick Pick',
15262  	                    'Check if item is lot  status / Serial Status  enabled');
15263            END IF;
15264 
15265            --Check if item is lot  status / Serial Status  enabled --
15266            inv_material_status_grp.get_lot_serial_status_control(
15267           	 p_organization_id	 	=> p_organization_id
15268           	,p_inventory_item_id	 	=> p_inventory_item_id
15269           	,x_return_status	 	=> x_return_status
15270           	,x_msg_count		 	=> x_msg_count
15271           	,x_msg_data		 	=> x_msg_data
15272           	,x_lot_status_enabled    	=> l_lot_status_enabled
15273           	,x_default_lot_status_id    	=> l_default_lot_status_id
15274           	,x_serial_status_enabled    	=> l_serial_status_enabled
15275           	,x_default_serial_status_id 	=> l_default_serial_status_id);
15276 
15277            wms_re_common_pvt.initinputpointer; -- Initialize the pointer
15278                    			       -- to the first trx detail input line
15279 
15280            IF l_debug = 1 THEN
15281  	      log_statement(l_api_name, 'Quick Pick',
15282  	                   'Initialize the pointer to the first trx detail input line');
15283  	      log_statement(l_api_name, 'Quick Pick',
15284  	                   'Loop through all the trx detail input lines');
15285            END IF;
15286 
15287                -- Loop through all the trx detail input lines
15288                WHILE TRUE LOOP
15289                   IF l_debug = 1 THEN
15290                      log_statement(l_api_name, 'Quick Pick',
15291  	                   'Get the next trx detail input line ');
15292                   END IF;
15293 
15294                   -- Get the next trx detail input line
15295                   wms_re_common_pvt.getnextinputline(
15296                          l_pp_transaction_temp_id
15297                        , l_revision
15298                        , l_lot_number
15299                        , l_lot_expiration_date
15300                        , l_from_subinventory_code
15301                        , l_from_locator_id
15302                        , l_from_cost_group_id
15303                        , l_to_subinventory_code
15304                        , l_to_locator_id
15305                        , l_to_cost_group_id
15306                        , l_needed_quantity
15307                        , l_sec_needed_quantity
15308                        , l_grade_code
15309                        , l_reservation_id
15310                        , l_serial_number -- [ new code ]
15311                        , l_lpn_id
15312                   );
15313                  EXIT WHEN l_pp_transaction_temp_id IS NULL;
15314                  IF l_debug = 1 THEN
15315 		    log_statement(l_api_name, 'Quick Pick',
15316 		  	          'Get sub/Locator /Lot / serial status allowed'  || l_needed_quantity );
15317                  END IF;
15318               -- Get sub/Locator /Lot / serial status allowed  --
15319 
15320          --LPN Status Project
15321                    IF l_debug = 1 THEN
15322 	                log_statement(l_api_name, 'Came to LPN Status Project ', l_onhand_status_trx_allowed);
15323                     END IF;
15324 
15325 
15326                 l_onhand_status_trx_allowed := 'Y';
15327 
15328                IF l_default_status_id = -1 THEN
15329                     l_onhand_status_trx_allowed:='N';
15330 
15331                    -- Get sub/Locator /Lot / serial status allowed  --
15332                   l_allowed  := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
15333           			p_transaction_type_id        => p_transaction_type_id
15334           		      , p_organization_id            => p_organization_id
15335           		      , p_inventory_item_id          => p_inventory_item_id
15336           		      , p_subinventory_code          => l_from_subinventory_code
15337           		      , p_locator_id                 => l_from_locator_id
15338           		      , p_lot_number                 => l_lot_number );
15339          		IF (  l_allowed =  'N') then
15340       			      WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SUB_STATUS_NA';
15341 			      fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
15342 			      fnd_msg_pub.ADD;
15343                               fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15344 			       IF l_debug = 1 THEN
15345       				  log_error_msg(l_api_name, x_msg_data);
15346 			       END IF;
15347                         END IF;
15348 
15349 
15350                ELSE
15351                      l_allowed:='N';
15352                      if (inv_cache.item_rec.serial_number_control_code in (1,6)) then
15353 		            l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
15354                                          p_transaction_type_id
15355                                         ,p_organization_id
15356                                         ,p_inventory_item_id
15357                                         ,l_from_subinventory_code
15358                                         ,l_from_locator_id
15359                                         ,l_lot_number
15360 		                        , l_lpn_id);
15361 
15362 	 	              IF l_debug = 1 THEN
15363 	                         log_statement(l_api_name, 'l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
15364                               END IF;
15365 
15366 			   IF (l_onhand_status_trx_allowed =  'N') then
15367       			          WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_DISALLOW_TRANSACTION';
15368 			          fnd_message.set_name('WMS', 'WMS_DISALLOW_TRANSACTION');
15369 			          fnd_msg_pub.ADD;
15370                                   fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15371 			              IF l_debug = 1 THEN
15372       	           			  log_error_msg(l_api_name, x_msg_data);
15373 			               END IF;
15374                             END IF;
15375        	           end if; -- if (inv_cache.item_rec.serial_number_control_code in (1,6))
15376 
15377 	         END IF;  -- IF l_default_status_id = -1
15378 
15379              --LPN Status Project
15380 
15381                  IF ( l_serial_status_enabled = 'Y') then
15382                       IF l_debug = 1 THEN
15383 		 	 log_statement(l_api_name, 'Quick Pick',
15384 		 	     'inside If l_serial_status_enabled =  y ') ;
15385 		 	 log_statement(l_api_name, 'Quick Pick',
15386 		 	    'Calling inv_detail_util_pvt.is_serial_trx_allowed');
15387                       END IF;
15388                       --bug 7171840 changed the code to check the status at serial level rather than item defualt status
15389                       FOR L_LPN_CUR IN lpn_serial_cur(l_lpn_id) LOOP
15390                               l_serial_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
15391                               p_transaction_type_id   => p_transaction_type_id
15392                             ,p_organization_id       => p_organization_id
15393                             ,p_inventory_item_id     => p_inventory_item_id
15394                             ,p_serial_status         => L_LPN_CUR.STATUS_ID ) ;
15395 
15396                         IF L_SERIAL_ALLOWED = 'N' THEN
15397                            log_statement(l_api_name, 'Quick Pick',
15398 		 		  	          'inside If l_serial_status_enabled =  N ') ;
15399                           EXIT;
15400                        END IF;
15401                        L_SERIAL_ALLOWED := 'Y';
15402                    END LOOP ;
15403                       /* commented out for bug 7171840
15404                       l_serial_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
15405           	              p_transaction_type_id   => p_transaction_type_id
15406           	             ,p_organization_id       => p_organization_id
15407           	             ,p_inventory_item_id     => p_inventory_item_id
15408             	             ,p_serial_status         => l_default_serial_status_id ) ;
15409                          end of bug 7171848*/
15410 
15411                  ELSIF ( l_serial_status_enabled = 'N') then
15412                      IF l_debug = 1 THEN
15413 		        log_statement(l_api_name, 'Quick Pick',
15414 		 		  	          'inside If l_serial_status_enabled =  N ') ;
15415                      END IF;
15416                      l_serial_allowed :=  'Y' ;
15417                  END IF;
15418 
15419                  l_cur_rec := l_cur_rec + 1 ;
15420 
15421                  -- Bug # 5512287
15422 		 g_locs(l_cur_rec).quantity            :=  l_needed_quantity;
15423                  g_locs(l_cur_rec).secondary_quantity  :=  l_sec_needed_quantity;
15424 
15425             	 g_locs(l_cur_rec).revision 		:=  l_revision;
15426           	 g_locs(l_cur_rec).lot_number 		:=  l_lot_number;
15427           	 g_locs(l_cur_rec).subinventory_code	:=  l_from_subinventory_code;
15428           	 g_locs(l_cur_rec).locator_id		:=  l_from_locator_id;
15429           	 g_locs(l_cur_rec).cost_group_id	:=  l_from_cost_group_id;
15430           	 g_locs(l_cur_rec).lpn_id		:=  l_lpn_id;
15431 
15432           	 --add record to table
15433       		 g_locs_index            := g_locs_index + 1;
15434 
15435       		 IF l_debug = 1 THEN
15436       		    log_statement(l_api_name, 'loc_index', 'loc index: ' || g_locs_index);
15437                  END IF;
15438 
15439       		IF l_debug = 1 THEN
15440           	   log_statement(l_api_name, 'validate_and_insert', 'Calling  validate_and_insert');
15441           	   log_statement(l_api_name, 'validate_and_insert', 'p_record_id 	'||  l_cur_rec);
15442           	   log_statement(l_api_name, 'validate_and_insert', 'p_needed_quantity 	'||  l_needed_quantity);
15443           	   log_statement(l_api_name, 'validate_and_insert', 'p_needed_sec_quantity 	'||  l_sec_needed_quantity);
15444           	   log_statement(l_api_name, 'validate_and_insert', 'p_organization_id 	'||  p_organization_id);
15445           	   log_statement(l_api_name, 'validate_and_insert', 'p_inventory_item_id'||  p_inventory_item_id);
15446           	   log_statement(l_api_name, 'validate_and_insert', 'p_to_subinventory_code'|| l_to_subinventory_code);
15447           	   log_statement(l_api_name, 'validate_and_insert', 'p_to_locator_id 	'||  l_to_locator_id);
15448           	   log_statement(l_api_name, 'validate_and_insert', 'p_to_cost_group_id '||   l_to_cost_group_id );
15449           	   log_statement(l_api_name, 'validate_and_insert', 'p_primary_uom 	'||   p_primary_uom);
15450           	   log_statement(l_api_name, 'validate_and_insert', 'p_transaction_uom 	'||   p_transaction_uom);
15451           	   log_statement(l_api_name, 'validate_and_insert', 'p_transaction_temp_id'|| p_transaction_temp_id );
15452              	   log_statement(l_api_name, 'validate_and_insert', 'p_type_code 	'||   p_type_code );
15453   		   log_statement(l_api_name, 'validate_and_insert', 'p_reservation_id  	'||   l_reservation_id  );
15454           	   log_statement(l_api_name, 'validate_and_insert', 'p_tree_id 		'||   l_tree_id);
15455           	   log_statement(l_api_name, 'validate_and_insert', 'Insert an Output record into WTT if status allowed');
15456   		 END IF;
15457   		 --  Insert an Output record into WTT if status allowed
15458   		 --
15459   	--LPN Status Project
15460 
15461                 IF l_debug = 1 THEN
15462 			 log_statement(l_api_name, 'l_onhand_status_trx_allowed: ', l_onhand_status_trx_allowed);
15463 		         log_statement(l_api_name, 'l_allowed: ', l_allowed);
15464 			 log_statement(l_api_name, 'l_serial_allowed: ', l_serial_allowed);
15465 		 END IF;
15466 
15467 
15468               IF ( ( nvl(l_allowed, 'Y') =  'Y' OR l_onhand_status_trx_allowed='Y') and  nvl(l_serial_allowed, 'Y')  =  'Y') then
15469         --LPN Status Project
15470                  IF p_tree_id IS NOT NULL THEN  -- Added for bug #4006426
15471 
15472                     IF l_debug = 1 THEN
15473                        log_statement(l_api_name, 'Calling validate_and_insert', '');
15474                     END IF;
15475                       validate_and_insert(
15476                        x_return_status              => x_return_status
15477                      , x_msg_count                  => x_msg_count
15478                      , x_msg_data                   => x_msg_data
15479                      , p_record_id                  => l_cur_rec
15480                      , p_needed_quantity            => l_needed_quantity
15481                      , p_use_pick_uom               => FALSE
15482                      , p_organization_id            => p_organization_id
15483                      , p_inventory_item_id          => p_inventory_item_id
15484                      , p_to_subinventory_code       => l_to_subinventory_code
15485                      , p_to_locator_id              => l_to_locator_id
15486                      , p_to_cost_group_id           => l_to_cost_group_id
15487                      , p_primary_uom                => p_primary_uom
15488                      , p_transaction_uom            => p_transaction_uom
15489                      , p_transaction_temp_id        => p_transaction_temp_id
15490                      , p_type_code                  => p_type_code
15491                      , p_rule_id                    => 0
15492                      , p_reservation_id             => l_reservation_id
15493                      , p_tree_id                    => l_tree_id
15494                      , p_debug_on                   => l_debug_on
15495                      , p_needed_sec_quantity        => l_sec_needed_quantity
15496                      , p_secondary_uom              => p_secondary_uom
15497                      , p_grade_code                 => p_grade_code
15498                      , x_inserted_record            => l_inserted_record
15499                      , x_allocated_quantity         => l_allocated_quantity
15500                      , x_remaining_quantity         => l_remaining_quantity
15501                      , x_sec_allocated_quantity     => l_sec_allocated_quantity
15502                      , x_sec_remaining_quantity     => l_sec_remaining_quantity
15503                      );
15504                  ELSIF p_tree_id is NULL THEN  -- Call the new local procedure validate_and_insert_noqtytree() for bug #4006426
15505 
15506                        IF l_debug = 1 THEN
15507                           log_statement(l_api_name, 'Calling validateNinsert', '');
15508                        END IF;
15509 
15510                          ValidNinsert(
15511                              x_return_status              => x_return_status
15512                            , x_msg_count                  => x_msg_count
15513                            , x_msg_data                   => x_msg_data
15514                            , p_record_id                  => l_cur_rec
15515                            , p_needed_quantity            => l_needed_quantity
15516                            , p_use_pick_uom               => FALSE
15517                            , p_organization_id            => p_organization_id
15518                            , p_inventory_item_id          => p_inventory_item_id
15519                            , p_to_subinventory_code       => l_to_subinventory_code
15520                            , p_to_locator_id              => l_to_locator_id
15521                            , p_to_cost_group_id           => l_to_cost_group_id
15522                            , p_primary_uom                => p_primary_uom
15523                            , p_transaction_uom            => p_transaction_uom
15524                            , p_transaction_temp_id        => p_transaction_temp_id
15525                            , p_type_code                  => p_type_code
15526                            , p_rule_id                    => 0
15527                            , p_reservation_id             => l_reservation_id
15528                            , p_tree_id                    => l_tree_id
15529                            , p_debug_on                   => l_debug_on
15530                            , x_inserted_record            => l_inserted_record
15531                            , x_allocated_quantity         => l_allocated_quantity
15532                            , x_remaining_quantity         => l_remaining_quantity
15533                            );
15534                  END IF;
15535 
15536                    IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15537                       IF l_debug = 1 THEN
15538                                 log_statement(l_api_name, 'uerr_validate_insert',
15539                                         'Unexpected error in validate_and_insert');
15540                          END IF;
15541                          RAISE fnd_api.g_exc_unexpected_error;
15542                       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15543                          IF l_debug = 1 THEN
15544                             log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
15545                          END IF;
15546                          RAISE fnd_api.g_exc_error;
15547                       END IF;
15548 
15549                       IF l_inserted_record = FALSE   OR l_allocated_quantity < l_needed_quantity THEN
15550                          fnd_message.set_name('WMS', 'WMS_LPN_UNAVAILABLE');  --- to be Added to Mesg Dict
15551                          fnd_msg_pub.ADD;
15552                          fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15553                          IF l_debug = 1 THEN
15554                           log_error_msg(l_api_name, x_msg_data);
15555                          END IF;
15556 
15557                          WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_LPN_UNAVAILABLE';
15558                          IF p_tree_id IS NOT NULL THEN  -- Bug# 4006426
15559 
15560                              IF l_debug = 1 THEN
15561                                 log_statement(l_api_name, 'insert_failed', 'Record failed to allocation.  Rolling back and ' || 'invalidating LPN');
15562                                 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
15563                              END IF;
15564                              inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
15565                          END IF; -- Bug # 4006426
15566                        END IF;
15567 
15568                          IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15569                             IF l_debug = 1 THEN
15570                                log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
15571                             END IF;
15572                             RAISE fnd_api.g_exc_unexpected_error;
15573                          ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15574                             IF l_debug = 1 THEN
15575                                log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
15576                             END IF;
15577                             RAISE fnd_api.g_exc_error;
15578                          END IF;
15579                       ELSE
15580 
15581 			 IF (  l_allowed =  'N') then
15582 			       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SUB_STATUS_NA';
15583 			       fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
15584 			       fnd_msg_pub.ADD;
15585 
15586 			       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15587 			       IF l_debug = 1 THEN
15588 				  log_error_msg(l_api_name, x_msg_data);
15589 			       END IF;
15590 
15591 			 ELSIF l_serial_allowed =  'N' then
15592 			       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SERIAL_STATUS_NA' ;
15593 			       fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
15594 			       fnd_msg_pub.ADD;
15595 			       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15596 
15597 			       IF l_debug = 1 THEN
15598 				  log_error_msg(l_api_name, x_msg_data);
15599 			       END IF;
15600 			 END IF;
15601                       END IF;
15602 
15603                    -- <<nextoutputrecord>>
15604                    l_cur_rec  := g_locs(l_cur_rec).next_rec;
15605 
15606                 END LOOP;
15607       EXCEPTION
15608           WHEN fnd_api.g_exc_error THEN
15609 
15610                 ROLLBACK TO QuickPicksp;
15611                 freeglobals;
15612                 x_return_status  := fnd_api.g_ret_sts_error;
15613                 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15614 
15615                 IF l_debug = 1 THEN
15616                    log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
15617                 END IF;
15618 
15619           WHEN fnd_api.g_exc_unexpected_error THEN
15620                 ROLLBACK TO QuickPicksp;
15621                 freeglobals;
15622                 x_return_status  := fnd_api.g_ret_sts_unexp_error;
15623                 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15624 
15625                 IF l_debug = 1 THEN
15626                    log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
15627                 END IF;
15628 
15629           WHEN OTHERS THEN
15630                 ROLLBACK TO QuickPicksp;
15631                 freeglobals;
15632                 x_return_status  := fnd_api.g_ret_sts_unexp_error;
15633                 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15634                   fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
15635                 END IF;
15636                 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15637 
15638                 IF l_debug = 1 THEN
15639                    log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
15640                 END IF;
15641       END QuickPick;
15642 
15643   -- LG convergence
15644   --
15645   -- API name    : get_available_inventory
15646   -- Type        : Private
15647   -- Function    : Applies a wms rule to the given transaction
15648   --               input parameters and creates recommendations
15649   -- Pre-reqs    : Record in WMS_STRATEGY_MAT_TXN_TMP_V uniquely
15650   --               identified by parameters p_transaction_temp_id and
15651   --               p_type_code ( base table for the view is
15652   --               MTL_MATERIAL_TRANSACTIONS_TEMP );
15653   --               At least one transaction detail record in
15654   --               WMS_TRX_DETAILS_TMP_V identified by line type code = 1
15655   --               and parameters p_transaction_temp_id and p_type_code
15656   --               ( base tables are MTL_MATERIAL_TRANSACTIONS_TEMP and
15657   --               WMS_TRANSACTIONS_TEMP, respectively );
15658   --               Rule record has to exist in WMS_RULES_B uniquely
15659   --               identified by parameter p_rule_id;
15660   --     Package WMS_RULE_(RULEID) must exist;
15661   --               If picking, quantity tree has to exist, created through
15662   --               INV_Quantity_Tree_PVT.Create_Tree and uniquely identified
15663   --               by parameter p_tree_id
15664   -- Parameters  :
15665   --   p_api_version          Standard Input Parameter
15666   --   p_init_msg_list        Standard Input Parameter
15667   --   p_commit               Standard Input Parameter
15668   --   p_validation_level     Standard Input Parameter
15669   --   p_rule_id              Identifier of the rule to apply
15670   --   p_type_code            Type code of the rule
15671   --   p_partial_success_allowed_flag
15672   --            'Y' or 'N'
15673   --   p_transaction_temp_id  Identifier for the record in view
15674   --            wms_strategy_mat_txn_tmp_v that represents
15675   --            the request for detailing
15676   --   p_organization_id      Organization identifier
15677   --   p_inventory_item_id    Inventory item identifier
15678   --   p_transaction_uom      Transaction UOM code
15679   --   p_primary_uom          Primary UOM code
15680   --   p_tree_id              Identifier for the quantity tree
15681   --
15682   -- Output Parameters
15683   --   x_return_status        Standard Output Parameter
15684   --   x_msg_count            Standard Output Parameter
15685   --   x_msg_data             Standard Output Parameter
15686   --   x_finished             whether the rule has found enough quantity to
15687   --                          find a location that completely satisfy
15688   --                          the requested quantity (value is 'Y' or 'N')
15689   --
15690   -- Version
15691   --   Currently version is 1.0
15692   --
15693   -- Notes       : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
15694   --               This API must be called internally by
15695   --               WMS_Strategy_PVT.Apply only !
15696   --APPLY
15697   PROCEDURE get_available_inventory(
15698     p_api_version                  IN            NUMBER
15699   , p_init_msg_list                IN            VARCHAR2
15700   , p_commit                       IN            VARCHAR2
15701   , p_validation_level             IN            NUMBER
15702   , x_return_status                OUT NOCOPY    VARCHAR2
15703   , x_msg_count                    OUT NOCOPY    NUMBER
15704   , x_msg_data                     OUT NOCOPY    VARCHAR2
15705   , p_rule_id                      IN            NUMBER
15706   , p_type_code                    IN            NUMBER
15707   , p_partial_success_allowed_flag IN            VARCHAR2
15708   , p_transaction_temp_id          IN            NUMBER
15709   , p_organization_id              IN            NUMBER
15710   , p_inventory_item_id            IN            NUMBER
15711   , p_transaction_uom              IN            VARCHAR2
15712   , p_primary_uom                  IN            VARCHAR2
15713   , p_transaction_type_id          IN            NUMBER
15714   , p_tree_id                      IN            NUMBER
15715   , x_finished                     OUT NOCOPY    VARCHAR2
15716   , p_detail_serial                IN            BOOLEAN
15717   , p_from_serial                  IN            VARCHAR2
15718   , p_to_serial                    IN            VARCHAR2
15719   , p_detail_any_serial            IN            NUMBER
15720   , p_unit_volume                  IN            NUMBER
15721   , p_volume_uom_code              IN            VARCHAR2
15722   , p_unit_weight                  IN            NUMBER
15723   , p_weight_uom_code              IN            VARCHAR2
15724   , p_base_uom_code                IN            VARCHAR2
15725   , p_lpn_id                       IN            NUMBER
15726   , p_unit_number                  IN            VARCHAR2
15727   , p_simulation_mode              IN            NUMBER
15728   , p_project_id                   IN            NUMBER
15729   , p_task_id                      IN            NUMBER
15730   ) IS
15731     -- API standard variables
15732     l_api_version   CONSTANT NUMBER                                              := 1.0;
15733     l_api_name      CONSTANT VARCHAR2(30)                                        := 'Apply';
15734     -- variables needed for dynamic SQL
15735     l_cursor                 INTEGER;
15736     l_rows                   INTEGER;
15737     -- rule dynamic SQL input variables
15738     l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE;
15739     l_revision               wms_transactions_temp.revision%TYPE  := null;
15740     l_lot_number             wms_transactions_temp.lot_number%TYPE  := null;
15741     l_lot_expiration_date    wms_transactions_temp.lot_expiration_date%TYPE;
15742     l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
15743     l_to_subinventory_code   wms_transactions_temp.to_subinventory_code%TYPE;
15744     l_subinventory_code      wms_transactions_temp.to_subinventory_code%TYPE;
15745     l_from_locator_id        wms_transactions_temp.from_locator_id%TYPE;
15746     l_to_locator_id          wms_transactions_temp.to_locator_id%TYPE;
15747     l_locator_id             wms_transactions_temp.to_locator_id%TYPE;
15748     l_from_cost_group_id     wms_transactions_temp.from_cost_group_id%TYPE;
15749     l_to_cost_group_id       wms_transactions_temp.to_cost_group_id%TYPE;
15750     l_cost_group_id          wms_transactions_temp.to_cost_group_id%TYPE;
15751     l_lpn_id                 wms_transactions_temp.lpn_id%TYPE  := null;
15752     l_initial_pri_quantity   wms_transactions_temp.primary_quantity%TYPE;
15753     -- rule dynamic SQL output variables
15754     l_orevision              wms_transactions_temp.revision%TYPE;
15755     l_olot_number            wms_transactions_temp.lot_number%TYPE;
15756     l_olot_expiration_date   wms_transactions_temp.lot_expiration_date%TYPE;
15757     l_osubinventory_code     wms_transactions_temp.from_subinventory_code%TYPE;
15758     l_olocator_id            wms_transactions_temp.from_locator_id%TYPE;
15759     l_olocator_id_prev       wms_transactions_temp.from_locator_id%TYPE;
15760     l_olocator_id_new        wms_transactions_temp.from_locator_id%TYPE;
15761     l_ocost_group_id         wms_transactions_temp.from_cost_group_id%TYPE;
15762     l_olpn_id                wms_transactions_temp.lpn_id%TYPE;
15763     l_possible_quantity      wms_transactions_temp.primary_quantity%TYPE;
15764     l_possible_trx_qty       wms_transactions_temp.transaction_quantity%TYPE;
15765     l_reservation_id         wms_transactions_temp.reservation_id%TYPE;
15766     -- variables needed for qty tree
15767     l_qoh                    NUMBER;
15768     l_rqoh                   NUMBER;
15769     l_qr                     NUMBER;
15770     l_qs                     NUMBER;
15771     l_att                    NUMBER;
15772     l_atr                    NUMBER;
15773     --
15774     l_rule_func_sql          LONG;
15775     l_rule_result            NUMBER;
15776     l_dummy                  NUMBER;
15777     l_pack_exists            NUMBER;
15778     l_serial_control_code    NUMBER;
15779     l_is_serial_control      NUMBER;
15780     l_package_name           VARCHAR2(128);
15781     l_msg_data               VARCHAR2(240);
15782     l_msg_count              NUMBER;
15783     l_rule_id                NUMBER;
15784     l_unit_number            VARCHAR2(30);
15785     --variables related to pick by UOM
15786     l_uom_code               VARCHAR2(3);
15787     l_order_by_string        VARCHAR2(1000);
15788     l_consist_string         VARCHAR2(1000);
15789     l_cur_order_by_string    VARCHAR2(1000)                                      := '-9999999';
15790     l_default_pick_rule      NUMBER;
15791     l_default_put_rule       NUMBER;
15792     l_allowed                VARCHAR2(1);
15793     l_loc_avail_units        NUMBER;
15794     l_capacity_updated       BOOLEAN;
15795     l_consider_staging_capacity   BOOLEAN; --Added bug3237702
15796     l_return_status          VARCHAR2(1);
15797     l_consist_exists         BOOLEAN;
15798     l_comingle               VARCHAR2(1);
15799     l_serial_number          VARCHAR2(30);
15800     l_detail_serial          NUMBER;
15801     l_found                  BOOLEAN;
15802     l_first_serial           NUMBER;
15803     l_locs_index             NUMBER; --index to v_locs table
15804     l_debug_on               BOOLEAN;
15805     l_uom_index              NUMBER;
15806     l_lpn_controlled_flag    NUMBER;
15807     l_check_cg               BOOLEAN;
15808     l_restrict_subs_code     NUMBER;
15809     l_restrict_locs_code     NUMBER;
15810     l_quantity_function      NUMBER;
15811     v_current_row            t_location_rec;
15812     --added to support allocation mode
15813     l_cur_lpn_group          NUMBER;
15814     l_cur_lpn_rec            NUMBER;
15815     l_needed_quantity        NUMBER;
15816     l_inserted_record        BOOLEAN;
15817     l_expected_quantity      NUMBER;
15818     l_allocated_quantity     NUMBER;
15819     l_remaining_quantity     NUMBER;
15820     l_sec_inserted_record    BOOLEAN;                   -- new
15821     l_sec_expected_quantity  NUMBER;                    -- new
15822     l_sec_allocated_quantity NUMBER;                    -- new
15823     l_sec_remaining_quantity NUMBER;                    -- new
15824     l_sec_needed_quantity    NUMBER;                    -- new
15825     l_grade_code             VARCHAR2(150);             -- new
15826     l_allocation_mode        NUMBER;
15827     l_cur_uom_rec            NUMBER;
15828     l_first_uom_rec          NUMBER;
15829     l_last_uom_rec           NUMBER;
15830     l_finished               BOOLEAN;
15831     l_cur_consist_group      NUMBER;
15832     l_use_pick_uom           BOOLEAN;
15833     l_order_by_rank          NUMBER                                              := 0;
15834     l_cur_rec                NUMBER;
15835     l_prev_rec               NUMBER;
15836     l_next_rec               NUMBER;
15837     l_hash_size              NUMBER;
15838     l_sub_rsv_type	     NUMBER;
15839 
15840     --added to support pjm
15841     l_project_id             NUMBER;
15842     l_oproject_id            NUMBER;
15843     l_task_id                NUMBER;
15844     l_otask_id               NUMBER;
15845     l_input_lpn_id           NUMBER;
15846     --- Initilization of Ref cursors for Pick and putaway rules
15847 -- Added to pass into DoProjectCheck new parameter used in other apply procedure  Bug3237702
15848     l_dummy_loc		NUMBER;
15849 
15850     v_pick_cursor            wms_rule_pvt.cv_pick_type;
15851     v_put_cursor             wms_rule_pvt.cv_put_type;
15852 
15853     l_debug                  NUMBER;   -- 1 for debug is on , 0 for debug is off
15854     l_progress 		     VARCHAR2(10);  -- local variable to track program progress,
15855                                             -- especially useful when exception occurs
15856 
15857 
15858     --cursor to get default rule ids from mtl_parameters table
15859     CURSOR l_default_rules IS
15860       SELECT default_wms_picking_rule_id
15861            , default_put_away_rule_id
15862         FROM mtl_parameters
15863        WHERE organization_id = p_organization_id;
15864 
15865     --cursor used to determine if item is lot controlled
15866     CURSOR l_cur_serial IS
15867       SELECT serial_number_control_code
15868            , NVL(restrict_subinventories_code, 2)
15869            , NVL(restrict_locators_code, 2)
15870         FROM mtl_system_items
15871        WHERE organization_id = p_organization_id
15872          AND inventory_item_id = p_inventory_item_id;
15873 
15874     --cursor used to determine if the rule package exists
15875     CURSOR l_pack_gen IS
15876       SELECT COUNT(object_name)
15877         FROM user_objects
15878        WHERE object_name = l_package_name;
15879 
15880     --cursor used to determine if suggestions should be minimized
15881     -- for this rule.  This flag affects how the Pick UOM functionality
15882     -- works.
15883     CURSOR c_allocation_mode IS
15884       SELECT allocation_mode_id
15885            , qty_function_parameter_id
15886         FROM wms_rules_b
15887        WHERE rule_id = l_rule_id;
15888 
15889     --cursor used to determine if rule has any consistency requirements
15890     CURSOR l_consist IS
15891       SELECT consistency_id
15892         FROM wms_rule_consistencies
15893        WHERE rule_id = l_rule_id;
15894 
15895     --cursor to get lpn controlled flag from subinventory
15896     CURSOR c_subinventory IS
15897       SELECT lpn_controlled_flag, reservable_type
15898         FROM mtl_secondary_inventories
15899        WHERE organization_id = p_organization_id
15900          AND secondary_inventory_name = l_osubinventory_code;
15901 
15902     --cursor to get the total quantity for the LPN
15903     CURSOR c_lpn_quantity IS
15904       SELECT SUM(primary_transaction_quantity)
15905         FROM mtl_onhand_quantities_detail
15906        WHERE lpn_id = v_current_row.lpn_id;
15907 
15908 
15909   BEGIN
15910     --
15911     l_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
15912     l_progress := 10;
15913     -- debugging portion
15914     -- can be commented ut for final code
15915     if nvl(inv_cache.is_pickrelease, FALSE) THEN
15916       If (l_debug = 1) then
15917        log_event(l_api_name, 'Check if Pick Release', 'True');
15918       End if;
15919       l_consider_staging_capacity := FALSE;
15920     else
15921       If (l_debug = 1) then
15922        log_event(l_api_name, 'Check if Pick Release', 'False');
15923       End if;
15924       l_consider_staging_capacity := TRUE;
15925     end if;
15926     IF inv_pp_debug.is_debug_mode THEN
15927       inv_pp_debug.send_message_to_pipe('enter '|| g_pkg_name || '.'
15928               || l_api_name);
15929     END IF;
15930     IF l_debug = 1 THEN
15931        log_procedure(l_api_name, 'start', 'Start Apply');
15932     END IF;
15933     -- end of debugging section
15934     --
15935     -- Standard start of API savepoint
15936     SAVEPOINT applyrulesp;
15937 
15938     -- Standard call to check for call compatibility
15939     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
15940       RAISE fnd_api.g_exc_unexpected_error;
15941     END IF;
15942 
15943     -- Initialize message list if p_init_msg_list is set to TRUE
15944     IF fnd_api.to_boolean(p_init_msg_list) THEN
15945       fnd_msg_pub.initialize;
15946     END IF;
15947 
15948     --
15949     -- Initialize API return status to success
15950     x_return_status  := fnd_api.g_ret_sts_success;
15951     --
15952     -- Initialize functional return status to completed
15953     x_finished       := fnd_api.g_true;
15954 
15955     --
15956     -- Validate input parameters and pre-requisites, if validation level
15957     -- requires this
15958     IF p_validation_level <> fnd_api.g_valid_level_none THEN
15959       IF p_type_code IS NULL
15960          OR p_type_code = fnd_api.g_miss_num THEN
15961         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15962           fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
15963           fnd_msg_pub.ADD;
15964           IF l_debug = 1 THEN
15965              log_error_msg(l_api_name, 'type_code_missing');
15966           END IF;
15967         END IF;
15968         RAISE fnd_api.g_exc_error;
15969     END IF;
15970 
15971     -- init variables
15972     l_revision      := null;
15973     l_lot_number    := null;
15974     l_lpn_id        := null;
15975 
15976       --changed by jcearley on 11/22/99, b/c a null rule_id is now allowed
15977       --  if rule_id is null, use default rule (0 for put away, 1 for pick)
15978 
15979       IF p_rule_id IS NULL OR p_rule_id = fnd_api.g_miss_num THEN
15980            --query org parameters to get user's default rule
15981            IF l_debug = 1 THEN
15982               log_statement(l_api_name,'no_rule','Getting default rule at org level');
15983            END IF;
15984            OPEN l_default_rules;
15985            FETCH l_default_rules INTO l_default_pick_rule, l_default_put_rule;
15986 
15987            IF l_default_rules%NOTFOUND THEN
15988               IF l_debug = 1 THEN
15989                  log_statement(l_api_name, 'org_not_found', 'Organization not found');
15990               END IF;
15991              l_default_pick_rule  := NULL;
15992              l_default_put_rule   := NULL;
15993            END IF;
15994 
15995            CLOSE l_default_rules;
15996 
15997            --if default rule not defined, use default seeded rule
15998            IF p_type_code = 1 THEN --put away
15999              l_rule_id  := l_default_put_rule;
16000 
16001              IF l_rule_id IS NULL THEN
16002                 IF l_debug = 1 THEN
16003                    log_statement(l_api_name, 'no_org_rule_put',
16004                        'Did not find org default put away rule');
16005                 END IF;
16006                 l_rule_id  := 10;
16007              END IF;
16008             ELSE --pick
16009              l_rule_id  := l_default_pick_rule;
16010 
16011              IF l_rule_id IS NULL THEN
16012                 IF l_debug = 1 THEN
16013                    log_statement(l_api_name, 'no_org_rule_put',
16014                        'Did not find org default put away rule');
16015                 END IF;
16016                 l_rule_id  := 2;
16017              END IF;
16018            END IF;
16019            IF l_debug = 1 THEN
16020               log_statement(l_api_name, 'default_rule',
16021                  'Rule being used: ' || l_rule_id);
16022            END IF;
16023       ELSE
16024         l_rule_id  := p_rule_id;
16025       END IF;
16026 
16027       /* Lgao, Bug 5141737 select available will not check this flag, not used */
16028       /*IF p_partial_success_allowed_flag IS NULL
16029          OR p_partial_success_allowed_flag = fnd_api.g_miss_char THEN
16030         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16031           fnd_message.set_name('WMS', 'WMS_PARTIAL_SUCC_FLAG_MISS');
16032 
16033            IF l_debug = 1 THEN
16034               log_error_msg(l_api_name, 'partial_succ_flag_missing');
16035            END IF;
16036           fnd_msg_pub.ADD;
16037         END IF;
16038 
16039         RAISE fnd_api.g_exc_error;
16040       END IF;
16041       */
16042 
16043       IF p_transaction_temp_id IS NULL
16044          OR p_transaction_temp_id = fnd_api.g_miss_num THEN
16045         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16046           fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
16047           fnd_msg_pub.ADD;
16048            IF l_debug = 1 THEN
16049               log_error_msg(l_api_name, 'trx_req_line_id_missing');
16050            END IF;
16051 
16052         END IF;
16053 
16054         RAISE fnd_api.g_exc_error;
16055       END IF;
16056 
16057       IF p_organization_id IS NULL
16058          OR p_organization_id = fnd_api.g_miss_num THEN
16059         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16060           fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
16061           fnd_msg_pub.ADD;
16062           IF l_debug = 1 THEN
16063 	     log_error_msg(l_api_name, 'org_id_missing');
16064           END IF;
16065         END IF;
16066 
16067         RAISE fnd_api.g_exc_error;
16068       END IF;
16069 
16070       IF p_inventory_item_id IS NULL
16071          OR p_inventory_item_id = fnd_api.g_miss_num THEN
16072         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16073           fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
16074           fnd_msg_pub.ADD;
16075           IF l_debug = 1 THEN
16076              log_error_msg(l_api_name, 'item_id_missing');
16077           END IF;
16078         END IF;
16079 
16080         RAISE fnd_api.g_exc_error;
16081       END IF;
16082 
16083       IF  p_type_code = 2
16084           AND (p_tree_id IS NULL
16085                OR p_tree_id = fnd_api.g_miss_num
16086               ) THEN
16087         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16088           fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
16089           fnd_msg_pub.ADD;
16090 
16091           IF l_debug = 1 THEN
16092              log_error_msg(l_api_name, 'qty_tree_id_missing');
16093           END IF;
16094         END IF;
16095 
16096         RAISE fnd_api.g_exc_error;
16097       END IF;
16098     END IF;
16099 
16100     --inv_pp_debug.send_message_to_pipe('finished validations and qty tree init');
16101 
16102     --
16103     -- backup qty tree
16104     IF p_type_code = 2 THEN
16105        IF l_debug = 1 THEN
16106           log_statement(l_api_name, 'backup_tree',
16107                  'Calling inv_quantity_tree_pvt.backup_tree');
16108        END IF;
16109        inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
16110 
16111        IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
16112            IF l_debug = 1 THEN
16113               log_statement(l_api_name, 'backup_tree_unexp_err',
16114                  'Unexpected error from inv_quantity_tree_pvt.backup_tree');
16115            END IF;
16116 
16117            RAISE fnd_api.g_exc_unexpected_error;
16118         ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
16119            IF l_debug = 1 THEN
16120                  log_statement(l_api_name, 'backup_tree_err',
16121                        'Error from inv_quantity_tree_pvt.backup_tree');
16122            END IF;
16123            RAISE fnd_api.g_exc_error;
16124         END IF;
16125 
16126         --does the rule have any consistency restrictions?
16127         OPEN l_consist;
16128         FETCH l_consist INTO l_dummy;
16129 
16130         IF l_consist%NOTFOUND THEN
16131            l_consist_exists  := FALSE;
16132 
16133            IF l_debug = 1 THEN
16134               log_statement(l_api_name, 'consist_exist_false',
16135                     'Consistencies do not exist');
16136            END IF;
16137         ELSE
16138            l_consist_exists  := TRUE;
16139 
16140            IF l_debug = 1 THEN
16141               log_statement(l_api_name, 'consist_exist_true', 'Consistencies exist');
16142            END IF;
16143 
16144         END IF;
16145         CLOSE l_consist;
16146     END IF;
16147 
16148     --
16149 
16150     --Get allocation mode
16151     OPEN c_allocation_mode;
16152     FETCH c_allocation_mode INTO l_allocation_mode, l_quantity_function;
16153 
16154     IF c_allocation_mode%NOTFOUND
16155        OR l_allocation_mode IS NULL THEN
16156       --by default, make allocation mode 3
16157       l_allocation_mode  := 3;
16158     END IF;
16159 
16160     CLOSE c_allocation_mode;
16161 
16162     IF l_allocation_mode IN (3, 4) THEN
16163       l_use_pick_uom  := TRUE;
16164     ELSE
16165       l_use_pick_uom  := FALSE;
16166     END IF;
16167 
16168     -- make sure, everything is clean
16169     freeglobals;
16170     wms_parameter_pvt.clearcache;
16171     --
16172     g_trace_recs.DELETE;
16173     l_debug_on       := isruledebugon(p_simulation_mode);
16174     --query items table to see if item is serial controlled (picking) or if it
16175     -- restricts subs or locators (putaway)
16176     OPEN l_cur_serial;
16177     FETCH l_cur_serial
16178     INTO l_serial_control_code
16179         , l_restrict_subs_code
16180         , l_restrict_locs_code
16181         ;
16182 
16183     IF l_cur_serial%NOTFOUND THEN
16184       l_serial_control_code  := 1;
16185       l_restrict_subs_code   := 2;
16186       l_restrict_locs_code   := 2;
16187     END IF;
16188 
16189     CLOSE l_cur_serial;
16190 
16191     -- Only detail serial numbers if they are prespecified or entered
16192     -- at inventory receipt for this item.
16193     IF p_type_code = 2 THEN --pick
16194       IF l_serial_control_code IN (2, 5) THEN
16195         l_is_serial_control  := 1;
16196       ELSE
16197         l_is_serial_control  := 0;
16198       END IF;
16199     ELSE
16200       l_is_serial_control  := 0;
16201     END IF;
16202 
16203     IF p_detail_serial = TRUE THEN
16204       l_detail_serial  := 1;
16205     ELSE
16206       l_detail_serial  := 0;
16207     END IF;
16208 
16209     IF l_debug = 1 THEN
16210        log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
16211        log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
16212     END IF;
16213 
16214     --get the name of the rule package
16215     getpackagename(l_rule_id, l_package_name);
16216     -- Initialize the pointer to the first trx detail input line
16217     wms_re_common_pvt.initinputpointer;
16218     --
16219     IF l_debug = 1 THEN
16220        log_statement(l_api_name, 'get line ', 'get line input');
16221     END IF;
16222       wms_re_common_pvt.getnextinputline(
16223         l_pp_transaction_temp_id
16224       , l_revision
16225       , l_lot_number
16226       , l_lot_expiration_date
16227       , l_from_subinventory_code
16228       , l_from_locator_id
16229       , l_from_cost_group_id
16230       , l_to_subinventory_code
16231       , l_to_locator_id
16232       , l_to_cost_group_id
16233       , l_needed_quantity
16234       , l_sec_needed_quantity
16235       , l_grade_code
16236       , l_reservation_id
16237       , l_serial_number -- [ new code ]
16238       , l_lpn_id
16239       );
16240 
16241     -- Loop through all the trx detail input lines
16242       IF l_debug = 1 THEN
16243       	log_statement(l_api_name, 'input_rec', 'Got next input line');
16244       	log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
16245       	log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
16246       	log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
16247       	log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
16248       	log_statement(l_api_name, 'input_cg', 'cg:' || l_from_cost_group_id);
16249       	log_statement(l_api_name, 'input_tsub', 'tsub:' || l_to_subinventory_code);
16250       	log_statement(l_api_name, 'input_tloc', 'tloc:' || l_to_locator_id);
16251       	log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
16252       	log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
16253       	log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
16254       	log_statement(l_api_name, 'input_qty', 'sec qty:' || l_sec_needed_quantity);
16255 
16256       END IF;
16257 
16258       IF ((p_project_id IS NOT NULL) AND (l_to_locator_id IS NOT NULL) AND (p_type_code = 1)) THEN
16259         --bug 2400549 - for WIP backflush transfer putaway,
16260         --always use the locator specified on the move order line, even
16261         --if that locator is from common stock (not project)
16262         -- Bug 2666620: BackFlush MO Type Removed. It is now 5. Moreover Txn Action ID is 2 which is
16263         --              already handled.
16264         IF NOT (wms_engine_pvt.g_move_order_type = 5 AND wms_engine_pvt.g_transaction_action_id = 2) THEN
16265 
16266            IF l_debug = 1 THEN
16267               log_statement(l_api_name, 'do_project1', 'Calling do project check');
16268            END IF;
16269 
16270           IF doprojectcheck(l_return_status, l_to_locator_id, p_project_id, p_task_id, l_to_locator_id, l_dummy_loc) THEN
16271 
16272             IF l_debug = 1 THEN
16273                log_statement(l_api_name, 'do_project1_success', 'Do Project Check passed');
16274             END IF;
16275 
16276             NULL;
16277           END IF;
16278         END IF;
16279       END IF;
16280 
16281       --
16282       -- Save the initial input qty for later usage
16283       l_initial_pri_quantity  := l_needed_quantity;
16284       --
16285       l_input_lpn_id          := l_lpn_id;
16286 
16287       IF p_type_code = 2 THEN
16288         --check for null values.  NULL produces error in stored procedure,
16289         --  so we treat -9999 as NULL;
16290         -- since revision is varchar(3), use -99
16291         -- we only want to overwrite revision and lot for pick rules, since
16292         -- we use these values in putaway.
16293         IF (l_revision IS NULL) THEN
16294           --gmi_reservation_util.println('l_revision is null');
16295           l_revision  := '-99';
16296         END IF;
16297 
16298         IF (l_lot_number IS NULL) THEN
16299           l_lot_number  := '-9999';
16300         END IF;
16301       END IF;
16302 
16303       IF (p_type_code = 2) THEN --pick
16304         l_subinventory_code  := l_from_subinventory_code;
16305         l_locator_id         := l_from_locator_id;
16306         l_cost_group_id      := l_from_cost_group_id;
16307       ELSE --put away
16308         l_subinventory_code  := l_to_subinventory_code;
16309         l_locator_id         := l_to_locator_id;
16310         l_cost_group_id      := l_to_cost_group_id;
16311       END IF;
16312 
16313       IF (l_subinventory_code IS NULL) THEN
16314         l_subinventory_code  := '-9999';
16315       END IF;
16316 
16317       IF (l_locator_id IS NULL) THEN
16318         l_locator_id  := -9999;
16319       END IF;
16320 
16321       IF (l_cost_group_id IS NULL) THEN
16322         l_cost_group_id  := -9999;
16323       END IF;
16324 
16325       IF (l_lpn_id IS NULL) THEN
16326         l_lpn_id  := -9999;
16327       END IF;
16328 
16329       IF (p_project_id IS NULL) THEN
16330         l_project_id  := -9999;
16331       ELSE
16332         l_project_id  := p_project_id;
16333       END IF;
16334 
16335       IF (p_task_id IS NULL) THEN
16336         l_task_id  := -9999;
16337       ELSE
16338         l_task_id  := p_task_id;
16339       END IF;
16340 
16341       IF (p_unit_number IS NULL) THEN
16342         l_unit_number  := '-9999';
16343       ELSE
16344         l_unit_number  := p_unit_number;
16345       END IF;
16346 
16347       IF l_debug = 1 THEN
16348          log_statement(l_api_name, 'calling_open_curs', 'Calling open_curs');
16349       END IF;
16350 
16351       -- Bug# 2430429
16352       -- The call to open_curs was not using bind variables.
16353       -- This was causing performance problems
16354 
16355       -- l_cursor := dbms_sql.open_cursor;
16356       --build dynamic PL/SQL for call to stored procedure;
16357       -- open_curs opens the appropriate cursor for the rule;
16358       -- this call has to be dynamic because of the name of the rule package
16359       IF p_type_code = 2 THEN
16360          --pick_open_curs
16361          --inv_pp_debug.send_message_to_pipe('Calling **pick_open_curs ** wms_rule_pick_pkg1.execute');
16362          IF (l_revision IS NULL) THEN
16363            --gmi_reservation_util.println('l_revision is null');
16364            l_revision  := '-99';
16365          END IF;
16366 
16367          IF (l_lot_number IS NULL) THEN
16368            l_lot_number  := '-9999';
16369          END IF;
16370          IF (l_lpn_id IS NULL) THEN
16371             l_lpn_id  := -9999;
16372          END IF;
16373          IF l_debug = 1 THEN
16374                 log_statement(l_api_name, 'pick_open_rule :l_rule_id ', l_rule_id);
16375                 log_statement(l_api_name, 'pick_open_rule :p_organization_id ', p_organization_id);
16376                 log_statement(l_api_name, 'pick_open_rule :p_inventory_item_id ',  p_inventory_item_id);
16377                 log_statement(l_api_name, 'pick_open_rule :p_transaction_type_id ',  p_transaction_type_id);
16378                 log_statement(l_api_name, 'pick_open_rule :l_revision ',  l_revision);
16379                 log_statement(l_api_name, 'pick_open_rule :l_lot_number ',  l_lot_number);
16380                 log_statement(l_api_name, 'pick_open_rule :l_from_subinventory_code ',  l_subinventory_code);
16381                 log_statement(l_api_name, 'pick_open_rule :l_locator_id ',  l_locator_id);
16382                 log_statement(l_api_name, 'pick_open_rule :l_cost_group_id ',  l_cost_group_id);
16383                 log_statement(l_api_name, 'pick_open_rule :l_pp_transaction_temp_id ',  l_pp_transaction_temp_id);
16384                 log_statement(l_api_name, 'pick_open_rule :l_is_serial_control ', l_is_serial_control);
16385                 log_statement(l_api_name, 'pick_open_rule :l_detail_serial ',  l_detail_serial);
16386                 log_statement(l_api_name, 'pick_open_rule :p_detail_any_serial ',  p_detail_any_serial);
16387                 log_statement(l_api_name, 'pick_open_rule :p_from_serial ', p_from_serial);
16388                 log_statement(l_api_name, 'pick_open_rule :p_to_serial ', p_to_serial);
16389                 log_statement(l_api_name, 'pick_open_rule :l_unit_number ',  l_unit_number);
16390                 log_statement(l_api_name, 'pick_open_rule :l_lpn_id ',  l_lpn_id);
16391                 log_statement(l_api_name, 'pick_open_rule :l_project_id ',  l_project_id);
16392                 log_statement(l_api_name, 'pick_open_rule :l_task_id ',  l_task_id);
16393                 log_statement(l_api_name, 'pick_open_rule  :l_rule_result ',l_rule_result);
16394           END IF;
16395           pick_open_rule(
16396             v_pick_cursor
16397           , l_rule_id
16398           , p_organization_id
16399           , p_inventory_item_id
16400           , p_transaction_type_id
16401           , l_revision
16402           , l_lot_number
16403           , l_subinventory_code
16404           , l_locator_id
16405           , l_cost_group_id
16406           , l_pp_transaction_temp_id
16407           , l_is_serial_control
16408           , l_detail_serial
16409           , p_detail_any_serial
16410           , p_from_serial
16411           , p_to_serial
16412           , l_unit_number
16413           , l_lpn_id
16414           , l_project_id
16415           , l_task_id
16416           , l_rule_result
16417           );
16418         --gmi_reservation_util.println('after open rule');
16419           fetchcursorrows(
16420               x_return_status
16421             , x_msg_count
16422             , x_msg_data
16423             , v_pick_cursor
16424             , l_rule_id
16425             );
16426         close_pick_rule(l_rule_id, v_pick_cursor);
16427 
16428         /*FETCH v_pick_cursor bulk collect INTO
16429         WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl;
16430         */
16431         /*FOR i IN 1..WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT
16432         LOOP
16433             WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).organization_id := p_organization_id;
16434             WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).inventory_item_id := p_inventory_item_id;
16435         END LOOP;
16436         gmi_reservation_util.println('fetch the rows, return rows number'
16437                       ||WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT);
16438         FOR i IN 1..WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT
16439         LOOP
16440           gmi_reservation_util.println('fetch the rows, 2nd qty '
16441                       ||WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).secondary_onhand_qty);
16442         end loop;
16443         */
16444      END IF;
16445   EXCEPTION
16446     /*WHEN INVALID_PKG_STATE THEN
16447       x_return_status  := fnd_api.g_ret_sts_unexp_error;
16448       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
16449       fnd_message.set_token('LIST_PKG',  l_list_pkg);
16450       fnd_message.set_token('RULE_NAME', l_package_name);
16451       fnd_msg_pub.ADD;
16452       log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
16453                             || l_list_pkg || ' / ' || l_package_name);
16454      */
16455     WHEN OTHERS THEN
16456       x_return_status  := fnd_api.g_ret_sts_unexp_error;
16457 
16458       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16459         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
16460       END IF;
16461 
16462       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16463       --
16464       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
16465 
16466       -- debugging portion
16467       -- can be commented ut for final code
16468       IF inv_pp_debug.is_debug_mode THEN
16469         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
16470         -- the message retrieved here since it is no longer on the stack
16471         inv_pp_debug.set_last_error_message(SQLERRM);
16472         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
16473         inv_pp_debug.send_last_error_message;
16474       END IF;
16475   -- end of debugging section
16476   END get_available_inventory;
16477 
16478   PROCEDURE FetchCursorRows(
16479     x_return_status       OUT NOCOPY    VARCHAR2
16480   , x_msg_count           OUT NOCOPY    NUMBER
16481   , x_msg_data            OUT NOCOPY    VARCHAR2
16482   , p_cursor              IN            wms_rule_pvt.cv_pick_type
16483   , p_rule_id             IN            NUMBER
16484   ) IS
16485     invalid_pkg_state  exception;
16486     Pragma Exception_Init(invalid_pkg_state, -6508);
16487 
16488     l_list_pkg     VARCHAR2(30);
16489 
16490     l_api_name     VARCHAR2(30)  := 'FetchCursor';
16491     l_rows         NUMBER;
16492     l_func_sql     VARCHAR(1000);
16493     l_cursor       NUMBER;
16494     l_dummy        NUMBER;
16495     l_package_name VARCHAR2(128);
16496     l_ctr          NUMBER        := 0;
16497 
16498 
16499   BEGIN
16500     -- Initialize API return status to success
16501     x_return_status  := fnd_api.g_ret_sts_success;
16502 
16503     --
16504     -- debugging portion
16505     -- can be commented ut for final code
16506     IF inv_pp_debug.is_debug_mode THEN
16507       inv_pp_debug.send_message_to_pipe('enter '|| g_pkg_name || '.' || l_api_name);
16508     END IF;
16509 
16510     log_procedure(l_api_name, 'start', 'Start FetchCursorrows');
16511     -- end of debugging section
16512     --
16513 
16514     --get package name based on rule id
16515     getpackagename(p_rule_id, l_package_name);
16516     log_statement(l_package_name,  'package_name ', l_package_name);
16517     --- calling the static fetch cursor. The name of the rule package will be
16518     --- determined based on the rule_id
16519     --- If the ctr is 1 then there is no subscript ,
16520     --- if ctr = 2 then subscript = 1
16521     --- and if ctr = 3 then subscript = 2, this script is added to the package
16522     --- name.
16523     l_ctr        := wms_rule_gen_pkgs.get_count_no_lock('PICK');
16524     l_list_pkg   :=  'wms_rule_pick_pkg' || l_ctr ;
16525     log_statement(l_package_name,  'l_ctr ', l_ctr);
16526     --log_statement(l_package_name,  'p_cursor ', p_cursor);
16527 
16528     IF (l_ctr = 1) THEN
16529 
16530       wms_rule_pick_pkg1.execute_fetch_available_inv(
16531         p_cursor
16532       , p_rule_id
16533       , x_return_status
16534       );
16535     ELSIF (l_ctr = 2) THEN
16536 
16537       wms_rule_pick_pkg2.execute_fetch_available_inv(
16538         p_cursor
16539       , p_rule_id
16540       , x_return_status
16541       );
16542     ELSIF (l_ctr = 3) THEN
16543       wms_rule_pick_pkg3.execute_fetch_available_inv(
16544         p_cursor
16545       , p_rule_id
16546       , x_return_status
16547       );
16548     END IF;
16549 
16550     IF inv_pp_debug.is_debug_mode THEN
16551       inv_pp_debug.send_message_to_pipe('exit '|| g_pkg_name || '.' || l_api_name);
16552     END IF;
16553     -- end of debugging section
16554     log_procedure(l_api_name, 'end', 'End FetchCursorrows');
16555   --
16556   EXCEPTION
16557     WHEN INVALID_PKG_STATE THEN
16558       x_return_status  := fnd_api.g_ret_sts_unexp_error;
16559       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
16560       fnd_message.set_token('LIST_PKG',  l_list_pkg);
16561       fnd_message.set_token('RULE_NAME', l_package_name);
16562       fnd_msg_pub.ADD;
16563       log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
16564                             || l_list_pkg || ' / ' || l_package_name);
16565 
16566     WHEN OTHERS THEN
16567       x_return_status  := fnd_api.g_ret_sts_unexp_error;
16568 
16569       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16570         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
16571       END IF;
16572 
16573       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16574       --
16575       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
16576 
16577       -- debugging portion
16578       -- can be commented ut for final code
16579       IF inv_pp_debug.is_debug_mode THEN
16580         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
16581         -- the message retrieved here since it is no longer on the stack
16582         inv_pp_debug.set_last_error_message(SQLERRM);
16583         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
16584         inv_pp_debug.send_last_error_message;
16585       END IF;
16586   -- end of debugging section
16587   END FetchCursorRows;
16588   -- end LG convergence
16589 
16590 END wms_rule_pvt;