DBA Data[Home] [Help]

PACKAGE BODY: APPS.WMS_RULE_PVT

Source


1 PACKAGE BODY wms_rule_pvt AS
2   /* $Header: WMSVPPRB.pls 120.109.12020000.14 2013/03/20 20:38:42 sahmahes 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   --               10/15/09 Bug 8638386 Pushkar
31   --                        Reorganize/extend fix 8665496 - for lot conversion + deviation
32   --               12/12/11  Added these 5 new variables as part of Bug 13448337 schiluve
33   --
34   --               g_rule_select_serial_new -- Added this variable to hold the select stmt of
35   --               the newly created parameters in the rule building code
36   --                   g_rule_group_by_new -- Added this variable to hold the group by of the newly
37   --                   created group in the rule building code
38   --               g_rule_order_new -- Added this variable to hold the order by string of the
39   --                   newly created order by in the rule building code
40   --               g_pickuom_serial_case -- Added this variable to hold the value for the specific
41   --                   parameter and object id and when ordering is ascending for the allocation mode id in 4,5
42   --               g_pickuom_serial_flag -- Added this variable to hold the value for the specific
43   --                   parameter and object id and when ordering is ascending for the allocation mode id in 4,5
44   --                   l_order_by_string1 -- Added this variable to hold the newly added order by string
45   --                   l_order_by_string2 -- Added this variable to hold the newly added order by string
46   --
47 
48   --
49   -- Package global variable that stores the package name
50   g_pkg_name             CONSTANT VARCHAR2(30)                                            := 'WMS_Rule_PVT';
51   --
52   -- API versions used within this API
53   g_qty_tree_api_version CONSTANT NUMBER                                                  := 1.0; -- INV_Quantity_Tree_PVT
54   --
55   -- Caching locator record in DoProjectCheck
56   g_locator_id    NUMBER;
57   g_locator       INV_VALIDATE.locator;
58   g_transaction_type_id         NUMBER;
59   g_organization_id         NUMBER;
60   g_inventory_item_id         NUMBER;
61   g_subinventory_code         WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
62   g_allowed                 VARCHAR2(1);
63   g_st_locator_id    NUMBER;
64   g_lpn_controlled_flag         NUMBER;
65 
66   --g_serial_objects_used NUMBER ;
67 
68   -- Caching in function getconversionrate
69   g_gcr_organization_id    NUMBER;
70   g_gcr_inventory_item_id  NUMBER;
71   g_gcr_uom_code           VARCHAR2(3);
72   g_gcr_conversion_rate    NUMBER;
73 
74   g_debug                  NUMBER;
75   --
76   -- constants and global variables needed for dynamic SQL
77   --
78 
79   /* LG. need to talk to gopal, for all the non restircted loc, should do an outter join*/
80   g_put_base_no_restrict          LONG
81   := '
82  select  msei.secondary_inventory_name subinventory_code               --changed
83         ,mil.inventory_location_id locator_id
84         ,msei.organization_id organization_id                          --changed
85         ,mil.project_id project_id
86         ,mil.task_id task_id
87         ,g_inventory_item_id inventory_item_id
88         ,mil.location_current_units location_current_units
89         ,mil.inventory_item_id locator_inventory_item_id
90         ,mil.empty_flag empty_flag
91         ,mil.mixed_items_flag mixed_items_flag
92         ,mil.LAST_UPDATE_DATE
93         ,mil.LAST_UPDATED_BY
94         ,mil.CREATION_DATE
95         ,mil.CREATED_BY
96         ,mil.LAST_UPDATE_LOGIN
97         ,mil.DESCRIPTION
98         ,mil.DESCRIPTIVE_TEXT
99         ,mil.DISABLE_DATE
100         ,mil.INVENTORY_LOCATION_TYPE
101         ,mil.PICKING_ORDER
102         ,mil.PHYSICAL_LOCATION_CODE
103         ,mil.LOCATION_MAXIMUM_UNITS
104         ,mil.LOCATION_WEIGHT_UOM_CODE
105         ,mil.MAX_WEIGHT
106         ,mil.VOLUME_UOM_CODE
107         ,mil.MAX_CUBIC_AREA
108         ,mil.X_COORDINATE
109         ,mil.Y_COORDINATE
110         ,mil.Z_COORDINATE
111         ,mil.INVENTORY_ACCOUNT_ID
112         ,mil.SEGMENT1
113         ,mil.SEGMENT2
114         ,mil.SEGMENT3
115         ,mil.SEGMENT4
116         ,mil.SEGMENT5
117         ,mil.SEGMENT6
118         ,mil.SEGMENT7
119         ,mil.SEGMENT8
120         ,mil.SEGMENT9
121         ,mil.SEGMENT10
122         ,mil.SEGMENT11
123         ,mil.SEGMENT12
124         ,mil.SEGMENT13
125         ,mil.SEGMENT14
126         ,mil.SEGMENT15
127         ,mil.SEGMENT16
128         ,mil.SEGMENT17
129         ,mil.SEGMENT18
130         ,mil.SEGMENT19
131         ,mil.SEGMENT20
132         ,mil.SUMMARY_FLAG
133         ,mil.ENABLED_FLAG
134         ,mil.START_DATE_ACTIVE
135         ,mil.END_DATE_ACTIVE
136         ,mil.ATTRIBUTE_CATEGORY
137         ,mil.ATTRIBUTE1
138         ,mil.ATTRIBUTE2
139         ,mil.ATTRIBUTE3
140         ,mil.ATTRIBUTE4
141         ,mil.ATTRIBUTE5
142         ,mil.ATTRIBUTE6
143         ,mil.ATTRIBUTE7
144         ,mil.ATTRIBUTE8
145         ,mil.ATTRIBUTE9
146         ,mil.ATTRIBUTE10
147         ,mil.ATTRIBUTE11
148         ,mil.ATTRIBUTE12
149         ,mil.ATTRIBUTE13
150         ,mil.ATTRIBUTE14
151         ,mil.ATTRIBUTE15
152         ,mil.REQUEST_ID
153         ,mil.PROGRAM_APPLICATION_ID
154         ,mil.PROGRAM_ID
155         ,mil.PROGRAM_UPDATE_DATE
156         ,mil.PHYSICAL_LOCATION_ID
157         ,mil.PICK_UOM_CODE
158         ,mil.DIMENSION_UOM_CODE
159         ,mil.LENGTH
160         ,mil.WIDTH
161         ,mil.HEIGHT
162         ,mil.LOCATOR_STATUS
163         ,mil.STATUS_ID
164         ,mil.CURRENT_CUBIC_AREA
165         ,mil.AVAILABLE_CUBIC_AREA
166         ,mil.CURRENT_WEIGHT
167         ,mil.AVAILABLE_WEIGHT
168         ,mil.LOCATION_AVAILABLE_UNITS
169         ,mil.SUGGESTED_CUBIC_AREA
170         ,mil.SUGGESTED_WEIGHT
171         ,mil.LOCATION_SUGGESTED_UNITS
172         ,mil.rowid
173    from MTL_ITEM_LOCATIONS mil
174        ,MTL_SECONDARY_INVENTORIES msei
175   where mil.organization_id(+) = msei.organization_id
176     and mil.subinventory_code(+) = msei.secondary_inventory_name
177     and NVL(msei.disable_date, sysdate+1) > sysdate
178     and NVL(mil.disable_date, sysdate+1) > sysdate
179     and mil.ORGANIZATION_ID = g_organization_id
180 '; --8467209.added org_id above
181   g_put_base_sub_restrict         LONG
182   := '
183  select  msei.secondary_inventory_name subinventory_code            -- changed
184         ,mil.inventory_location_id locator_id
185         ,msei.organization_id organization_id                       -- changed
186         ,mil.project_id project_id
187         ,mil.task_id task_id
188         ,g_inventory_item_id inventory_item_id
189         ,mil.location_current_units location_current_units
190         ,mil.inventory_item_id locator_inventory_item_id
191         ,mil.empty_flag empty_flag
192         ,mil.mixed_items_flag mixed_items_flag
193         ,mil.LAST_UPDATE_DATE
194         ,mil.LAST_UPDATED_BY
195         ,mil.CREATION_DATE
196         ,mil.CREATED_BY
197         ,mil.LAST_UPDATE_LOGIN
198         ,mil.DESCRIPTION
199         ,mil.DESCRIPTIVE_TEXT
200         ,mil.DISABLE_DATE
201         ,mil.INVENTORY_LOCATION_TYPE
202         ,mil.PICKING_ORDER
203         ,mil.PHYSICAL_LOCATION_CODE
204         ,mil.LOCATION_MAXIMUM_UNITS
205         ,mil.LOCATION_WEIGHT_UOM_CODE
206         ,mil.MAX_WEIGHT
207         ,mil.VOLUME_UOM_CODE
208         ,mil.MAX_CUBIC_AREA
209         ,mil.X_COORDINATE
210         ,mil.Y_COORDINATE
211         ,mil.Z_COORDINATE
212         ,mil.INVENTORY_ACCOUNT_ID
213         ,mil.SEGMENT1
214         ,mil.SEGMENT2
215         ,mil.SEGMENT3
216         ,mil.SEGMENT4
217         ,mil.SEGMENT5
218         ,mil.SEGMENT6
219         ,mil.SEGMENT7
220         ,mil.SEGMENT8
221         ,mil.SEGMENT9
222         ,mil.SEGMENT10
223         ,mil.SEGMENT11
224         ,mil.SEGMENT12
225         ,mil.SEGMENT13
226         ,mil.SEGMENT14
227         ,mil.SEGMENT15
228         ,mil.SEGMENT16
229         ,mil.SEGMENT17
230         ,mil.SEGMENT18
231         ,mil.SEGMENT19
232         ,mil.SEGMENT20
233         ,mil.SUMMARY_FLAG
234         ,mil.ENABLED_FLAG
235         ,mil.START_DATE_ACTIVE
236         ,mil.END_DATE_ACTIVE
237         ,mil.ATTRIBUTE_CATEGORY
238         ,mil.ATTRIBUTE1
239         ,mil.ATTRIBUTE2
240         ,mil.ATTRIBUTE3
241         ,mil.ATTRIBUTE4
242         ,mil.ATTRIBUTE5
243         ,mil.ATTRIBUTE6
244         ,mil.ATTRIBUTE7
245         ,mil.ATTRIBUTE8
246         ,mil.ATTRIBUTE9
247         ,mil.ATTRIBUTE10
248         ,mil.ATTRIBUTE11
249         ,mil.ATTRIBUTE12
250         ,mil.ATTRIBUTE13
251         ,mil.ATTRIBUTE14
252         ,mil.ATTRIBUTE15
253         ,mil.REQUEST_ID
254         ,mil.PROGRAM_APPLICATION_ID
255         ,mil.PROGRAM_ID
256         ,mil.PROGRAM_UPDATE_DATE
257         ,mil.PHYSICAL_LOCATION_ID
258         ,mil.PICK_UOM_CODE
259         ,mil.DIMENSION_UOM_CODE
260         ,mil.LENGTH
261         ,mil.WIDTH
262         ,mil.HEIGHT
263         ,mil.LOCATOR_STATUS
264         ,mil.STATUS_ID
265         ,mil.CURRENT_CUBIC_AREA
266         ,mil.AVAILABLE_CUBIC_AREA
267         ,mil.CURRENT_WEIGHT
268         ,mil.AVAILABLE_WEIGHT
269         ,mil.LOCATION_AVAILABLE_UNITS
270         ,mil.SUGGESTED_CUBIC_AREA
271         ,mil.SUGGESTED_WEIGHT
272         ,mil.LOCATION_SUGGESTED_UNITS
273   ,mil.rowid
274 from MTL_ITEM_LOCATIONS mil
275        ,MTL_SECONDARY_INVENTORIES msei
276        ,MTL_ITEM_SUB_INVENTORIES misi
277   where mil.organization_id(+) = msei.organization_id
278     and mil.organization_id=g_organization_id ---bug8425620 8665549
279     and mil.subinventory_code(+) = msei.secondary_inventory_name
280     and NVL(msei.disable_date, sysdate+1) > sysdate
281     and NVL(mil.disable_date, sysdate+1) > sysdate
282     and mil.organization_id = misi.organization_id
283     and mil.subinventory_code = misi.secondary_inventory
284     and misi.inventory_item_id = g_inventory_item_id
285 ';
286   g_put_base_loc_restrict         LONG
287   := '
288  select  mil.subinventory_code subinventory_code
289         ,mil.inventory_location_id locator_id
290         ,mil.organization_id organization_id
291         ,mil.project_id project_id
292         ,mil.task_id task_id
293         ,g_inventory_item_id inventory_item_id
294         ,mil.location_current_units location_current_units
295         ,mil.inventory_item_id locator_inventory_item_id
296         ,mil.empty_flag empty_flag
297         ,mil.mixed_items_flag mixed_items_flag
298         ,mil.LAST_UPDATE_DATE
299         ,mil.LAST_UPDATED_BY
300         ,mil.CREATION_DATE
301         ,mil.CREATED_BY
302         ,mil.LAST_UPDATE_LOGIN
303         ,mil.DESCRIPTION
304         ,mil.DESCRIPTIVE_TEXT
305         ,mil.DISABLE_DATE
306         ,mil.INVENTORY_LOCATION_TYPE
307         ,mil.PICKING_ORDER
308         ,mil.PHYSICAL_LOCATION_CODE
309         ,mil.LOCATION_MAXIMUM_UNITS
310         ,mil.LOCATION_WEIGHT_UOM_CODE
311         ,mil.MAX_WEIGHT
312         ,mil.VOLUME_UOM_CODE
313         ,mil.MAX_CUBIC_AREA
314         ,mil.X_COORDINATE
315         ,mil.Y_COORDINATE
316         ,mil.Z_COORDINATE
317         ,mil.INVENTORY_ACCOUNT_ID
318         ,mil.SEGMENT1
319         ,mil.SEGMENT2
320         ,mil.SEGMENT3
321         ,mil.SEGMENT4
322         ,mil.SEGMENT5
323         ,mil.SEGMENT6
324         ,mil.SEGMENT7
325         ,mil.SEGMENT8
326         ,mil.SEGMENT9
327         ,mil.SEGMENT10
328         ,mil.SEGMENT11
329         ,mil.SEGMENT12
330         ,mil.SEGMENT13
331         ,mil.SEGMENT14
332         ,mil.SEGMENT15
333         ,mil.SEGMENT16
334         ,mil.SEGMENT17
335         ,mil.SEGMENT18
336         ,mil.SEGMENT19
337         ,mil.SEGMENT20
338         ,mil.SUMMARY_FLAG
339         ,mil.ENABLED_FLAG
340         ,mil.START_DATE_ACTIVE
341         ,mil.END_DATE_ACTIVE
342         ,mil.ATTRIBUTE_CATEGORY
343         ,mil.ATTRIBUTE1
344         ,mil.ATTRIBUTE2
345         ,mil.ATTRIBUTE3
346         ,mil.ATTRIBUTE4
347         ,mil.ATTRIBUTE5
348         ,mil.ATTRIBUTE6
349         ,mil.ATTRIBUTE7
350         ,mil.ATTRIBUTE8
351         ,mil.ATTRIBUTE9
352         ,mil.ATTRIBUTE10
353         ,mil.ATTRIBUTE11
354         ,mil.ATTRIBUTE12
355         ,mil.ATTRIBUTE13
356         ,mil.ATTRIBUTE14
357         ,mil.ATTRIBUTE15
358         ,mil.REQUEST_ID
359         ,mil.PROGRAM_APPLICATION_ID
360         ,mil.PROGRAM_ID
361         ,mil.PROGRAM_UPDATE_DATE
362         ,mil.PHYSICAL_LOCATION_ID
363         ,mil.PICK_UOM_CODE
364         ,mil.DIMENSION_UOM_CODE
365         ,mil.LENGTH
366         ,mil.WIDTH
367         ,mil.HEIGHT
368         ,mil.LOCATOR_STATUS
369         ,mil.STATUS_ID
370         ,mil.CURRENT_CUBIC_AREA
371         ,mil.AVAILABLE_CUBIC_AREA
372         ,mil.CURRENT_WEIGHT
373         ,mil.AVAILABLE_WEIGHT
374         ,mil.LOCATION_AVAILABLE_UNITS
375         ,mil.SUGGESTED_CUBIC_AREA
376         ,mil.SUGGESTED_WEIGHT
377         ,mil.LOCATION_SUGGESTED_UNITS
378         ,mil.rowid
379    from MTL_ITEM_LOCATIONS mil
380        ,MTL_SECONDARY_INVENTORIES msei
381        ,MTL_ITEM_SUB_INVENTORIES misi
382        ,MTL_SECONDARY_LOCATORS msl
383   where mil.organization_id = msei.organization_id
384     and mil.organization_id=g_organization_id ---bug8425620 8665549
385     and mil.subinventory_code = msei.secondary_inventory_name
386     and NVL(msei.disable_date, sysdate+1) > sysdate
387     and NVL(mil.disable_date, sysdate+1) > sysdate
388     and mil.organization_id = misi.organization_id
389     and mil.subinventory_code = misi.secondary_inventory
390     and misi.inventory_item_id = g_inventory_item_id
391     and mil.organization_id = msl.organization_id
392     and mil.inventory_location_id = msl.secondary_locator
393     and msl.inventory_item_Id = g_inventory_item_id
394 ';
395   g_put_base             CONSTANT LONG
396         := '
397  select  x.organization_id
398         ,x.inventory_item_id
399         ,x.subinventory_code
400         ,x.locator_id
401   from (
402   -- subs not restricted and locator controlled
403   select msi.ORGANIZATION_ID    ORGANIZATION_ID
404         ,msi.INVENTORY_ITEM_ID    INVENTORY_ITEM_ID
405         ,msei.SECONDARY_INVENTORY_NAME  SUBINVENTORY_CODE
406         ,mil.INVENTORY_LOCATION_ID  LOCATOR_ID
407         ,mil.PROJECT_ID     PROJECT_ID
408         ,mil.TASK_ID      TASK_ID
409     from MTL_ITEM_LOCATIONS                      mil
410         ,MTL_SECONDARY_INVENTORIES               msei
411         ,MTL_PARAMETERS                          mp
412         ,MTL_SYSTEM_ITEMS                        msi
413    where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 2
414      and nvl(msi.RESTRICT_LOCATORS_CODE,2)       = 2
415      and mp.ORGANIZATION_ID                      = msi.ORGANIZATION_ID
416      and msei.ORGANIZATION_ID                    = msi.ORGANIZATION_ID
417      and nvl(msei.DISABLE_DATE,sysdate+1)        > sysdate
418      and decode(mp.STOCK_LOCATOR_CONTROL_CODE,
419                 4,decode(msei.LOCATOR_TYPE,
420                          5,nvl(msi.LOCATION_CONTROL_CODE,1),
421                          nvl(msei.LOCATOR_TYPE,1)),
422                 mp.STOCK_LOCATOR_CONTROL_CODE)   > 1
423      and mil.INVENTORY_LOCATION_ID               > 0  -- force U1 to be used
424      and mil.ORGANIZATION_ID                     = msei.ORGANIZATION_ID
425      and mil.SUBINVENTORY_CODE                   = msei.SECONDARY_INVENTORY_NAME
426      and nvl(mil.DISABLE_DATE,sysdate+1)         > sysdate
427   union all
428   -- subs restricted and locator controlled
429   select msi.ORGANIZATION_ID
430         ,msi.INVENTORY_ITEM_ID
431         ,misi.SECONDARY_INVENTORY
432         ,mil.INVENTORY_LOCATION_ID
433         ,mil.PROJECT_ID
434         ,mil.TASK_ID
435     from MTL_ITEM_LOCATIONS                      mil
436         ,MTL_SECONDARY_INVENTORIES               msei
437         ,MTL_ITEM_SUB_INVENTORIES                misi
438         ,MTL_PARAMETERS                          mp
439         ,MTL_SYSTEM_ITEMS                        msi
440    where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 1
441      and nvl(msi.RESTRICT_LOCATORS_CODE,2)       = 2
442      and mp.ORGANIZATION_ID                      = msi.ORGANIZATION_ID
443      and misi.ORGANIZATION_ID                    = msi.ORGANIZATION_ID
444      and misi.INVENTORY_ITEM_ID                  = msi.INVENTORY_ITEM_ID
445      and msei.ORGANIZATION_ID                    = misi.ORGANIZATION_ID
446      and msei.SECONDARY_INVENTORY_NAME           = misi.SECONDARY_INVENTORY
447      and nvl(msei.DISABLE_DATE,sysdate+1)        > sysdate
448      and decode(mp.STOCK_LOCATOR_CONTROL_CODE,
449                 4,decode(msei.LOCATOR_TYPE,
450                          5,nvl(msi.LOCATION_CONTROL_CODE,1),
451                          nvl(msei.LOCATOR_TYPE,1)),
452                 mp.STOCK_LOCATOR_CONTROL_CODE)   > 1
453      and mil.INVENTORY_LOCATION_ID               > 0  -- force U1 to be used
454      and mil.ORGANIZATION_ID                     = misi.ORGANIZATION_ID
455      and mil.SUBINVENTORY_CODE                   = misi.SECONDARY_INVENTORY
456      and nvl(mil.DISABLE_DATE,sysdate+1)         > sysdate
457   union all
458   -- locators restricted
459   select msi.ORGANIZATION_ID
460         ,msi.INVENTORY_ITEM_ID
461         ,misi.SECONDARY_INVENTORY
462         ,msl.SECONDARY_LOCATOR
463         ,mil.PROJECT_ID
464         ,mil.TASK_ID
465     from MTL_ITEM_LOCATIONS                      mil
466         ,MTL_SECONDARY_LOCATORS                  msl
467         ,MTL_SECONDARY_INVENTORIES               msei
468         ,MTL_ITEM_SUB_INVENTORIES                misi
469         ,MTL_PARAMETERS                          mp
470         ,MTL_SYSTEM_ITEMS                        msi
471    where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 1
472      and nvl(msi.RESTRICT_LOCATORS_CODE,2)       = 1
473      and mp.ORGANIZATION_ID                      = msi.ORGANIZATION_ID
474      and misi.ORGANIZATION_ID                    = msi.ORGANIZATION_ID
475      and misi.INVENTORY_ITEM_ID                  = msi.INVENTORY_ITEM_ID
476      and msei.ORGANIZATION_ID                    = misi.ORGANIZATION_ID
477      and msei.SECONDARY_INVENTORY_NAME           = misi.SECONDARY_INVENTORY
478      and nvl(msei.DISABLE_DATE,sysdate+1)        > sysdate
479      and msl.ORGANIZATION_ID                     = misi.ORGANIZATION_ID
480      and msl.INVENTORY_ITEM_ID                   = misi.INVENTORY_ITEM_ID
481      and msl.SUBINVENTORY_CODE                   = misi.SECONDARY_INVENTORY
482      and mil.ORGANIZATION_ID                     = msl.ORGANIZATION_ID
483      and mil.INVENTORY_LOCATION_ID               = msl.SECONDARY_LOCATOR
484      and nvl(mil.DISABLE_DATE,sysdate+1)         > sysdate
485   ) x
486   group by x.organization_id
487          , x.inventory_item_id
488          , x.subinventory_code
489          , x.locator_id
490   ';
491   -- /*LPN Status Project*/
492   g_pick_base_serial_detail              LONG
493   := '
494    select  msn.current_organization_id organization_id
495     ,msn.inventory_item_id
496     ,msn.revision
497     ,msn.lot_number
498     ,lot.expiration_date lot_expiration_date
499     ,msn.current_subinventory_code subinventory_code
500     ,msn.current_locator_id locator_id
501     ,msn.cost_group_id
502     ,msn.status_id   --added status_id
503     ,msn.serial_number
504     ,msn.initialization_date date_received
505     ,1 primary_quantity
506     ,null secondary_quantity                            -- new
507     ,lot.grade_code grade_code                          -- new
508     ,sub.reservable_type
509     ,nvl(loc.reservable_type,1)  locreservable          -- Bug 6719290
510     ,nvl(lot.reservable_type,1)  lotreservable          -- Bug 6719290
511     ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
512     ,WMS_Rule_PVT.GetConversionRate(
513          nvl(loc.pick_uom_code, sub.pick_uom_code)
514         ,msn.current_organization_id
515         ,msn.inventory_item_id) conversion_rate
516     ,msn.lpn_id lpn_id
517     ,loc.project_id project_id
518     ,loc.task_id task_id
519           ,NULL locator_inventory_item_id
520           ,NULL empty_flag
521           ,NULL location_current_units
522    from  mtl_serial_numbers msn
523     ,mtl_secondary_inventories sub
524     ,mtl_item_locations loc
525     ,mtl_lot_numbers lot
526    where msn.current_status = 3
527       and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
528       decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
529       and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
530       --and (g_detail_serial IN ( 1,2)
531         and ( g_detail_any_serial = 2   or   (g_detail_any_serial = 1
532             and g_from_serial_number <= msn.serial_number
533             and lengthb(g_from_serial_number) = lengthb(msn.serial_number)
534             and g_to_serial_number >=  msn.serial_number
535             and lengthb(g_to_serial_number) = lengthb(msn.serial_number))
536              or ( g_from_serial_number is null or g_to_serial_number is null)
537           )
538       and sub.organization_id = msn.current_organization_id
539       and sub.secondary_inventory_name = msn.current_subinventory_code
540       and loc.organization_id (+)= msn.current_organization_id
541       and loc.inventory_location_id (+)= msn.current_locator_id
542       and lot.organization_id (+)= msn.current_organization_id
543       and lot.inventory_Item_id (+)= msn.inventory_item_id
544       and lot.lot_number (+)= msn.lot_number
545      ';
546 
547  /*LPN Status Project*/
548   g_pick_base_serial              LONG
549         := '
550          select  msn.current_organization_id organization_id
551           ,msn.inventory_item_id
552           ,msn.revision
553           ,msn.lot_number
554           ,lot.expiration_date lot_expiration_date
555           ,msn.current_subinventory_code subinventory_code
556           ,msn.current_locator_id locator_id
557           ,msn.cost_group_id
558            ,msn.status_id   --added status_id
559           ,msn.serial_number
560           ,msn.initialization_date date_received
561           ,1 primary_quantity
562           ,null secondary_quantity                            -- new
563           ,lot.grade_code grade_code                          -- new
564           ,sub.reservable_type
565           ,nvl(loc.reservable_type,1)  locreservable          -- Bug 6719290
566           ,nvl(lot.reservable_type,1)  lotreservable          -- Bug 6719290
567           ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
568           ,WMS_Rule_PVT.GetConversionRate(
569                nvl(loc.pick_uom_code, sub.pick_uom_code)
570               ,msn.current_organization_id
571               ,msn.inventory_item_id) conversion_rate
572           ,msn.lpn_id lpn_id
573           ,loc.project_id project_id
574           ,loc.task_id task_id
575                 ,NULL locator_inventory_item_id
576                 ,NULL empty_flag
577                 ,NULL location_current_units
578            from  mtl_serial_numbers msn
579           ,mtl_secondary_inventories sub
580           ,mtl_item_locations loc
581           ,mtl_lot_numbers lot
582           where msn.current_status = 3
583             and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
584             decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
585             and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
586             and (g_detail_serial = 4
587                 OR(g_detail_any_serial = 1
588              OR (g_from_serial_number <= msn.serial_number
589                 AND lengthb(g_from_serial_number) = lengthb(msn.serial_number)
590                 AND g_to_serial_number >=  msn.serial_number
591                       AND lengthb(g_to_serial_number) = lengthb(msn.serial_number)
592                 )))
593             and sub.organization_id = msn.current_organization_id
594             and sub.secondary_inventory_name = msn.current_subinventory_code
595             and loc.organization_id (+)= msn.current_organization_id
596             and loc.inventory_location_id (+)= msn.current_locator_id
597             and lot.organization_id (+)= msn.current_organization_id
598             and lot.inventory_Item_id (+)= msn.inventory_item_id
599             and lot.lot_number (+)= msn.lot_number
600              ';
601  -------------------------------------------------
602 /*LPN Status Project*/
603  --- Added the following query to validate the serial status inside the rules package
604    g_pick_base_serial_v              LONG
605    := '
606     select  msn.current_organization_id organization_id
607      ,msn.inventory_item_id
608      ,msn.revision
609      ,msn.lot_number
610      ,lot.expiration_date lot_expiration_date
611      ,msn.current_subinventory_code subinventory_code
612      ,msn.current_locator_id locator_id
613      ,msn.cost_group_id
614      ,msn.status_id        --added status_id
615      ,msn.serial_number
616      ,msn.initialization_date date_received
617      ,1 primary_quantity
618      ,null secondary_quantity                            -- new
619      ,lot.grade_code grade_code                          -- new
620      ,sub.reservable_type
621      ,nvl(loc.reservable_type,1)   locreservable                -- Bug 6719290
622      ,nvl(lot.reservable_type,1)   lotreservable                -- Bug 6719290
623      ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
624      ,WMS_Rule_PVT.GetConversionRate(
625           nvl(loc.pick_uom_code, sub.pick_uom_code)
626          ,msn.current_organization_id
627          ,msn.inventory_item_id) conversion_rate
628      ,msn.lpn_id lpn_id
629      ,loc.project_id project_id
630      ,loc.task_id task_id
631            ,NULL locator_inventory_item_id
632            ,NULL empty_flag
633            ,NULL location_current_units
634       from  mtl_serial_numbers msn
635      ,mtl_secondary_inventories sub
636      ,mtl_item_locations loc
637      ,mtl_lot_numbers lot
638     where msn.current_status = 3
639        and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
640        decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
641        and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
642        and (g_detail_serial = 3
643            OR(g_detail_any_serial = 1
644         OR (g_from_serial_number <= msn.serial_number
645            AND lengthb(g_from_serial_number) = lengthb(msn.serial_number)
646            AND g_to_serial_number >=  msn.serial_number
647                  AND lengthb(g_to_serial_number) = lengthb(msn.serial_number)
648            )))
649        and sub.organization_id = msn.current_organization_id
650        and sub.secondary_inventory_name = msn.current_subinventory_code
651        and loc.organization_id (+)= msn.current_organization_id
652        and loc.inventory_location_id (+)= msn.current_locator_id
653        and lot.organization_id (+)= msn.current_organization_id
654        and lot.inventory_Item_id (+)= msn.inventory_item_id
655        and lot.lot_number (+)= msn.lot_number
656        and inv_detail_util_pvt.is_serial_trx_allowed(
657                                         g_transaction_type_id
658                                         ,msn.current_organization_id
659                                         ,msn.inventory_item_id
660                                         ,msn.status_id) = ''Y'' ';
661  /*LPN Status Project*/
662  -- Bug #3697741 modified the base query to get the project_id and task_id from mtl_inventory_locations
663   g_pick_base_lpn_only   CONSTANT LONG
664         := '
665    select  x.organization_id
666           ,x.inventory_item_id
667           ,x.revision
668           ,x.lot_number
669           ,lot.expiration_date lot_expiration_date
670           ,x.subinventory_code
671           ,sub.reservable_type
672           ,nvl(x.reservable_type,1) locreservable             -- Bug 6719290
673           ,nvl(lot.reservable_type,1) lotreservable           -- Bug 6719290
674           ,x.locator_id
675           ,x.cost_group_id
676           ,x.status_id                --added status_id
677           ,x.date_received date_received
678           ,x.primary_quantity primary_quantity
679           ,x.secondary_quantity       secondary_quantity            -- new
680           ,lot.grade_code             grade_code                    -- new
681           ,x.lpn_id lpn_id
682           ,x.project_id project_id
683           ,x.task_id task_id
684      from
685           (SELECT
686              moq.organization_id
687             ,moq.inventory_item_id
688             ,moq.revision
689             ,moq.lot_number
690             ,moq.subinventory_code
691             ,moq.locator_id
692             ,moq.cost_group_id
693             ,moq.status_id                --added status_id
694             ,mils.reservable_type                                  -- Bug 6719290
695             ,min(NVL(moq.orig_date_received,
696                  moq.date_received)) date_received
697             ,sum(moq.primary_transaction_quantity) primary_quantity
698             ,sum(moq.secondary_transaction_quantity) secondary_quantity   -- new
699             ,moq.lpn_id lpn_id
700             ,mils.project_id project_id
701             ,mils.task_id task_id
702           FROM
703               mtl_onhand_quantities_detail  moq
704             , mtl_item_locations            mils
705           WHERE
706                moq.organization_id = g_organization_id
707            AND moq.inventory_item_id = g_inventory_item_id
708            AND moq.organization_id = mils.organization_id
709            AND moq.subinventory_code = mils.subinventory_code
710            AND moq.locator_id = mils.inventory_location_id
711            AND moq.lpn_id IS NOT NULL
712            AND NOT EXISTS(
713                 select lpn_id
714                 from wms_license_plate_numbers wlpn1
715                 where wlpn1.parent_lpn_id = moq.lpn_id)
716            AND
717                1 = (select count(distinct(moq1.inventory_item_id))
718                from mtl_onhand_quantities_detail moq1
719                where   moq1.organization_id = moq.organization_id
720                     and moq1.subinventory_code = moq.subinventory_code
721                     and moq1.locator_id = moq.locator_id
722                     and moq1.lpn_id = moq.lpn_id)
723            GROUP BY
724                moq.organization_id, moq.inventory_item_id
725 	      --,moq.date_received --bug 6648984
726               ,NVL(moq.orig_date_received, moq.date_received) --13518247
727               ,moq.revision, moq.lot_number
728               ,moq.subinventory_code, moq.locator_id   --added status_id
729               ,moq.cost_group_id,moq.status_id,mils.reservable_type,moq.lpn_id       -- Bug 6719290
730               ,mils.project_id, mils.task_id
731            HAVING
732                sum(moq.primary_transaction_quantity) > 0 -- high volume project 8546026
733           ) x
734           ,mtl_secondary_inventories sub
735           ,mtl_lot_numbers lot
736     where
737 --      x.primary_quantity > 0 and  -- high volume project 8546026
738           x.organization_id = sub.organization_id
739       and x.subinventory_code = sub.secondary_inventory_name
740       and x.organization_id = lot.organization_id (+)
741       and x.inventory_item_id = lot.inventory_item_id (+)
742       and x.lot_number = lot.lot_number (+)
743 ';
744  /*LPN Status Project*/
745 -- Bug #3697741 modified the base query to get the project_id and task_id from mtl_inventory_locations
746 -- LG convergence, for this bug, an item is not locator controlled may not have
747 -- any records in mils. so the join will fail. put decode and outter join
748 -- need to talk to grao about this.
749   g_pick_base_lpn_loose  CONSTANT LONG
750         := '
751    select  x.organization_id
752           ,x.inventory_item_id
753           ,x.revision
754           ,x.lot_number
755           ,lot.expiration_date lot_expiration_date
756           ,x.subinventory_code
757           ,sub.reservable_type
758           ,nvl(x.reservable_type,1)   locreservable                          -- Bug 6719290
759           ,nvl(lot.reservable_type,1) lotreservable                          -- Bug 6719290
760           ,x.locator_id
761           ,x.cost_group_id
762           ,x.status_id                --added status_id
763           ,x.date_received date_received
764           ,x.primary_quantity primary_quantity
765           ,x.secondary_quantity       secondary_quantity            -- new
766           ,lot.grade_code             grade_code                    -- new
767           ,x.lpn_id lpn_id
768           ,x.project_id project_id
769           ,x.task_id task_id
770      from
771           (SELECT
772              moq.organization_id
773             ,moq.inventory_item_id
774             ,moq.revision
775             ,moq.lot_number
776             ,moq.subinventory_code
777             ,moq.locator_id
778             ,moq.cost_group_id
779             ,moq.status_id                --added status_id
780             ,mils.reservable_type                                  -- Bug 6719290
781             ,min(NVL(moq.orig_date_received,
782                  moq.date_received)) date_received
783             ,sum(moq.primary_transaction_quantity) primary_quantity
784             ,sum(moq.secondary_transaction_quantity) secondary_quantity   -- new
785             ,moq.lpn_id lpn_id
786             ,decode(mils.project_id, mils.project_id, moq.project_id) project_id
787             ,decode(mils.task_id, mils.task_id, moq.task_id) task_id
788           FROM
789             mtl_onhand_quantities_detail moq,mtl_item_locations mils
790           WHERE
791                moq.organization_id = g_organization_id
792            AND moq.inventory_item_id = g_inventory_item_id
793            AND moq.organization_id = mils.organization_id (+)
794            AND moq.subinventory_code = mils.subinventory_code (+)
795            AND moq.locator_id = mils.inventory_location_id (+)
796           GROUP BY
797                moq.organization_id, moq.inventory_item_id
798 	      --,moq.date_received --bug 6648984
799               ,NVL(moq.orig_date_received, moq.date_received) --13518247
800               ,moq.revision, moq.lot_number
801               ,moq.subinventory_code, moq.locator_id                --added status_id
802               ,moq.cost_group_id,moq.status_id, mils.reservable_type, moq.lpn_id         -- Bug 6719290
803               ,decode(mils.project_id, mils.project_id, moq.project_id)
804               ,decode(mils.task_id, mils.task_id, moq.task_id)
805           HAVING
806                sum(moq.primary_transaction_quantity) > 0 -- high volume project 8546026
807           ) x
808           ,mtl_secondary_inventories sub
809           ,mtl_lot_numbers lot
810     where
811 --    x.primary_quantity > 0 and   -- high volume project 8546026
812           x.organization_id = sub.organization_id
813       and x.subinventory_code = sub.secondary_inventory_name
814       and x.organization_id = lot.organization_id (+)
815       and x.inventory_item_id = lot.inventory_item_id (+)
816       and x.lot_number = lot.lot_number (+)
817 ';
818   g_pick_base                     LONG;
819   --
820   g_base_table_alias              wms_db_objects.table_alias%TYPE;
821   g_input_table_alias             wms_db_objects.table_alias%TYPE;
822   g_base_select                   LONG;
823   g_base_group_by                 LONG;
824   g_rule_select                   LONG;
825   g_rule_select_serial            LONG;
826   g_rule_select_serial_new        LONG; -- Added for Bug 13448337
827   g_rule_group_by                 LONG;
828   g_rule_group_by_new             LONG; -- Added for Bug 13448337
829   g_base_from                     LONG;
830   g_base_from_serial              LONG; --used if item is lot controlled
831   g_base_from_serial_v            LONG; --used for serial controlled item / Validation required
832   g_base_from_serial_detail       LONG; -- New
833   g_rule_from                     LONG;
834   g_input_where                   LONG;
835   g_rule_where                    LONG;
836   g_rule_order                    LONG;
837   g_rule_order_new                LONG; -- Added for Bug 13448337
838   g_stmt                          LONG;
839   g_stmt_task_type                LONG; --used for task type assignment  TTA
840   g_stmt_serial                   LONG;
841   g_stmt_serial_validate          LONG;
842   g_stmt_serial_detail            LONG;
843   g_stmt_serial_detail_new        LONG;
844   g_build_package_row             NUMBER;
845   g_build_package_tbl             DBMS_SQL.varchar2s;
846   g_default_pick_task_type_id     NUMBER;
847   g_default_putaway_task_type_id  NUMBER;
848   g_default_cc_task_type_id       NUMBER;
849   g_default_repl_task_type_id     NUMBER;
850   g_default_moxfer_task_type_id   NUMBER;
851   g_default_moissue_task_type_id  NUMBER;
852   g_default_operation_plan_id     NUMBER;
853   g_current_organization_id       NUMBER;
854   --
855   g_line_feed            CONSTANT VARCHAR2(1)                                             := '
856 ';
857   --global values for allocation mode
858   g_alloc_lpn_only                NUMBER                                                  := 1;
859   g_alloc_lpn_loose               NUMBER                                                  := 2;
860   g_alloc_no_lpn                  NUMBER                                                  := 3;
861   g_alloc_pick_uom                NUMBER                                                  := 4;
862 
863   -- Added for R12.1 Replenishment Project - 6681109
864   g_alloc_strict_pick_uom         NUMBER                                                  := 5;
865   g_pickuom_serial_case NUMBER;-- Added for Bug 13448337
866   g_pickuom_serial_flag NUMBER;-- Added for Bug 13448337
867 
868   --Used for storing both the current record being dealt with and a
869   -- a variety of stored records.  This represents a single row returned
870   -- by the FetchCursor function, which gets the row from the Rule.
871   -- This records are stored in an array, but are accessed like linked
872   -- lists.  Each record contains the index of the next record
873   -- that should be looked at (next_rec).
874   TYPE t_location_rec IS RECORD(
875     revision                      wms_transactions_temp.revision%TYPE
876   , lot_number                    wms_transactions_temp.lot_number%TYPE
877   , lot_expiration_date           wms_transactions_temp.lot_expiration_date%TYPE
878   , subinventory_code             wms_transactions_temp.from_subinventory_code%TYPE
879   , locator_id                    wms_transactions_temp.from_locator_id%TYPE
880   , cost_group_id                 wms_transactions_temp.from_cost_group_id%TYPE
881   , uom_code                      VARCHAR2(3)
882   , lpn_id                        NUMBER
883   , serial_number                 VARCHAR2(30)
884   , quantity                      wms_transactions_temp.primary_quantity%TYPE
885   , secondary_quantity            wms_transactions_temp.secondary_quantity%TYPE
886   , grade_code                    wms_transactions_temp.grade_code%TYPE
887   , secondary_uom_code            VARCHAR2(3)
888   , consist_string                VARCHAR2(1000)
889   , order_by_string               VARCHAR2(1000)
890   , next_rec                      NUMBER);
891 
892   TYPE t_location_table IS TABLE OF t_location_rec
893     INDEX BY BINARY_INTEGER;
894 
895   --these arrays store location recs in sequential order. However, when
896   -- the records are read from the array, they are read in the order
897   -- dictated by the pointer in the location_rec (next_rec)
898   g_locs                          t_location_table; -- array of all locators read from cursor
899   g_locs_index                    NUMBER                                                  := 0;
900 
901   -- Bug 8247123: Table to keep track of secondary qty to be allocated,
902   -- per reservation.  RESERVATION_ID is used as the index.
903   -- Added for bug 8665496
904   TYPE t_qty_tbl IS TABLE OF NUMBER INDEX BY LONG;
905   g_sec_alloc_qty                 t_qty_tbl;
906 
907   -- Added for bug 8665496 - to track qty to be allocated per reservation.
908   g_alloc_qty                     t_qty_tbl;
909 
910   -- This record is used to store information about a consistency group.
911   -- A consistency group consists of all records which share the same
912   -- consist_string.  The consist_string is the concatenation of each
913   -- record's values for the columns which are defined as a rule's
914   -- consistencies.  For example, if a rule's consistency restrictions
915   -- are lot number and locator_id, then the consist string would
916   -- lot_number||locator_id.  Each record could have different
917   -- values for the consist string, like LOTA123, or LOTB1000.
918   -- For creating pick suggestions for rules that have consistency
919   -- restrictions, we need to keep track of the quantity available
920   -- for each consistency group.
921   -- 2/26/02
922   -- Group record altered to support LPNs
923   TYPE t_group_rec IS RECORD(
924     consist_string                VARCHAR2(1000)
925   , lpn_id                        NUMBER
926   , quantity                      NUMBER
927   , total_quantity                NUMBER
928   , secondary_quantity            NUMBER                               -- new
929   , secondary_total_quantity      NUMBER                               -- new
930   , grade_code                    VARCHAR2(150)                        -- new
931   , order_by_rank                 NUMBER
932   , first_rec                     NUMBER
933   , last_rec                      NUMBER
934   , prev_group                    NUMBER
935   , next_group                    NUMBER
936   , prev_consist_lpn_id           NUMBER
937   , next_consist_lpn_id           NUMBER
938   , parent_consist_group          NUMBER);
939 
940   TYPE t_group_table IS TABLE OF t_group_rec
941     INDEX BY BINARY_INTEGER;
942 
943   g_consists                      t_group_table;
944   g_lpns                          t_group_table;
945   g_first_order_by_rank           NUMBER                                                  := NULL;
946   g_first_consist_group           NUMBER                                                  := 0;
947   g_last_consist_group            NUMBER;
948   g_first_lpn_group               NUMBER;
949   g_last_lpn_group                NUMBER;
950   g_trace_recs                    wms_search_order_globals_pvt.pre_suggestions_record_tbl;
951 
952   PROCEDURE FetchCursorRows(
953     x_return_status       OUT NOCOPY    VARCHAR2
954   , x_msg_count           OUT NOCOPY    NUMBER
955   , x_msg_data            OUT NOCOPY    VARCHAR2
956   , p_cursor              IN            wms_rule_pvt.cv_pick_type
957   , p_rule_id             IN            NUMBER
958   );
959 
960   -- =============================================
961   -- Procedure to log message for Label Printing
962   -- =============================================
963   PROCEDURE TRACE(p_message IN VARCHAR2) IS
964   BEGIN
965     inv_log_util.TRACE(p_message, 'RULE_ENGINE', 4);
966   END TRACE;
967 
968   --Procedures for logging messages
969   PROCEDURE log_event(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
970     l_module VARCHAR2(255);
971   BEGIN
972     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
973     inv_log_util.trace(p_message, l_module, 9);
974    /* fnd_log.STRING(log_level => fnd_log.level_event, module => l_module, message => p_message);
975     inv_log_util.trace(p_message, l_module, 9);
976     gmi_reservation_util.println(p_message); */
977   END log_event;
978 
979   PROCEDURE log_error(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
980     l_module VARCHAR2(255);
981   BEGIN
982     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
983     inv_log_util.trace(p_message, l_module, 9); /*
984     fnd_log.STRING(log_level => fnd_log.level_error, module => l_module, message => p_message);
985     inv_log_util.trace(p_message, l_module, 9);
986     gmi_reservation_util.println(p_message); */
987   END log_error;
988 
989   PROCEDURE log_error_msg(p_api_name VARCHAR2, p_label VARCHAR2) IS
990     l_module VARCHAR2(255);
991   BEGIN
992     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
993     inv_log_util.trace('err:', l_module, 9); /*
994     fnd_log.message(log_level => fnd_log.level_error, module => l_module, pop_message => FALSE);
995     inv_log_util.trace('err:', l_module, 9);
996     gmi_reservation_util.println(p_label); */
997   END log_error_msg;
998 
999   PROCEDURE log_procedure(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
1000     l_module VARCHAR2(255);
1001   BEGIN
1002     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
1003     inv_log_util.trace(p_message, l_module, 9);/*
1004     fnd_log.STRING(log_level => fnd_log.level_procedure, module => l_module, message => p_message);
1005     inv_log_util.trace(p_message, l_module, 9);
1006     gmi_reservation_util.println(p_message); */
1007   END log_procedure;
1008 
1009   PROCEDURE log_statement(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
1010     l_module VARCHAR2(255);
1011   BEGIN
1012     l_module  := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
1013     inv_log_util.trace(p_message, l_module, 9);/*
1014     fnd_log.STRING(log_level => fnd_log.level_statement, module => l_module, message => p_message);
1015     inv_log_util.trace(p_message, l_module, 9);
1016     gmi_reservation_util.println(p_label||' '||p_message);*/
1017   END log_statement;
1018 
1019   -- Start 1 of Bug 13026723
1020   -- Function to check if the LPN with LPN_ID = p_lpn_id is already reserved for a cycle count or not
1021   FUNCTION IS_LPN_CYC_RESERVED(p_organization_id NUMBER, p_lpn_id NUMBER)
1022   RETURN BOOLEAN IS
1023         l_lpn_used NUMBER;
1024         l_debug    NUMBER;
1025   l_api_name          VARCHAR2(20) := 'IS_LPN_CYC_RESERVED';
1026   BEGIN
1027         g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'), 0);
1028      l_debug := g_debug;
1029      IF l_debug = 1 THEN
1030          log_statement(l_api_name, 'IS_LPN_CYC_RESERVED', 'Inside function IS_LPN_CYC_RESERVED');
1031      END IF;
1032 
1033         SELECT COUNT(*)
1034        INTO l_lpn_used
1035        FROM mtl_reservations mr
1036      WHERE mr.organization_id = p_organization_id
1037         AND mr.demand_source_type_id = 9 -- Cycle Count Reservation
1038            AND mr.lpn_id = p_lpn_id;
1039 
1040         IF l_lpn_used >= 1 THEN
1041      RETURN TRUE;
1042   ELSE
1043      RETURN FALSE;
1044   END IF;
1045 
1046   EXCEPTION WHEN OTHERS THEN
1047      RETURN FALSE;
1048 
1049   END IS_LPN_CYC_RESERVED;
1050   -- End 1 of Bug 13026723
1051 
1052   ----
1053   ---- Function to check if Restriction , Sort-criteria and Consistency was defined for a given picking rule
1054   ---- using serial object
1055 
1056   FUNCTION IsSerialObjectUsed( p_organization_id  NUMBER )
1057   RETURN BOOLEAN IS
1058   l_serial_object_used          NUMBER ;
1059   BEGIN
1060     /* Trace( ' Start IsSerialObjectUsed');
1061      Trace( ' Start IsSerialObjectUsed p_organization_id '|| to_char(p_organization_id));
1062      Trace( ' Start IsSerialObjectUsed g_serial_objects_used ' || to_char( g_serial_objects_used));
1063      */
1064 
1065     l_serial_object_used  := 0 ;
1066   IF ( wms_rule_pvt.g_serial_objects_used IS NULL )   THEN
1067      --Trace( ' IsSerialObjectUsed -- If condition is true ');
1068      SELECT count( DISTINCT p.object_id)
1069        INTO l_serial_object_used
1070        FROM wms_selection_criteria_txn wsc,
1071             wms_strategies_b wsb,
1072             wms_strategy_members wsm,
1073             wms_rules_b wrb,
1074             wms_restrictions r,
1075             wms_sort_criteria s,
1076             wms_rule_consistencies c,
1077             wms_parameters_b p
1078       WHERE wsc.rule_type_code = 2
1079         AND wsc.enabled_flag = 1
1080         AND wsc.return_type_code = 'S'
1081         AND wsc.from_organization_id = p_organization_id
1082         AND wsc.return_type_id = wsb.strategy_id
1083         AND wsb.strategy_id = wsm.strategy_id
1084         AND wsm.rule_id = wrb.rule_id
1085         AND (
1086              ( wrb.rule_id = r.rule_id AND ((r.parameter_id = p.parameter_id ) OR (r.operand_parameter_id = p.parameter_id)))
1087                 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)              )
1088         AND wrb.organization_id IN (p_organization_id, -1)
1089         AND p.object_id = 26; --- 26 is Serial object
1090 
1091         wms_rule_pvt.g_serial_objects_used := l_serial_object_used;
1092 
1093         --Trace( ' IsSerialObjectUsed -- l_serial_object_used ' || wms_rule_pvt.g_serial_object_used);
1094   ELSE
1095     l_serial_object_used  := wms_rule_pvt.g_serial_objects_used;
1096   END IF;
1097 
1098   If l_serial_object_used  >= 1  THEN
1099      RETURN TRUE;
1100   ELSE
1101      RETURN FALSE;
1102   END IF;
1103 
1104   EXCEPTION WHEN OTHERS THEN
1105      RETURN FALSE;
1106   END IsSerialObjectUsed;
1107 
1108   --
1109   -- Name        : FreeGlobals
1110   -- Function    : Initializes global variables.
1111   -- Notes       : privat procedure for internal use only
1112   --
1113   PROCEDURE freeglobals IS
1114   BEGIN
1115     g_base_select         := NULL;
1116     g_rule_select         := NULL;
1117     g_rule_select_serial  := NULL;
1118     g_rule_select_serial_new  := NULL; -- Added for Bug 13448337
1119     g_base_from           := NULL;
1120     g_base_from_serial    := NULL;
1121     g_base_from_serial_v  := NULL;
1122     g_base_from_serial_detail := NULL;
1123     g_rule_from           := NULL;
1124     g_input_where         := NULL;
1125     g_rule_where          := NULL;
1126     g_rule_order          := NULL;
1127     g_rule_order_new      := NULL; -- Added for Bug 13448337
1128     g_base_group_by       := NULL;
1129     g_rule_group_by       := NULL;
1130     g_rule_group_by_new   := NULL; -- Added for Bug 13448337
1131     g_stmt                := NULL;
1132     g_stmt_serial         := NULL;
1133     g_stmt_serial_detail  := NULL;
1134     g_stmt_serial_detail_new  := NULL;
1135     g_pick_base           := NULL;
1136     g_pickuom_serial_case  := 0; -- Added for Bug 13448337
1137     g_pickuom_serial_flag  := 0; -- Added for Bug 13448337
1138     -- clean up the serial number detailing table
1139     -- Commenting out for Bug 5251221
1140     --inv_detail_util_pvt.init_output_serial_rows;
1141     -- clean up the bind variables table
1142     inv_sql_binding_pvt.initbindtables;
1143   END freeglobals;
1144 
1145   ----
1146   ----
1147 
1148   --------------
1149   --- Build Rules List
1150   ---  Generate all static rule list package  for diffrent rule types.
1151   ---- Total of  15 packages will be generated
1152   ---- WMS_RULE_PICK_PKG, WMS_RULE_PICK_PKG1, WMS_RULE_PICK_PKG2
1153   PROCEDURE buildrulespkg(errbuf OUT NOCOPY VARCHAR2, retcode OUT NOCOPY NUMBER, x_return_status OUT NOCOPY VARCHAR2) IS
1154     l_return_status VARCHAR2(1);
1155     l_msg_count     NUMBER;
1156     l_msg_data      VARCHAR2(240);
1157     l_rule_id       NUMBER;
1158     l_error_string  VARCHAR2(240);
1159   BEGIN
1160 
1161     --
1162     -- kkoothan  Bug Fix:2561401
1163     -- Initialized the value of X_RETURN_STATUS to Success
1164     -- at the start of the procedure and set its value accordingly
1165     -- when the procedure returns Failure/Error.
1166     --
1167     X_RETURN_STATUS := fnd_api.g_ret_sts_success;
1168 
1169     --- Updates  the table wms_rule_list_package ,
1170     --- for all rule type package counter with value 3
1171     --- so that all three "rules list packages" for all type of
1172     ----Rules will be generated.
1173 
1174     UPDATE wms_rule_list_package
1175        SET package_name_count = 3;
1176 
1177     wms_rule_gen_pkgs.generateruleexecpkgs(
1178       p_api_version                => 1.0
1179     , p_init_msg_list              => fnd_api.g_true
1180     , p_validation_level           => fnd_api.g_valid_level_full
1181     , x_return_status              => l_return_status
1182     , x_msg_count                  => l_msg_count
1183     , x_msg_data                   => l_msg_data
1184     , p_pick_code                  => 2
1185     , p_put_code                   => 1
1186     , p_task_code                  => 3
1187     , p_label_code                 => 4
1188     , p_cg_code                    => 5
1189     , p_op_code                    => 7
1190     , p_pkg_type                   => 'B'
1191     );
1192 
1193     IF (l_return_status = fnd_api.g_ret_sts_success) THEN
1194       FND_FILE.put_line(FND_FILE.LOG, 'Success from GenerateRuleExecPkgs');
1195     ELSE
1196       FND_FILE.put_line(FND_FILE.LOG, 'Error from GenerateRuleExecPkgs:');
1197       X_RETURN_STATUS :=  fnd_api.g_ret_sts_error; -- Expected Error
1198       retcode  := 1;
1199 
1200       FOR i IN 1 .. l_msg_count LOOP
1201         --fnd_file.put_line(fnd_file.LOG, 'Error:');
1202         l_error_string  := fnd_message.get;
1203         --fnd_file.put_line(fnd_file.LOG, l_error_string);
1204         errbuf          := errbuf || ' Error: GenerateRuleExecPkgs ' || l_error_string;
1205       END LOOP;
1206     END IF;
1207   EXCEPTION
1208     WHEN OTHERS THEN
1209       X_RETURN_STATUS := fnd_api.g_ret_sts_unexp_error; -- Unexpecetd Error
1210       retcode  := 2;
1211       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1212         fnd_msg_pub.add_exc_msg(g_pkg_name, 'BuildRulePkg');
1213       END IF;
1214 
1215       fnd_msg_pub.count_and_get(p_count => l_msg_count, p_data => l_msg_data);
1216       --fnd_file.put_line(fnd_file.LOG, 'Exception');
1217       --fnd_file.put_line(fnd_file.LOG, l_msg_data);
1218       errbuf   := errbuf || 'Error in BuildRulesPkg:' || l_msg_data;
1219   END buildrulespkg;
1220 
1221   --
1222   -- Name        : GetConversionRate
1223   -- Function    : Finds the conversion rate between the given UOM and
1224   --    the base UOM of the class which contains the
1225   --    item's primary UOM. Support interclass and intraclass
1226   --    conversions.
1227   -- Notes       : private procedure for internal use only;
1228   --               Similar to inv_convert.inv_um_converstion, but no
1229   --     Used to order locations returned from rule package
1230   FUNCTION getconversionrate(p_uom_code VARCHAR2, p_organization_id NUMBER, p_inventory_item_id NUMBER)
1231     RETURN NUMBER IS
1232     l_conversion_rate NUMBER;
1233     l_from_class      VARCHAR2(10);
1234     l_to_class        VARCHAR2(10);
1235     l_class_rate      NUMBER;
1236 
1237     --get conversion rate between given uom and that uom class's
1238     -- base uom
1239     CURSOR c_conversion_rate IS
1240       SELECT   conversion_rate
1241              , uom_class
1242           FROM mtl_uom_conversions
1243          WHERE uom_code = p_uom_code
1244            AND inventory_item_id IN (p_inventory_item_id, 0)
1245            AND NVL(disable_date, TRUNC(SYSDATE) + 1) > TRUNC(SYSDATE)
1246       ORDER BY inventory_item_id DESC;
1247 
1248     -- find the uom class for the item's primary uom
1249     CURSOR c_primary_uom_class IS
1250       SELECT uom_class
1251         FROM mtl_units_of_measure muom, mtl_system_items msi
1252        WHERE msi.organization_id = p_organization_id
1253          AND msi.inventory_item_id = p_inventory_item_id
1254          AND muom.uom_code = msi.primary_uom_code;
1255 
1256     -- find the conversion rate between the base uoms of two classes
1257     CURSOR c_class_conversion_rate IS
1258       SELECT   conversion_rate
1259           FROM mtl_uom_class_conversions
1260          WHERE from_uom_class = l_from_class
1261            AND to_uom_class = l_to_class
1262            AND inventory_item_id IN (p_inventory_item_id, 0)
1263            AND NVL(disable_date, TRUNC(SYSDATE) + 1) > TRUNC(SYSDATE)
1264       ORDER BY inventory_item_id DESC;
1265   BEGIN
1266     IF (p_uom_code IS NULL) THEN
1267       RETURN 0;
1268     END IF;
1269 
1270     IF (nvl(g_gcr_organization_id,-1) = p_organization_id
1271       AND nvl(g_gcr_inventory_item_id,-1) = p_inventory_item_id
1272       AND nvl(g_gcr_uom_code,'-1') = p_uom_code) THEN
1273       l_conversion_rate := g_gcr_conversion_rate;
1274     ELSE
1275       OPEN c_conversion_rate;
1276       --Cursor returns 0, 1, or 2 records
1277       -- Because the results are ordered by item_id desc, the results
1278       -- are also ordered from specific (item_Id > 0) to default (item_id = 0);
1279       --So, we only have to fetch one record
1280       FETCH c_conversion_rate INTO l_conversion_rate, l_to_class;
1281 
1282       IF (c_conversion_rate%NOTFOUND) THEN
1283         --don't raise error. Instead, just return 1
1284         l_conversion_rate  := 0;
1285       END IF;
1286 
1287       CLOSE c_conversion_rate;
1288 
1289       IF l_conversion_rate <> 0 THEN
1290         OPEN c_primary_uom_class;
1291         FETCH c_primary_uom_class INTO l_from_class;
1292 
1293         IF (c_primary_uom_class%NOTFOUND) THEN
1294           l_from_class       := NULL;
1295           l_conversion_rate  := 0;
1296         END IF;
1297 
1298         CLOSE c_primary_uom_class;
1299 
1300         -- check to see if interclass conversion - if so, get conversion
1301         -- between 2 classes
1302         IF  l_from_class IS NOT NULL
1303             AND l_to_class IS NOT NULL
1304             AND l_from_class <> l_to_class THEN
1305           OPEN c_class_conversion_rate;
1306           FETCH c_class_conversion_rate INTO l_class_rate;
1307 
1308           IF c_class_conversion_rate%NOTFOUND THEN
1309             l_class_rate  := 0;
1310           END IF;
1311 
1312           l_conversion_rate  := l_conversion_rate * l_class_rate;
1313         END IF;
1314       END IF;
1315       g_gcr_organization_id := p_organization_id;
1316       g_gcr_inventory_item_id := p_inventory_item_id;
1317       g_gcr_uom_code := p_uom_code;
1318       g_gcr_conversion_rate := l_conversion_rate;
1319     END IF;
1320 
1321     RETURN l_conversion_rate;
1322   END getconversionrate;
1323 
1324   --
1325   -- Name        : BuildBaseSQL
1326   -- Function    : Builds the base part of a pick or put away rule representing
1327   --               dynamic SQL cursor text.
1328   -- Notes       : privat procedure for internal use only
1329   --
1330   PROCEDURE buildbasesql(
1331     x_return_status      OUT NOCOPY    VARCHAR2
1332   , x_msg_count          OUT NOCOPY    NUMBER
1333   , x_msg_data           OUT NOCOPY    VARCHAR2
1334   , p_type_code          IN            NUMBER
1335   , p_allocation_mode_id IN            NUMBER
1336   ) IS
1337     l_api_name             VARCHAR2(30)                      := 'BuildBaseSQL';
1338     l_return_status        VARCHAR2(1)                       := fnd_api.g_ret_sts_success;
1339     --
1340     -- variables needed for dynamic SQL
1341     l_identifier           VARCHAR2(10);
1342     -- variables for the base and input representing DB objects
1343     l_input_table_name     wms_db_objects.table_name%TYPE;
1344     l_type_dependent_alias wms_db_objects.table_alias%TYPE;
1345 
1346     --
1347     -- cursor for the base and input representing DB objects
1348     CURSOR baseinp IS
1349       SELECT wdo1.table_alias
1350            , wdo2.table_name
1351            , wdo2.table_alias
1352         FROM wms_db_objects wdo1, wms_db_objects wdo2
1353        WHERE wdo1.db_object_id = 1
1354          AND wdo2.db_object_id = 2;
1355   --
1356   BEGIN
1357     --
1358     -- Initialize API return status to success
1359     x_return_status     := fnd_api.g_ret_sts_success;
1360 
1361     --
1362     -- debugging portion
1363     -- can be commented ut for final code
1364     log_procedure(l_api_name, 'start', 'Start BuildBaseSql');
1365     log_statement(l_api_name, 'type_code', 'type_code: ' || p_type_code);
1366     -- end of debugging section
1367     --
1368 
1369 
1370     -- get names and aliases of the base and input representing DB objects
1371     OPEN baseinp;
1372     FETCH baseinp INTO g_base_table_alias, l_input_table_name, g_input_table_alias;
1373 
1374     IF baseinp%NOTFOUND THEN
1375       CLOSE baseinp;
1376       log_statement(l_api_name, 'no_base_input', 'No base input found');
1377       RAISE NO_DATA_FOUND;
1378     END IF;
1379 
1380     CLOSE baseinp;
1381 
1382     --
1383     -- Build 'select' skeleton
1384     IF p_type_code = 1 THEN -- put away:
1385       l_type_dependent_alias  := g_input_table_alias; -- rev and lot from input
1386     ELSIF p_type_code = 2 THEN -- pick:
1387       l_type_dependent_alias  := g_base_table_alias; -- rev and lot from basis
1388     END IF;
1389 
1390     --
1391     --2/21/02 - remove all columns but sub and loc from picking query
1392     IF p_type_code = 2 THEN
1393       g_base_select  :=    l_type_dependent_alias
1394                         || '.REVISION'
1395                         || g_line_feed
1396                         || ','
1397                         || l_type_dependent_alias
1398                         || '.LOT_NUMBER'
1399                         || g_line_feed
1400                         || ','
1401                         || l_type_dependent_alias
1402                         || '.LOT_EXPIRATION_DATE'
1403                         || g_line_feed
1404                         || ','
1405                         || g_base_table_alias
1406                         || '.SUBINVENTORY_CODE'
1407                         || g_line_feed
1408                         || ','
1409                         || g_base_table_alias
1410                         || '.LOCATOR_ID'
1411                         || g_line_feed;
1412     ELSE
1413       g_base_select  := g_base_table_alias
1414                        || '.SUBINVENTORY_CODE'
1415                        || g_line_feed || ','
1416                        || g_base_table_alias
1417                        || '.LOCATOR_ID'
1418                        || g_line_feed;
1419     END IF;
1420 
1421     -- added to suport PJM
1422     IF p_type_code = 1 THEN
1423       g_base_select  := g_base_select
1424                        || ','
1425                        || g_base_table_alias
1426                        || '.PROJECT_ID'
1427                        || g_line_feed;
1428       g_base_select  := g_base_select
1429                        || ','
1430                        || g_base_table_alias
1431                        || '.TASK_ID'
1432                        || g_line_feed;
1433     END IF;
1434 
1435     --added to support Picking by UOM.
1436     --UOM only matters in picking
1437     IF p_type_code = 2 THEN --pick
1438       g_base_select  := g_base_select
1439                        || ','
1440                        || g_base_table_alias
1441                        || '.COST_GROUP_ID'
1442                        || g_line_feed;
1443       g_base_select  := g_base_select
1444                        || ','
1445                        || g_base_table_alias
1446                        || '.UOM_CODE'
1447                        || g_line_feed;
1448 
1449       IF p_allocation_mode_id IN (g_alloc_lpn_only, g_alloc_lpn_loose) THEN
1450         g_base_select  := g_base_select
1451                        || ','
1452                        || g_base_table_alias
1453                        || '.LPN_ID'
1454                        || g_line_feed;
1455       ELSE
1456         g_base_select  := g_base_select
1457                        || ',decode(g_lpn_id, -9999, NULL, g_lpn_id) LPN_ID'
1458                        || g_line_feed;
1459       END IF;
1460     /* 2/21/02 - no longer need these args, since put and pick packages
1461      * are not build differently
1462      * else  --put away
1463      *  --for put, get cost group from wms_transactions_temp,
1464      *  --  not input table (wms_trx_details_tmp_v)
1465      *  g_base_select := g_base_select ||',NULL cost_group_id'
1466      *                                 || g_line_feed;
1467      *  g_base_select := g_base_select ||',NULL uom_code'
1468      *                                 || g_line_feed;
1469      */
1470     END IF;
1471 
1472     --
1473     -- Build type code independent 'from' skeleton
1474     g_base_from                 := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1475     g_base_from_serial          := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1476     g_base_from_serial_v        := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1477     g_base_from_serial_detail   := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1478 
1479     --
1480     -- Add type code dependent part to 'from' skeleton
1481     -- We need to build 9 different putaway cursors using 3 different put
1482     -- bases.  So, here we insert a place holder (:g_put_base) which we will
1483     -- replace in GenerateRulePackage with the appropriate base
1484     IF p_type_code = 1 THEN -- put away
1485       g_base_from  := g_base_from || ',(:g_put_base)' || g_base_table_alias || g_line_feed;
1486     ELSIF p_type_code = 2 THEN -- pick
1487       --need to generate 2 pick bases - one for non-serial controlled,
1488       --and one for serial control, since we won't know whether
1489       -- the inventory item is serial controlled until the stored
1490       -- procedure is run.
1491       IF p_allocation_mode_id = g_alloc_lpn_only THEN
1492         g_pick_base  := g_pick_base_lpn_only;
1493       ELSIF p_allocation_mode_id = g_alloc_lpn_loose THEN
1494         g_pick_base  := g_pick_base_lpn_loose;
1495       ELSE
1496         /**
1497          *Bug 2310403
1498          *Errors allocating for LPN putaway move orders.
1499          *The problem occurs because we should only pick material
1500          *from a certain LPN, but the base returned by build_sql
1501          *does not have an LPN_ID.  So now, we'll use the lpn_loose
1502          *base, and add a group_by statement on the outermost query
1503          *so that we only get one rec per rev/lot/sub/loc when we
1504          *aren't allocating LPNs
1505                *--build non-serial controlled pick base
1506                *log_statement(l_api_name, 'build_sql_no_serial',
1507                *  'Calling inv_detail_util_pvt.build_sql for base');
1508                *inv_detail_util_pvt.build_sql
1509          *( x_return_status       => l_return_status    ,
1510          *  x_sql_statement       => g_pick_base
1511          *  );
1512                *IF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
1513                *  log_statement(l_api_name, 'err_build_sql',
1514                *      'Error in inv_detail_util_pvt.build_sql');
1515                *  RAISE fnd_api.g_exc_unexpected_error;
1516                *ELSIF l_return_status = fnd_api.g_ret_sts_error THEN
1517                *  log_statement(l_api_name, 'unexp_err_build_sql',
1518                *    'Unexp. error in inv_detail_util_pvt.build_sql');
1519                *  RAISE fnd_api.g_exc_error;
1520                *END IF;
1521                *log_statement(l_api_name, 'success_build_sql',
1522                *      'Inv_detail_util_pvt.build_sql successful');
1523 
1524                *-- replace the bind variables used in the base sql
1525                *-- with the global variables in the stored rule procedure
1526                *g_pick_base :=
1527          *   REPLACE(g_pick_base,':organization_id','g_organization_id');
1528                *g_pick_base :=
1529          *   REPLACE(g_pick_base,':inventory_item_id','g_inventory_item_id');
1530          */
1531         g_pick_base  := g_pick_base_lpn_loose;
1532       END IF;
1533 
1534          /*LPN Status Project*/
1535       -- The conversion_rate (found using GetConversionRate) is used
1536       --  to order picking locations from largest Pick UOM to smallest.
1537       -- The API call to is_sub_loc_lot_trx_allowed checks the status
1538       --  of the subinventory, locator, and lot to make sure that we can
1539       --  pick from this location
1540       g_pick_base         :=    g_line_feed
1541                  || 'SELECT x.organization_id       organization_id     '
1542                                        || g_line_feed
1543                  || '  ,x.inventory_item_id         inventory_item_id   '
1544                                        || g_line_feed
1545                  || '  ,x.revision                  revision            '
1546                                        || g_line_feed
1547                  || '  ,x.lot_number                lot_number          '
1548                                        || g_line_feed
1549                  || '  ,x.lot_expiration_date       lot_expiration_date '
1550                                        || g_line_feed
1551                  || '  ,x.subinventory_code         subinventory_code   '
1552                  || g_line_feed
1553                  || '  ,x.locator_id                locator_id          '
1554                                        || g_line_feed
1555                  || '  ,x.cost_group_id             cost_group_id       '
1556                                        || g_line_feed
1557                  || '  ,x.status_id                 status_id       '   --added status_id
1558                               || g_line_feed
1559                  || '  ,NULL                        serial_number       '
1560                                        || g_line_feed
1561                  || '  ,x.lpn_id                    lpn_id              '
1562                                        || g_line_feed
1563                  || '  ,x.project_id                project_id          '
1564                                        || g_line_feed
1565                  || '  ,x.task_id                   task_id             '
1566                                        || g_line_feed
1567                  || '  ,x.date_received             date_received       '
1568                                        || g_line_feed
1569                  || '  ,x.primary_quantity          primary_quantity    '
1570                                        || g_line_feed
1571                  || '  ,x.secondary_quantity          secondary_quantity    '         -- new
1572                                        || g_line_feed                                 -- new
1573                  || '  ,x.grade_code                  grade_code            '         -- new
1574                                        || g_line_feed                                 -- new
1575                  || '  ,x.reservable_type           reservable_type     '
1576                                        || g_line_feed
1577                  || '  ,x.locreservable             locreservable '              -- Bug 6719290 Start
1578                                        || g_line_feed
1579                  || '  ,x.lotreservable             lotreservable '
1580                                        || g_line_feed                            -- Bug 6719290 End
1581                  || '  ,NVL(loc.pick_uom_code,sub.pick_uom_code) uom_code'
1582                                        || g_line_feed
1583                  || '  ,WMS_Rule_PVT.GetConversionRate(                 '
1584                                        || g_line_feed
1585                  || '       NVL(loc.pick_uom_code, sub.pick_uom_code)   '
1586                                        || g_line_feed
1587                  || '       ,x.organization_id            '
1588                                        || g_line_feed
1589                  || '       ,x.inventory_item_id) conversion_rate       '
1590                                        || g_line_feed
1591                  || '  ,NULL locator_inventory_item_id                  '
1592                                        || g_line_feed
1593                  || '  ,NULL empty_flag                                 '
1594                                        || g_line_feed
1595                  || '  ,NULL location_current_units                     '
1596                                        || g_line_feed
1597                  || 'FROM ('
1598                  || g_pick_base
1599                   --extra line feed?                  || g_line_feed
1600                  || '     ) x                                           '
1601                                        || g_line_feed
1602                  || '    ,mtl_secondary_inventories sub                 '
1603                                        || g_line_feed
1604                  || '    ,mtl_item_locations loc                        '
1605                                        || g_line_feed
1606                  || 'WHERE x.organization_id = loc.organization_id (+)  '
1607                                        || g_line_feed
1608                  || '   AND x.locator_id = loc.inventory_location_id (+)'
1609                                        || g_line_feed
1610                  || '   AND sub.organization_id = x.organization_id     '
1611                                        || g_line_feed
1612                  || '   AND sub.secondary_inventory_name = x.subinventory_code '
1613                                        || g_line_feed; /*
1614                  || '   AND inv_detail_util_pvt.is_sub_loc_lot_trx_allowed('
1615                                        || g_line_feed
1616                  || '       g_transaction_type_id,          '
1617                                        || g_line_feed
1618                  || '       x.organization_id,            '
1619                                        || g_line_feed
1620                  || '       x.inventory_item_id,            '
1621                                        || g_line_feed
1622                  || '       x.subinventory_code,            '
1623                                        || g_line_feed
1624                  || '       x.locator_id,             '
1625                                       || g_line_feed
1626                 || '       x.lot_number)=''Y''                   '
1627                                       || g_line_feed;    */
1628       --
1629 
1630       -- finally apply the corrections to the basis SQL
1631       g_base_from         := g_base_from || ',(' || g_pick_base || ') '
1632                           || g_base_table_alias || g_line_feed;
1633       --Construct the base for the serial cursor
1634       g_base_from_serial  := g_base_from_serial || ',(' || g_pick_base_serial;
1635       g_base_from_serial_v  := g_base_from_serial_v || ',(' || g_pick_base_serial_v;
1636       g_base_from_serial_detail  := g_base_from_serial_detail || ',(' || g_pick_base_serial_detail;
1637 
1638       --need to add restrictions to serial base if we are allocating
1639       -- entire LPNs only
1640       --bug 2943552
1641       --  previoulsy, we were adding the new clause directly to
1642       --  g_pick_base_serial.  However, g_pick_base_serial is a global
1643       --  constant string that never gets cleared.  As a result, all
1644       --  subsequent serial sql statements would get this restriction.
1645       --  Now, we add the entire lpn only clause to g_base_from_serial.
1646       --bug 3064635 - after above fix, we were missing initial
1647       -- parantheses, because we were concatenating clause with
1648       -- g_pick_base_serial.  Now, we concatenate clause with
1649       -- g_base_from_serial
1650       IF p_allocation_mode_id = g_alloc_lpn_only THEN
1651         g_base_from_serial  := g_base_from_serial
1652                          || 'and msn.lpn_id IS NOT NULL
1653                              and not exists(
1654                                   select lpn_id
1655                                   from wms_license_plate_numbers wlpn1
1656                                   where wlpn1.parent_lpn_id = msn.lpn_id)
1657                                      and
1658                                         1 = (select count(distinct(moq1.inventory_item_id))
1659                                              from mtl_onhand_quantities_detail moq1
1660                                              where moq1.organization_id = msn.current_organization_id
1661                              and moq1.subinventory_code = msn.current_subinventory_code
1662                              and moq1.locator_id = msn.current_locator_id
1663                              and moq1.lpn_id = msn.lpn_id)
1664                             ';
1665       -- END IF;
1666     /* g_base_from_serial := g_base_from_serial || ')' || g_base_table_alias
1667                        || g_line_feed; */
1668 
1669     ---
1670     g_base_from_serial_v  :=
1671                    g_base_from_serial_v
1672                 || ' and msn.lpn_id IS NOT NULL
1673           and not exists(
1674         select lpn_id
1675         from wms_license_plate_numbers wlpn1
1676         where wlpn1.parent_lpn_id = msn.lpn_id)
1677           and
1678              1 = (select count(distinct(moq1.inventory_item_id))
1679                    from mtl_onhand_quantities_detail moq1
1680                    where moq1.organization_id = msn.current_organization_id
1681          and moq1.subinventory_code = msn.current_subinventory_code
1682          and moq1.locator_id = msn.current_locator_id
1683          and moq1.lpn_id = msn.lpn_id)
1684          ';
1685 
1686     ---
1687     g_base_from_serial_detail  :=
1688                    g_base_from_serial_detail
1689                 || ' and msn.lpn_id IS NOT NULL
1690           and not exists(
1691         select lpn_id
1692         from wms_license_plate_numbers wlpn1
1693         where wlpn1.parent_lpn_id = msn.lpn_id)
1694           and
1695              1 = (select count(distinct(moq1.inventory_item_id))
1696                    from mtl_onhand_quantities_detail moq1
1697                    where moq1.organization_id = msn.current_organization_id
1698          and moq1.subinventory_code = msn.current_subinventory_code
1699          and moq1.locator_id = msn.current_locator_id
1700          and moq1.lpn_id = msn.lpn_id)
1701          ';
1702 
1703       END IF;
1704 
1705         g_base_from_serial := g_base_from_serial || ')' || g_base_table_alias
1706                 || g_line_feed;
1707         g_base_from_serial_v := g_base_from_serial_v || ')' || g_base_table_alias
1708                 || g_line_feed;
1709 
1710         g_base_from_serial_detail := g_base_from_serial_detail || ')' || g_base_table_alias
1711                 || g_line_feed;
1712 
1713     --
1714     END IF;
1715 
1716     --currently used only for serial controlled item, when you aren't
1717     -- detailing serial numbers
1718     g_base_group_by     :=    g_base_table_alias
1719                            || '.ORGANIZATION_ID'
1720                            || g_line_feed
1721                            || ','
1722                            || g_base_table_alias
1723                            || '.INVENTORY_ITEM_ID'
1724                            || g_line_feed
1725                            || ','
1726                            || l_type_dependent_alias
1727                            || '.REVISION'
1728                            || g_line_feed
1729                            || ','
1730                            || l_type_dependent_alias
1731                            || '.LOT_NUMBER'
1732                            || g_line_feed
1733                            || ','
1734                            || g_base_table_alias
1735                            || '.LOT_EXPIRATION_DATE'
1736                            || g_line_feed
1737                            || ','
1738                            || g_base_table_alias
1739                            || '.SUBINVENTORY_CODE'
1740                            || g_line_feed
1741                            || ','
1742                            || g_base_table_alias
1743                            || '.LOCATOR_ID'
1744                            || g_line_feed
1745                            || ','
1746                            || g_base_table_alias
1747                            || '.COST_GROUP_ID'
1748                            || g_line_feed
1749                            || ','
1750                            || g_base_table_alias
1751                            || '.PROJECT_ID'
1752                            || g_line_feed
1753                            || ','
1754                            || g_base_table_alias
1755                            || '.TASK_ID'
1756                            || g_line_feed
1757                            || ','
1758                            || g_base_table_alias
1759                            || '.UOM_CODE'
1760                            || g_line_feed
1761                            || ','                                               --new
1762                            || g_base_table_alias                                --new
1763                            || '.GRADE_CODE'                                     --new
1764                            || g_line_feed;                                      --new
1765 
1766     --
1767     -- group by the base lpn id only if the lpn id is in the select statement
1768     IF p_allocation_mode_id IN (g_alloc_lpn_only, g_alloc_lpn_loose) THEN
1769       g_base_group_by  := g_base_group_by || ',' || g_base_table_alias || '.LPN_ID' || g_line_feed;
1770     END IF;
1771 
1772     -- debugging portion
1773     -- can be commented ut for final code
1774     log_procedure(l_api_name, 'end', 'End BuildBaseSql');
1775   -- end of debugging section
1776   --
1777   EXCEPTION
1778     WHEN fnd_api.g_exc_error THEN
1779       x_return_status  := fnd_api.g_ret_sts_error;
1780       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1781       --
1782       log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
1783     --
1784     WHEN fnd_api.g_exc_unexpected_error THEN
1785       x_return_status  := fnd_api.g_ret_sts_unexp_error;
1786       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1787       --
1788       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
1789 
1790     --
1791     WHEN OTHERS THEN
1792       x_return_status  := fnd_api.g_ret_sts_unexp_error;
1793 
1794       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1795         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1796       END IF;
1797 
1798       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1799       --
1800       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
1801 
1802   END buildbasesql;
1803 
1804   --
1805   -- Name        : BuildRuleSQL
1806   -- Function    : Builds the rule dependent part of the rule's sql statement
1807   -- Notes       : private procedure for internal use only
1808   PROCEDURE buildrulesql(
1809     x_return_status      OUT NOCOPY    VARCHAR2
1810   , x_msg_count          OUT NOCOPY    NUMBER
1811   , x_msg_data           OUT NOCOPY    VARCHAR2
1812   , p_rule_id            IN            NUMBER
1813   , p_type_code          IN            NUMBER
1814   , p_allocation_mode_id IN            NUMBER
1815   ) IS
1816     --
1817     l_api_name                   VARCHAR2(30)                                              := 'BuildRuleSQL';
1818     -- variables needed for dynamic SQL
1819     l_identifier                 VARCHAR2(10);
1820     -- other variables
1821     l_db_object_id               wms_db_objects.db_object_id%TYPE;
1822     l_table_name                 wms_db_objects.table_name%TYPE;
1823     l_table_alias                wms_db_objects.table_alias%TYPE;
1824     l_context_dependent_flag     wms_db_objects.context_dependent_flag%TYPE;
1825     l_parent_table_alias         wms_db_objects.table_alias%TYPE;
1826     l_parameter_type_code        wms_parameters_b.parameter_type_code%TYPE;
1827     l_column_name                wms_parameters_b.column_name%TYPE;
1828     l_expression                 wms_parameters_b.expression%TYPE;
1829     l_data_type_code             wms_parameters_b.data_type_code%TYPE;
1830     l_parent_parameter_type_code wms_parameters_b.parameter_type_code%TYPE;
1831     l_parent_column_name         wms_parameters_b.column_name%TYPE;
1832     l_parent_expression          wms_parameters_b.expression%TYPE;
1833     l_parent_data_type_code      wms_parameters_b.data_type_code%TYPE;
1834     l_operand_type_code          wms_restrictions.operand_type_code%TYPE;
1835     l_operand_constant_number    wms_restrictions.operand_constant_number%TYPE;
1836     l_operand_constant_character wms_restrictions.operand_constant_character%TYPE;
1837     l_operand_constant_date      wms_restrictions.operand_constant_date%TYPE;
1838     l_operand_expression         wms_restrictions.operand_expression%TYPE;
1839     l_operand_flex_value_set_id  wms_restrictions.operand_flex_value_set_id%TYPE;
1840     l_bracket_open               wms_restrictions.bracket_open%TYPE;
1841     l_bracket_close              wms_restrictions.bracket_close%TYPE;
1842     l_validation_type            fnd_flex_value_sets.validation_type%TYPE;
1843     l_id_column_name             fnd_flex_validation_tables.id_column_name%TYPE;
1844     l_value_column_name          fnd_flex_validation_tables.value_column_name%TYPE;
1845     l_application_table_name     fnd_flex_validation_tables.application_table_name%TYPE;
1846     l_additional_where_clause    fnd_flex_validation_tables.additional_where_clause%TYPE;
1847     l_left_part_conv_fct         VARCHAR2(40);
1848     l_right_part_conv_fct        VARCHAR2(40);
1849     l_outer_join                 VARCHAR2(4);
1850     l_logical_operator           mfg_lookups.meaning%TYPE;
1851     l_asc_desc                   mfg_lookups.meaning%TYPE;
1852     l_operator                   mfg_lookups.meaning%TYPE;
1853     l_restriction_exist          BOOLEAN                                                   := FALSE;
1854     l_rule_id                    NUMBER;
1855     l_sequence_number            NUMBER;
1856     l_flex_column_name           fnd_flex_validation_tables.id_column_name%TYPE;
1857     l_order_by_string            VARCHAR2(1000);
1858     l_order_by_string1           VARCHAR2(1000); -- Added for Bug 13448337
1859     l_order_by_string2           VARCHAR2(1000); -- Added for Bug 13448337
1860     l_new_constant_character     VARCHAR2(500);
1861     --l_new_expression      VARCHAR2(4100);
1862     l_consist_string             VARCHAR2(1000);
1863     l_parameter_id NUMBER; -- Added for Bug 13448337
1864     l_object_id NUMBER;    -- Added for Bug 13448337
1865 
1866     -- cursor for all DB objects used within the rule.
1867     -- Most objects found using this query correspond to a database table
1868     -- which must be added to the from clause.
1869     -- DB Objects 1 and 2 are always included in the from clause, so
1870     --  we don't need to get them with this query.
1871     --
1872     -- 2/21/02 - remove quantity function objects from this query.  For
1873     -- putaway, we check quantity function in the Apply function.
1874     -- For picking, the quantity function object is "base", which is always
1875     -- included
1876     CURSOR objects IS
1877       -- 1. all single referenced DB objects
1878       SELECT   wdo.db_object_id
1879              , wdo.table_name
1880              , wdo.table_alias
1881              , wdo.context_dependent_flag
1882           FROM wms_db_objects wdo
1883              , wms_parameters_b wpb
1884              , (SELECT wsc.parameter_id
1885                   FROM wms_sort_criteria wsc
1886                  WHERE wsc.rule_id = p_rule_id
1887                 UNION
1888                 SELECT wr.parameter_id
1889                   FROM wms_restrictions wr
1890                  WHERE wr.rule_id = p_rule_id
1891                 UNION
1892                 SELECT wr.operand_parameter_id
1893                   FROM wms_restrictions wr
1894                  WHERE wr.rule_id = p_rule_id
1895                    AND wr.operand_type_code = 4
1896                 UNION
1897                 SELECT wrc.parameter_id
1898                   FROM wms_rule_consistencies wrc
1899                  WHERE wrc.rule_id = p_rule_id) x
1900          WHERE wpb.parameter_id = x.parameter_id
1901            AND wpb.db_object_ref_type_code = 1
1902            AND wdo.db_object_id = wpb.db_object_id
1903            AND wdo.db_object_id NOT IN (1, 2)
1904       UNION
1905       -- 2. all parents of single referenced DB objects
1906       SELECT   wdo.db_object_id
1907              , wdo.table_name
1908              , wdo.table_alias
1909              , wdo.context_dependent_flag
1910           FROM wms_db_objects wdo
1911              , (SELECT     wdop.parent_db_object_id
1912                       FROM wms_db_objects_parents wdop
1913                      WHERE wdop.type_code = p_type_code
1914                 CONNECT BY wdop.db_object_id = PRIOR wdop.parent_db_object_id
1915                 START WITH wdop.db_object_id IN (SELECT wdod.db_object_id
1916                                                    FROM wms_db_objects wdod
1917                                                       , wms_parameters_b wpbd
1918                                                       , (SELECT wscd.parameter_id
1919                                                            FROM wms_sort_criteria wscd
1920                                                           WHERE wscd.rule_id = p_rule_id
1921                                                          UNION
1922                                                          SELECT wrd.parameter_id
1923                                                            FROM wms_restrictions wrd
1924                                                           WHERE wrd.rule_id = p_rule_id
1925                                                          UNION
1926                                                          SELECT wrd.operand_parameter_id
1927                                                            FROM wms_restrictions wrd
1928                                                           WHERE wrd.rule_id = p_rule_id
1929                                                             AND wrd.operand_type_code = 4
1930                                                          UNION
1931                                                          SELECT wrcd.parameter_id
1932                                                            FROM wms_rule_consistencies wrcd
1933                                                           WHERE wrcd.rule_id = p_rule_id) xd
1934                                                   WHERE wpbd.parameter_id = xd.parameter_id
1935                                                     AND wpbd.db_object_ref_type_code = 1
1936                                                     AND wdod.db_object_id = wpbd.db_object_id)) x
1937          WHERE wdo.db_object_id = x.parent_db_object_id
1938            AND wdo.db_object_id NOT IN (1, 2)
1939       -- 3. all multi referenced DB objects
1940       UNION
1941       SELECT   wdo.db_object_id
1942              , wdo.table_name
1943              , NVL(wdorm.table_alias, wdo.table_alias)
1944              , wdo.context_dependent_flag
1945           FROM wms_db_objects wdo
1946              , wms_db_obj_ref_members wdorm
1947              , wms_db_object_references wdor
1948              , wms_parameters_b wpb
1949              , (SELECT wsc.parameter_id
1950                   FROM wms_sort_criteria wsc
1951                  WHERE wsc.rule_id = p_rule_id
1952                 UNION
1953                 SELECT wr.parameter_id
1954                   FROM wms_restrictions wr
1955                  WHERE wr.rule_id = p_rule_id
1956                 UNION
1957                 SELECT wr.operand_parameter_id
1958                   FROM wms_restrictions wr
1959                  WHERE wr.rule_id = p_rule_id
1960                    AND wr.operand_type_code = 4
1961                 UNION
1962                 SELECT wrc.parameter_id
1963                   FROM wms_rule_consistencies wrc
1964                  WHERE wrc.rule_id = p_rule_id) x
1965          WHERE wpb.parameter_id = x.parameter_id
1966            AND wpb.db_object_ref_type_code = 2
1967            AND wdor.db_object_reference_id = wpb.db_object_reference_id
1968            AND wdorm.db_object_reference_id = wdor.db_object_reference_id
1969            AND wdo.db_object_id = wdorm.db_object_id
1970            AND wdo.db_object_id NOT IN (1, 2)
1971       UNION
1972       -- 4. all parents of multi referenced DB objects
1973       SELECT   wdo.db_object_id
1974              , wdo.table_name
1975              , wdo.table_alias
1976              , wdo.context_dependent_flag
1977           FROM wms_db_objects wdo
1978              , (SELECT     wdop.parent_db_object_id
1979                       FROM wms_db_objects_parents wdop
1980                      WHERE wdop.type_code = p_type_code
1981                 CONNECT BY wdop.db_object_id = PRIOR wdop.parent_db_object_id
1982                 START WITH wdop.db_object_id IN (SELECT wdoi.db_object_id
1983                                                    FROM wms_db_objects wdoi
1984                                                       , wms_db_obj_ref_members wdormi
1985                                                       , wms_db_object_references wdori
1986                                                       , wms_parameters_b wpbi
1987                                                       , (SELECT wsc.parameter_id
1988                                                            FROM wms_sort_criteria wsc
1989                                                           WHERE wsc.rule_id = p_rule_id
1990                                                          UNION
1991                                                          SELECT wr.parameter_id
1992                                                            FROM wms_restrictions wr
1993                                                           WHERE wr.rule_id = p_rule_id
1994                                                          UNION
1995                                                          SELECT wr.operand_parameter_id
1996                                                            FROM wms_restrictions wr
1997                                                           WHERE wr.rule_id = p_rule_id
1998                                                             AND wr.operand_type_code = 4
1999                                                          UNION
2000                                                          SELECT wrc.parameter_id
2001                                                            FROM wms_rule_consistencies wrc
2002                                                           WHERE wrc.rule_id = p_rule_id) xi
2003                                                   WHERE wpbi.parameter_id = xi.parameter_id
2004                                                     AND wpbi.db_object_ref_type_code = 2
2005                                                     AND wdori.db_object_reference_id = wpbi.db_object_reference_id
2006                                                     AND wdormi.db_object_reference_id = wdori.db_object_reference_id
2007                                                     AND wdoi.db_object_id = wdormi.db_object_id)) x
2008          WHERE wdo.db_object_id = x.parent_db_object_id
2009            AND wdo.db_object_id NOT IN (1, 2)
2010       ORDER BY 1;
2011 
2012     --
2013     -- Finds the join conditions to join a DB object to it's parent
2014     --  DB object.  This is used to build the where clause for the rule.
2015     CURSOR conditions IS
2016       SELECT wpb.parameter_type_code
2017            , wpb.column_name
2018            , wpb.expression
2019            , wpb.data_type_code
2020            , wpbp.parameter_type_code
2021            , wpbp.column_name
2022            , wpbp.expression
2023            , wpbp.data_type_code
2024            , wdop.table_alias -- alias n.a. for multi object based parameters
2025         FROM wms_db_objects wdop, wms_parameters_b wpbp, wms_parameters_b wpb, wms_db_object_joins wdoj
2026        WHERE wdoj.db_object_id = l_db_object_id
2027          AND wdoj.type_code = p_type_code
2028          AND wpb.parameter_id = wdoj.parameter_id
2029          AND wpbp.parameter_id = wdoj.parent_parameter_id
2030          AND wdop.db_object_id(+) = wpbp.db_object_id;
2031 
2032     --
2033     -- cursor for the quantity function parameter of the actual rule.
2034     -- Used only for picking and putaway
2035     CURSOR qtyfnct IS
2036       SELECT wpb.parameter_type_code
2037            , wpb.column_name
2038            , wpb.expression
2039            , wpb.data_type_code
2040            , wdo.table_alias -- alias n.a. for multi object based parameters
2041         FROM wms_db_objects wdo, wms_parameters_b wpb, wms_rules_b wrb
2042        WHERE wrb.rule_id = p_rule_id
2043          AND wpb.parameter_id = wrb.qty_function_parameter_id
2044          AND wdo.db_object_id(+) = wpb.db_object_id;
2045 
2046     --
2047     -- Finds the restrictions defined in the rule.
2048     --  Each restriction becomes part of the where clause.
2049     CURSOR RESTRICT IS
2050       SELECT   wpbl.parameter_type_code
2051              , wpbl.column_name
2052              , wpbl.expression
2053              , wpbl.data_type_code
2054              , wdol.table_alias -- alias n.a. for multi object based parameters
2055              , DECODE(
2056                  wr.operator_code
2057                , 1, '>'
2058                , 2, '<'
2059                , 3, '='
2060                , 4, '<>'
2061                , 5, '>='
2062                , 6, '<='
2063                , 7, 'IN'
2064                , 8, 'NOT IN'
2065                , 9, 'LIKE'
2066                , 10, 'NOT LIKE'
2067                , 11, 'IS NULL'
2068                , 12, 'IS NOT NULL'
2069                , NULL
2070                )
2071              , wr.operand_type_code
2072              , wr.operand_constant_number
2073              , wr.operand_constant_character
2074              , wr.operand_constant_date
2075              , wr.operand_expression
2076              , wr.operand_flex_value_set_id
2077              , DECODE(wr.logical_operator_code, 1, 'and', 2, 'or', NULL)
2078              , wr.bracket_open
2079              , wr.bracket_close
2080              , wpbr.parameter_type_code
2081              , wpbr.column_name
2082              , wpbr.expression
2083              , DECODE(
2084                  wr.operand_type_code
2085                , 4, wpbr.data_type_code
2086                , 5, wpbl.data_type_code
2087                , 6, DECODE(ffvs.format_type, 'N', 1, 'C', 2, 3)
2088                , 7, NULL
2089                , wr.operand_type_code
2090                )
2091              , wdor.table_alias -- alias n.a. for multi object based parameters
2092              , ffvs.validation_type -- only 'independent' and 'table' are supported
2093              , ffvt.id_column_name
2094              , ffvt.value_column_name
2095              , ffvt.application_table_name
2096              , ffvt.additional_where_clause
2097              , wr.rule_id
2098              , wr.sequence_number
2099           FROM fnd_flex_validation_tables ffvt
2100              , fnd_flex_value_sets ffvs
2101              , wms_db_objects wdor
2102              , wms_parameters_b wpbr
2103              , wms_db_objects wdol
2104              , wms_parameters_b wpbl
2105              , wms_restrictions wr
2106          WHERE wr.rule_id = p_rule_id
2107            AND wpbl.parameter_id = wr.parameter_id
2108            AND wdol.db_object_id(+) = wpbl.db_object_id
2109            AND wpbr.parameter_id(+) = wr.operand_parameter_id
2110            AND wdor.db_object_id(+) = wpbr.db_object_id
2111            AND ffvs.flex_value_set_id(+) = wr.operand_flex_value_set_id
2112            AND ffvt.flex_value_set_id(+) = wr.operand_flex_value_set_id
2113       ORDER BY wr.rule_id, wr.sequence_number -- order is important
2114                                              ;
2115 
2116     --
2117     -- Finds the Sort criteria entries for this rule.  Each sort criterion
2118     -- becomes a part of the order by clause of the sql statement.
2119     CURSOR sortcrit IS
2120       SELECT   wpb.parameter_type_code
2121              , wpb.column_name
2122              , wpb.expression
2123              , wpb.data_type_code
2124              , wdo.table_alias -- alias n.a. for multi object based parameters
2125              , wms_parameter_pvt.getflexdatatypecode(
2126                  wpb.data_type_code
2127                , wpb.db_object_ref_type_code
2128                , wpb.parameter_type_code
2129                , wpb.flexfield_usage_code
2130                , wpb.flexfield_application_id
2131                , wpb.flexfield_name
2132                , wpb.column_name
2133                )
2134              , DECODE(wsc.order_code, 1, 'asc', 2, 'desc', NULL)
2135              , wsc.rule_id
2136              , wsc.sequence_number
2137 	     , wpb.object_id       -- Added for Bug 13448337
2138              , wsc.parameter_id    -- Added for Bug 13448337
2139           FROM wms_db_objects wdo, wms_parameters_b wpb, wms_sort_criteria wsc
2140          WHERE wsc.rule_id = p_rule_id
2141            AND wpb.parameter_id = wsc.parameter_id
2142            AND wdo.db_object_id(+) = wpb.db_object_id
2143       ORDER BY wsc.rule_id, wsc.sequence_number;
2144 
2145     --
2146     -- Used to find all the consistency restrictions for the rule.
2147     -- Used to build portions of the Select and order by clauses.
2148     CURSOR consistencies IS
2149       SELECT wpb.parameter_type_code
2150            , wpb.column_name
2151            , wpb.expression
2152            , wdo.table_alias
2153         FROM wms_rule_consistencies wrc, wms_parameters_b wpb, wms_db_objects wdo
2154        WHERE wrc.rule_id = p_rule_id
2155          AND wpb.parameter_id = wrc.parameter_id
2156          AND wdo.db_object_id(+) = wpb.db_object_id;
2157   BEGIN
2158     -- Initialize API return status to success
2159     x_return_status    := fnd_api.g_ret_sts_success;
2160 
2161     log_procedure(l_api_name, 'start', 'Start BuildRuleSql');
2162     log_statement(l_api_name, 'rule_id', 'rule_id: ' || p_rule_id);
2163     log_statement(l_api_name, 'type_code', 'type_code: ' || p_type_code);
2164 
2165     -- end of debugging section
2166     --
2167     --If no rule, build default rule
2168     IF p_rule_id IS NULL THEN
2169       log_statement(l_api_name, 'null_rule_id', 'Rule id is NULL');
2170 
2171       -- if no rule and strategy is defined
2172       -- hardcoded this section
2173       IF p_type_code = 2 THEN
2174         g_rule_select  := 'NULL serial_number
2175                           ,nvl(base.primary_quantity,0)
2176                           ,nvl(base.secondary_quantity,0)              -- new
2177                           ,base.grade_code,                            -- new
2178                           ,NULL consist_string,
2179                           ,NULL order_by_string';
2180         g_rule_from    := ' mtl_system_items msi, ';
2181         g_rule_where   :=
2182                          ' and msi.ORGANIZATION_ID = mptdtv.FROM_ORGANIZATION_ID
2183                            and msi.INVENTORY_ITEM_ID = mptdtv.inventory_item_id ';
2184       ELSE
2185         g_rule_select  := 'NULL serial_number
2186                           ,nvl(WMS_Parameter_PVT.GetAvailableUnitCapacity
2187                                 (  mptdtv.TO_ORGANIZATION_ID
2188                                    ,base.SUBINVENTORY_CODE
2189                                    ,base.LOCATOR_ID
2190                                    ,mil.LOCATION_MAXIMUM_UNITS
2191                                 )
2192                                ,0)
2193                           ,NULL consist_string
2194                           ,NULL order_by_string';
2195         g_rule_from    := ' mtl_item_locations mil , ';
2196         g_rule_where   := ' and mil.ORGANIZATION_ID (+) = base.ORGANIZATION_ID
2197                             and mil.INVENTORY_LOCATION_ID (+) = base.locator_id ';
2198       END IF;
2199 
2200       g_rule_order     := NULL;
2201       g_rule_order_new := NULL; -- Added for Bug 13448337
2202       --
2203       x_return_status  := fnd_api.g_ret_sts_success;
2204       RETURN;
2205     END IF;
2206 
2207     -- Find all DB objects referenced within the rule and add them to the
2208     -- from clause.
2209     log_statement(l_api_name, 'start_objects', 'start objects loop');
2210     OPEN objects;
2211 
2212     WHILE TRUE LOOP
2213       FETCH objects INTO l_db_object_id, l_table_name, l_table_alias, l_context_dependent_flag;
2214       EXIT WHEN objects%NOTFOUND;
2215       log_statement(l_api_name, 'db_object_id', 'db_object_id: ' || l_db_object_id);
2216 
2217       --
2218       -- Add DB objects to the from clause
2219 
2220       -- For TTA, if g_rule_from is NULL, do no add ','
2221       -- Don't add a comma for the first table in the from clause
2222       IF  (g_rule_from IS NULL)
2223           AND (p_type_code IN (3, 4, 5, 7)) THEN -- brach for TTA
2224         g_rule_from  := l_table_name || ' ' || l_table_alias;
2225       ELSE
2226         g_rule_from  := l_table_name || ' ' || l_table_alias || g_line_feed || ',' || g_rule_from;
2227       END IF; -- end TTA branch
2228 
2229       -- Find each join condition joining current db object to its
2230       -- parent db object.  Add these conditions to the where clause.
2231       log_statement(l_api_name, 'start_conditions', 'start conditions loop');
2232       OPEN conditions;
2233 
2234       WHILE TRUE LOOP
2235         FETCH conditions INTO l_parameter_type_code
2236                             , l_column_name
2237                             , l_expression
2238                             , l_data_type_code
2239                             , l_parent_parameter_type_code
2240                             , l_parent_column_name
2241                             , l_parent_expression
2242                             , l_parent_data_type_code
2243                             , l_parent_table_alias;
2244         EXIT WHEN conditions%NOTFOUND;
2245         --
2246         log_statement(l_api_name, 'param_type_code', 'param_type_code: ' || l_parameter_type_code);
2247         log_statement(l_api_name, 'column_name', 'column_name: ' || l_column_name);
2248         log_statement(l_api_name, 'expression', 'expression: ' || l_expression);
2249         log_statement(l_api_name, 'data_type_code', 'data_type_code: ' || l_data_type_code);
2250         log_statement(l_api_name, 'parent_param_type_code', 'parent_param_type_code: ' || l_parent_parameter_type_code);
2251         log_statement(l_api_name, 'parent_column_name', 'parent_column_name: ' || l_parent_column_name);
2252         log_statement(l_api_name, 'parent_expression', 'parent_expression: ' || l_parent_expression);
2253         log_statement(l_api_name, 'parent_data_type_code', 'parent_data_type_code: ' || l_parent_data_type_code);
2254         log_statement(l_api_name, 'parent_table_alias', 'parent_table_alias: ' || l_parent_table_alias);
2255         -- find out, if data type conversion is needed
2256         inv_sql_binding_pvt.getconversionstring(l_data_type_code, l_parent_data_type_code, l_left_part_conv_fct, l_right_part_conv_fct);
2257 
2258         --
2259         -- find out, if outer join has to be used
2260         IF l_context_dependent_flag = 'Y' THEN
2261 
2262 		     --- Bug# 6893143
2263           --- Don't use outer join for mtl_lot_numbers and mtl_transaction_lots_temp table
2264           --- db_object_id = 6 for mtl_lot_numbers table
2265           --- parent_table_alias = 'mtlt' for mtl_transaction_lots_temp table
2266           --- this is valid for task_type assignment
2267           IF ((l_db_object_id = 6) AND (UPPER(l_parent_table_alias) = 'MTLT')
2268                AND (p_type_code = 3)) THEN
2269             log_statement(l_api_name, 'NN DEBUG', 'Removing outer join between MLN AND MTLT');
2270             l_outer_join  := NULL;
2271           ELSE
2272           l_outer_join  := ' (+)';
2273 		   END IF;
2274         ELSIF l_context_dependent_flag = 'N' THEN
2275 		  --- Bug# 6893143
2276           --- USE outer join for mtl_transaction_lots_temp and mtl_material_transactions_temp table
2277           --- db_object_id = 1029 for mtl_transaction_lots_temp table
2278           --- parent_table_alias = 'mmtt' for mtl_material_transactions_temp table
2279           --- this is valid for task_type assignment
2280           IF ((l_db_object_id = 1029) AND (UPPER(l_parent_table_alias) = 'MMTT')
2281                AND (p_type_code = 3)) THEN
2282             log_statement(l_api_name, 'NN DEBUG', 'Adding outer join between MTLT AND MMTT');
2283             l_outer_join  := ' (+)';
2284           ELSE
2285           l_outer_join  := NULL;
2286 		   END IF;
2287         ELSE
2288           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2289             fnd_message.set_name('WMS', 'WMS_BAD_CONTEXT_DEPT_FLAG');
2290             fnd_message.set_token('CONTEXT_DEPENDENT_FLAG', l_context_dependent_flag);
2291             log_error_msg(l_api_name, 'bad_context_depend_flag');
2292             fnd_msg_pub.ADD;
2293           END IF;
2294 
2295           RAISE fnd_api.g_exc_error;
2296         END IF;
2297 
2298         --
2299         -- add join conditions to where clause
2300         -- first, build the left side of the join
2301         g_rule_where  := g_rule_where || 'and ';
2302 
2303         IF l_parameter_type_code = 1 THEN -- based on column in table
2304           --g_rule_where  := g_rule_where || l_table_alias || '.' || l_column_name || l_outer_join;
2305           IF l_column_name = 'EFFECTIVITY_DATE' THEN   -- Bug 8212802
2306 
2307             IF l_parent_parameter_type_code = 1 THEN
2308                 g_rule_where  := g_rule_where || ' NVL(' || l_table_alias || '.' || l_column_name || ','||  l_left_part_conv_fct || l_parent_table_alias || '.' || l_parent_column_name|| l_right_part_conv_fct || ') ';
2309             ELSIF l_parent_parameter_type_code = 2 THEN
2310                 g_rule_where  := g_rule_where || ' NVL(' || l_table_alias || '.' || l_column_name || ','||  l_left_part_conv_fct || l_parent_expression|| l_right_part_conv_fct || ') ';
2311             ELSE
2312                 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2313                     fnd_message.set_name('WMS', 'WMS_BAD_PARENT_PARA_TYPE');
2314                     fnd_message.set_token('PARENT_PARAMETER_TYPE_CODE', l_parent_parameter_type_code);
2315                     log_error_msg(l_api_name, 'bad_parent_param_type_joins');
2316                     fnd_msg_pub.ADD;
2317                 END IF;
2318                 RAISE fnd_api.g_exc_error;
2319             END IF;
2320 
2321           ELSE
2322               g_rule_where  := g_rule_where || l_table_alias || '.' || l_column_name || l_outer_join;
2323           END IF;
2324 
2325         ELSIF l_parameter_type_code = 2 THEN -- based on expression
2326           --g_rule_where  := g_rule_where || l_expression || l_outer_join;
2327           g_rule_where  := g_rule_where || l_expression ;    -- || l_outer_join; --Bug #3719043
2328         ELSE
2329           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2330             fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2331             fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2332             log_error_msg(l_api_name, 'bad_param_type_code_joins');
2333             fnd_msg_pub.ADD;
2334           END IF;
2335 
2336           RAISE fnd_api.g_exc_error;
2337         END IF;
2338 
2339         IF l_column_name = 'EFFECTIVITY_DATE' THEN   -- Bug 8212802
2340         g_rule_where  := g_rule_where || ' <= ' || l_left_part_conv_fct;
2341         ELSE
2342         g_rule_where  := g_rule_where || ' = ' || l_left_part_conv_fct;
2343         END IF;
2344 
2345         -- now, build right side of join condition
2346         IF l_parent_parameter_type_code = 1 THEN
2347 		  --- Bug# 6893143
2348         --- we need to form condition mln.LOT_NUMBER = nvl(mmtt.LOT_NUMBER,mtlt.LOT_NUMBER)
2349         --- db_object_id = 6 for mtl_lot_numbers table
2350         --- parent_table_alias = 'mtlt' for mtl_transaction_lots_temp table
2351         --- this is valid for task_type assignment
2352           IF ((l_db_object_id = 6) AND (UPPER(l_parent_table_alias) = 'MTLT')
2353           AND (UPPER(l_parent_column_name)= 'LOT_NUMBER')
2354           AND (UPPER(l_column_name) = 'LOT_NUMBER')
2355           AND (p_type_code = 3)) THEN
2356             g_rule_where  := g_rule_where || 'nvl(mmtt.LOT_NUMBER,'||l_parent_table_alias || '.' || l_parent_column_name || ')';
2357           ELSE
2358           g_rule_where  := g_rule_where || l_parent_table_alias || '.' || l_parent_column_name;
2359 		    END IF;
2360         ELSIF l_parent_parameter_type_code = 2 THEN
2361           g_rule_where  := g_rule_where || l_parent_expression;
2362         ELSE
2363           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2364             fnd_message.set_name('WMS', 'WMS_BAD_PARENT_PARA_TYPE');
2365             fnd_message.set_token('PARENT_PARAMETER_TYPE_CODE', l_parent_parameter_type_code);
2366             log_error_msg(l_api_name, 'bad_parent_param_type_joins');
2367             fnd_msg_pub.ADD;
2368           END IF;
2369 
2370           RAISE fnd_api.g_exc_error;
2371         END IF;
2372 
2373         g_rule_where  := g_rule_where || l_right_part_conv_fct || g_line_feed;
2374       END LOOP;
2375 
2376       CLOSE conditions;
2377       log_statement(l_api_name, 'end_conditions', 'end of conditions loop');
2378     END LOOP;
2379 
2380     CLOSE objects;
2381     log_statement(l_api_name, 'end_objects', 'end of objects loop');
2382 
2383     -- Add qty function parameter
2384     -- added by jcearley on 12/8/99
2385     -- qtyfunction should be added only for picking or putaway
2386     -- 2/21/02 - we no longer add the quantity function to the putaway
2387     -- sql statement.  Instead, we check capacity in Apply.
2388     -- old code: IF (p_type_code IN (1,2)) THEN
2389     IF (p_type_code = 2) THEN
2390       -- Add serial number to select statement.  If item is serial controlled,
2391       -- and we are detailing it, then get serial number from base.  Otherwise,
2392       -- set serial number to NULL
2393       IF p_type_code = 2 THEN
2394         g_rule_select  := g_rule_select || ',' || g_base_table_alias || '.SERIAL_NUMBER' || g_line_feed;
2395       ELSE
2396         g_rule_select  := g_rule_select || ',NULL SERIAL_NUMBER' || g_line_feed;
2397       END IF;
2398 
2399       -- Used when we are detailing a serial controlled item but
2400       -- not detailing serial numbers.
2401       g_rule_select_serial  := g_rule_select_serial || ',NULL SERIAL_NUMBER' || g_line_feed;
2402       log_statement(l_api_name, 'qty_func', 'finding qty function');
2403       OPEN qtyfnct;
2404       FETCH qtyfnct INTO l_parameter_type_code, l_column_name, l_expression, l_data_type_code, l_table_alias;
2405 
2406       IF qtyfnct%NOTFOUND THEN
2407         CLOSE qtyfnct;
2408 
2409         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2410           fnd_message.set_name('WMS', 'WMS_QTY_FUNC_NOT_FOUND');
2411           log_error_msg(l_api_name, 'qty_func_not_found');
2412           fnd_msg_pub.ADD;
2413         END IF;
2414 
2415         RAISE fnd_api.g_exc_error;
2416       END IF;
2417 
2418       CLOSE qtyfnct;
2419       --
2420       log_statement(l_api_name, 'param_type_code_qty', 'param_type_code: ' || l_parameter_type_code);
2421       log_statement(l_api_name, 'column_name_qty', 'column_name: ' || l_column_name);
2422       log_statement(l_api_name, 'expression_qty', 'expression: ' || l_expression);
2423       log_statement(l_api_name, 'data_type_code_qty', 'data_type_code: ' || l_data_type_code);
2424       log_statement(l_api_name, 'table_alias_qty', 'table_alias: ' || l_table_alias);
2425 
2426       IF l_data_type_code <> 1 THEN
2427         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2428           fnd_message.set_name('WMS', 'WMS_BAD_QTY_FUNC_DATA_TYPE');
2429           fnd_message.set_token('DATATYPE', l_data_type_code);
2430           log_error_msg(l_api_name, 'bad_qty_func_data_type');
2431           fnd_msg_pub.ADD;
2432         END IF;
2433 
2434         RAISE fnd_api.g_exc_error;
2435       END IF;
2436 
2437       --
2438 
2439       -- Add qty function parameter to select clause
2440       IF l_parameter_type_code = 1 THEN
2441         g_rule_select         := g_rule_select || ',nvl(' || l_table_alias || '.' || l_column_name || ',0)' || g_line_feed;
2442         g_rule_select_serial  := g_rule_select_serial || ',sum(nvl(' || l_table_alias || '.' || l_column_name || ',0))' || g_line_feed;
2443       ELSIF l_parameter_type_code = 2 THEN
2444         -- Important Detail !!!
2445         -- Since the only quantity used by the engine internally
2446         -- for picking is the primary quantity,
2447         -- the expression from the parameter is ignored here.
2448         -- Instead, we only look at the primary quantity from the
2449         -- base.
2450         -- The next line is commented out and replaced with the
2451         -- line followed.
2452 
2453         --updated by jcearley on 12/7/99
2454         -- primary quantity is only useful for picking. Thus, I'm adding a check
2455         -- on the type_code.  If it's picking, use primary qty.  If it's put away,
2456         -- use the previously commented out line.
2457         IF (p_type_code = 1) THEN --put away
2458           g_rule_select         := g_rule_select
2459                                    || ',nvl(' || l_expression || ',0)'
2460                                    || g_line_feed;
2461           g_rule_select_serial  := g_rule_select_serial
2462                                    || ',sum(nvl(' || l_expression || ',0))'
2463                                    || g_line_feed;
2464         ELSIF (p_type_code = 2) THEN
2465           g_rule_select         := g_rule_select
2466                                 || ',base.primary_quantity ' || g_line_feed
2467                                 || ',base.secondary_quantity ' || g_line_feed         -- new
2468                                 || ',base.grade_code ' || g_line_feed;                -- new
2469           g_rule_select_serial  := g_rule_select_serial
2470                                 || ',sum(base.primary_quantity) ' || g_line_feed
2471                                 || ',sum(base.secondary_quantity) ' || g_line_feed         -- new
2472                                 || ',base.grade_code ' || g_line_feed;                -- new
2473         END IF;
2474       ELSE
2475         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2476           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2477           fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2478           log_error_msg(l_api_name, 'bad_param_type_code_qty');
2479           fnd_msg_pub.ADD;
2480         END IF;
2481 
2482         RAISE fnd_api.g_exc_error;
2483       END IF; -- parameter type code = 1
2484     END IF; -- type code in 1,2
2485 
2486     --
2487     log_statement(l_api_name, 'start_restrictions', 'start restrictions loop');
2488     -- Add restrictions
2489     OPEN RESTRICT;
2490 
2491     --
2492     --  Loop through all the restrictions, adding them to where clause
2493     WHILE TRUE LOOP
2494       FETCH RESTRICT INTO l_parameter_type_code
2495                         , l_column_name
2496                         , l_expression
2497                         , l_data_type_code
2498                         , l_table_alias
2499                         , l_operator
2500                         , l_operand_type_code
2501                         , l_operand_constant_number
2502                         , l_operand_constant_character
2503                         , l_operand_constant_date
2504                         , l_operand_expression
2505                         , l_operand_flex_value_set_id
2506                         , l_logical_operator
2507                         , l_bracket_open
2508                         , l_bracket_close
2509                         , l_parent_parameter_type_code
2510                         , l_parent_column_name
2511                         , l_parent_expression
2512                         , l_parent_data_type_code
2513                         , l_parent_table_alias
2514                         , l_validation_type
2515                         , l_id_column_name
2516                         , l_value_column_name
2517                         , l_application_table_name
2518                         , l_additional_where_clause
2519                         , l_rule_id
2520                         , l_sequence_number;
2521       EXIT WHEN RESTRICT%NOTFOUND;
2522       --
2523       log_statement(l_api_name, 'sequence_num', 'sequence_num: ' || l_sequence_number);
2524 
2525       -- For first restriction, add 'and (' before adding the restrictions.
2526       -- Needed to join restrictions and other join statements already in
2527       -- the where clause.
2528       IF l_restriction_exist = FALSE THEN
2529         l_restriction_exist  := TRUE;
2530         g_rule_where         := g_rule_where || 'and (' || g_line_feed;
2531       END IF;
2532 
2533       --
2534       -- find out, if data type conversion is needed
2535       inv_sql_binding_pvt.getconversionstring(l_parent_data_type_code, l_data_type_code, l_left_part_conv_fct, l_right_part_conv_fct);
2536       log_statement(l_api_name, 'left_part', 'add left part of res');
2537 
2538       -- add left part of the restrictions
2539       IF l_parameter_type_code = 1 THEN -- parameter is table.column
2540         g_rule_where  :=    g_rule_where
2541                          || l_logical_operator
2542                          || l_bracket_open
2543                          || ' '
2544                          || l_left_part_conv_fct
2545                          || l_table_alias
2546                          || '.'
2547                          || l_column_name
2548                          || l_right_part_conv_fct
2549                          || ' '
2550                          || l_operator
2551                          || ' ';
2552       ELSIF l_parameter_type_code = 2 THEN -- parameter is an expression
2553         g_rule_where  :=    g_rule_where
2554                          || l_logical_operator
2555                          || l_bracket_open
2556                          || ' '
2557                          || l_left_part_conv_fct
2558                          || l_expression
2559                          || l_right_part_conv_fct
2560                          || ' '
2561                          || l_operator
2562                          || ' ';
2563       ELSE
2564         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2565           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2566           fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2567           log_error_msg(l_api_name, 'bad_param_type_code_left_rest');
2568           fnd_msg_pub.ADD;
2569         END IF;
2570 
2571         RAISE fnd_api.g_exc_error;
2572       END IF;
2573 
2574       --
2575       log_statement(l_api_name, 'right_part', 'add right part of res');
2576 
2577       -- add right part of the restrictions
2578 
2579       IF l_operand_type_code = 1 THEN -- right side = const. number
2580         g_rule_where  := g_rule_where || l_operand_constant_number || l_operand_expression || l_bracket_close || g_line_feed;
2581       ELSIF l_operand_type_code = 2 THEN -- right side = const. character
2582         --need to insert escape character of any apostrophes already in
2583         -- character field
2584 
2585         --first case - string of length one
2586         IF LENGTH(l_operand_constant_character) = 1 THEN
2587           --if the one character is an apostrophe, provide escape
2588           -- character, then add single quotes
2589           IF l_operand_constant_character = '''' THEN
2590             l_new_constant_character  := '''''';
2591           END IF;
2592 
2593           l_new_constant_character  := '''' || l_operand_constant_character || '''';
2594         -- second case - length > 2 - treat any single quote which is not
2595         -- the first or last character as an apostrophe, and ecape the
2596         -- character
2597         ELSIF LENGTH(l_operand_constant_character) > 2 THEN
2598           --    get the string minus the first and last characters
2599           --    (we take care of first and last characters later)
2600           l_new_constant_character  := SUBSTR(l_operand_constant_character, 2, LENGTH(l_operand_constant_character) - 2);
2601           --    replace all apostrophes with two apostrophes
2602           l_new_constant_character  := REPLACE(l_new_constant_character, '''', '''''');
2603           --    recontstruct the original string
2604           l_new_constant_character  :=
2605                          SUBSTR(l_operand_constant_character, 1, 1)
2606                          || l_new_constant_character
2607                          || SUBSTR( l_operand_constant_character , -1 , 1 );
2608         -- third case - Length 2 - treat any single quote like a single
2609         -- quote.  we deal with quotes at the beginning and end of the string
2610         -- below.
2611         ELSE
2612           l_new_constant_character  := l_operand_constant_character;
2613         END IF;
2614 
2615         IF LENGTH(l_new_constant_character) > 1 THEN
2616           --check to see if string already has single quotes around it
2617           --if not, add the quotes.
2618           --this process checks both sides. if there is an initial quote but not
2619           -- a trailing quote, only the trailing quote is added.
2620           IF (SUBSTR(l_new_constant_character, 1, 1) <> '''') THEN
2621             l_new_constant_character  := '''' || l_new_constant_character;
2622           END IF;
2623 
2624           IF (SUBSTR(l_new_constant_character, -1, 1) <> '''') THEN
2625             l_new_constant_character  := l_new_constant_character || '''';
2626           END IF;
2627         END IF;
2628 
2629         g_rule_where  := g_rule_where || l_new_constant_character || l_bracket_close || g_line_feed;
2630       ELSIF l_operand_type_code = 3 THEN -- right side = const. date
2631         --l_identifier := inv_sql_binding_pvt.InitBindVar(l_operand_constant_date);
2632         --Bug #2611142 - Add quotes before and after l_operand_constant_date
2633         g_rule_where  := g_rule_where
2634                        || ''''
2635                        || l_operand_constant_date
2636                        || ''''
2637                        || ' '
2638                        || l_operand_expression
2639                        || l_bracket_close
2640                        || g_line_feed;
2641       ELSIF l_operand_type_code = 4 THEN -- right side = parameter
2642         IF l_parent_parameter_type_code = 1 THEN -- table.column
2643           g_rule_where  :=
2644                 g_rule_where || l_parent_table_alias
2645                              || '.'
2646                              || l_parent_column_name
2647                              || l_operand_expression
2648                              || l_bracket_close
2649                              || g_line_feed;
2650         ELSIF l_parent_parameter_type_code = 2 THEN -- expression
2651           g_rule_where  := g_rule_where
2652                           || l_parent_expression
2653                           || l_operand_expression
2654                           || l_bracket_close
2655                           || g_line_feed;
2656         ELSE
2657           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2658             fnd_message.set_name('WMS', 'WMS_BAD_PARENT_PARA_TYPE');
2659             fnd_message.set_token('PARENT_PARAMETER_TYPE_CODE', l_parent_parameter_type_code);
2660             log_error_msg(l_api_name, 'bad_parent_param_type_right_rest');
2661             fnd_msg_pub.ADD;
2662           END IF;
2663 
2664           RAISE fnd_api.g_exc_error;
2665         END IF;
2666       ELSIF l_operand_type_code = 5 THEN -- right side = expression
2667         --changed by jcearley on 12/8/99 - automatically put expression
2668         -- in parentheses - prevents syntax error during rule generation
2669         g_rule_where  := g_rule_where
2670                        || '(' || l_operand_expression || ')'
2671                        || l_bracket_close
2672                        || g_line_feed;
2673       ELSIF l_operand_type_code = 6 THEN -- right side = flex value set
2674         IF l_validation_type = 'F' THEN -- > validation type 'table'
2675           IF (l_id_column_name IS NULL) THEN
2676             l_flex_column_name  := l_value_column_name;
2677           ELSE
2678             l_flex_column_name  := l_id_column_name;
2679           END IF;
2680 
2681           g_rule_where  :=    g_rule_where
2682                            || '( select '
2683                            || l_flex_column_name
2684                            || ' from '
2685                            || l_application_table_name
2686                            || ' '
2687                            || l_additional_where_clause
2688                            || ')'
2689                            || l_bracket_close
2690                            || g_line_feed;
2691         ELSIF l_validation_type = 'I' THEN -- > validation type 'independent'
2692           --l_identifier := inv_sql_binding_pvt.initbindvar
2693            -- (l_operand_flex_value_set_id);
2694           g_rule_where  :=    g_rule_where
2695                            || '( select FLEX_VALUE from '
2696                            || 'FND_FLEX_VALUES_VL where FLEX_VALUE_SET_ID = '
2697                            || l_operand_flex_value_set_id
2698                            || ' and ENABLED_FLAG = ''Y'' and sysdate between nvl('
2699                            || 'START_DATE_ACTIVE,sysdate-1) and nvl('
2700                            || 'END_DATE_ACTIVE,sysdate+1) )'
2701                            || l_bracket_close
2702                            || g_line_feed;
2703         ELSE
2704           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2705             fnd_message.set_name('WMS', 'WMS_BAD_REF_FLEXVSET_DATA');
2706             fnd_message.set_token('DATATYPE', l_validation_type);
2707             log_error_msg(l_api_name, 'bad_ref_flexvset_data');
2708             fnd_msg_pub.ADD;
2709           END IF;
2710 
2711           RAISE fnd_api.g_exc_error;
2712         END IF;
2713       ELSIF l_operand_type_code = 7 THEN -- right side = nothing
2714         g_rule_where  := g_rule_where || l_bracket_close || g_line_feed;
2715       ELSE
2716         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2717           fnd_message.set_name('WMS', 'WMS_BAD_OPERAND_TYPE_CODE');
2718           fnd_message.set_token('OPERAND_TYPE_CODE', l_operand_type_code);
2719           fnd_msg_pub.ADD;
2720         END IF;
2721 
2722         RAISE fnd_api.g_exc_error;
2723       END IF;
2724     END LOOP;
2725 
2726     CLOSE RESTRICT;
2727     --
2728     log_statement(l_api_name, 'end_restrictions', 'end restrictions loop');
2729 
2730     -- Insert bracket after adding the additional restriction clauses
2731     IF l_restriction_exist = TRUE THEN
2732       g_rule_where  := g_rule_where || ')' || g_line_feed;
2733     END IF;
2734 
2735     --
2736 
2737     l_order_by_string  := NULL;
2738     l_order_by_string1  := NULL; -- Added for Bug 13448337
2739     l_order_by_string2  := NULL; -- Added for Bug 13448337
2740 
2741     log_statement(l_api_name, 'alloc_mode', 'alloc_mode: ' || p_allocation_mode_id);
2742     log_statement(l_api_name, 'start_sort_crit', 'start sort crit loop');
2743     -- Add sort criteria
2744     OPEN sortcrit;
2745 
2746     --
2747     -- Loop through all sort criteria, adding them to Order By clause
2748     WHILE TRUE LOOP
2749       FETCH sortcrit INTO l_parameter_type_code
2750                         , l_column_name
2751                         , l_expression
2752                         , l_data_type_code
2753                         , l_table_alias
2754                         , l_parent_data_type_code
2755                         , l_asc_desc
2756                         , l_rule_id
2757                         , l_sequence_number
2758                 	, l_object_id     -- Added for Bug 13448337
2759                         , l_parameter_id; -- Added for Bug 13448337
2760       EXIT WHEN sortcrit%NOTFOUND;
2761       --
2762       log_statement(l_api_name, 'seq_number_sort', 'seq_number sort:' || l_sequence_number);
2763       -- find out, if data type conversion is needed
2764       inv_sql_binding_pvt.getconversionstring(l_parent_data_type_code
2765                                             , l_data_type_code
2766                                             , l_left_part_conv_fct
2767                                             , l_right_part_conv_fct);
2768 
2769        -- Added for Bug 13448337
2770        IF (p_type_code=2 AND l_parameter_id= 10008 AND l_object_id= 54 AND l_asc_desc = 'asc' AND p_allocation_mode_id IN (4,5)) THEN
2771                  g_pickuom_serial_case := 1;
2772                  g_pickuom_serial_flag := 1;
2773            ELSE
2774                  g_pickuom_serial_case := 0;
2775        END IF;
2776        -- End of Bug 13448337
2777 
2778       -- initialize  order by clause
2779       IF g_rule_order IS NOT NULL THEN
2780         g_rule_order  := g_rule_order || ',';
2781       END IF;
2782 
2783       -- Added for Bug 13448337
2784        IF g_rule_order_new IS NOT NULL THEN
2785            g_rule_order_new  := g_rule_order_new || ',';
2786        END IF;
2787       -- End of Bug 13448337
2788 
2789       --
2790       -- add sort criterion to order by clause
2791       IF l_parameter_type_code = 1 THEN -- table.column
2792         g_rule_order  :=    g_rule_order
2793                          || l_left_part_conv_fct
2794                          || l_table_alias
2795                          || '.'
2796                          || l_column_name
2797                          || l_right_part_conv_fct
2798                          || ' '
2799                          || l_asc_desc
2800                          || g_line_feed;
2801 
2802         -- Added for Bug 13448337
2803               IF (g_pickuom_serial_case = 1) THEN
2804                   g_rule_order_new  :=    g_rule_order_new
2805                          || l_left_part_conv_fct||'min('
2806                          || l_table_alias
2807                          || '.'
2808                          || l_column_name||')'
2809                          || l_right_part_conv_fct
2810                          || ' '
2811                          || l_asc_desc
2812                          || g_line_feed;
2813               ELSE
2814                 g_rule_order_new := g_rule_order_new
2815                          || l_left_part_conv_fct
2816                          || l_table_alias
2817                          || '.'
2818                          || l_column_name
2819                          || l_right_part_conv_fct
2820                          || ' '
2821                          || l_asc_desc
2822                          || g_line_feed;
2823               END IF;
2824        -- End of Bug 13448337
2825 
2826         --added support for Picking by UOM
2827         --build the order_by_string for the select stmt;
2828         --this string is a concatenation of all the columns in the
2829         -- order by clause.
2830         -- order by string only matters for picking - set to NULL
2831         -- if not picking
2832         -- Needed in Apply procedure.
2833         IF (p_type_code = 2) THEN --pick
2834           IF (l_order_by_string IS NULL) THEN
2835             l_order_by_string  := l_left_part_conv_fct
2836                                 || l_table_alias || '.' || l_column_name
2837                                 || l_right_part_conv_fct;
2838           ELSE
2839             -- need to hard code in '||' so string is concatenated at
2840             -- run time
2841             l_order_by_string  :=
2842                             l_order_by_string
2843                             || '||'
2844                             || l_left_part_conv_fct
2845                             || l_table_alias || '.' || l_column_name
2846                             || l_right_part_conv_fct;
2847           END IF;
2848 
2849           -- Added for Bug 13448337
2850           IF (g_pickuom_serial_case = 1) THEN
2851               IF (l_order_by_string1 IS NULL) THEN
2852                 l_order_by_string1  := l_left_part_conv_fct||'min('
2853                                 || l_table_alias || '.' || l_column_name||')'
2854                                 || l_right_part_conv_fct;
2855             ELSE
2856              l_order_by_string1 := l_order_by_string1
2857                             || '||'
2858                             || l_left_part_conv_fct||'min('
2859                             || l_table_alias || '.' || l_column_name||')'
2860                             || l_right_part_conv_fct;
2861             END IF;
2862          ELSE
2863           IF (l_order_by_string1 IS NULL) THEN
2864               l_order_by_string1  := l_left_part_conv_fct
2865                                 || l_table_alias || '.' || l_column_name
2866                                 || l_right_part_conv_fct;
2867           ELSE
2868              l_order_by_string1 :=  l_order_by_string1
2869                             || '||'
2870                             || l_left_part_conv_fct
2871                             || l_table_alias || '.' || l_column_name
2872                             || l_right_part_conv_fct;
2873           END IF;
2874           IF (l_order_by_string2 IS NULL) THEN
2875              l_order_by_string2  := l_left_part_conv_fct
2876                                 || l_table_alias || '.' || l_column_name
2877                                 || l_right_part_conv_fct;
2878           ELSE
2879              l_order_by_string2 :=  l_order_by_string2
2880                             || '||'
2881                             || l_left_part_conv_fct
2882                             || l_table_alias || '.' || l_column_name
2883                             || l_right_part_conv_fct;
2884           END IF;
2885          END IF;
2886          -- End of Bug 13448337
2887 
2888           -- include sort criteria in the group by clause, so that
2889                 --  we can preserve the sort order.  Used only when
2890                 --  detailing serial controlled items but not detailing serial
2891                 --  numbers.
2892           -- Added for Bug 13448337
2893         g_rule_group_by  := g_rule_group_by || ',' || l_table_alias || '.' || l_column_name;
2894                 IF (g_pickuom_serial_case = 1) THEN
2895                                 g_rule_group_by_new  := g_rule_group_by_new;
2896                 ELSE
2897                         g_rule_group_by_new  := g_rule_group_by_new || ',' || l_table_alias || '.' || l_column_name;
2898                 END IF;
2899         -- End of Bug 13448337
2900         END IF;
2901       ELSIF l_parameter_type_code = 2 THEN -- expression
2902         g_rule_order  := g_rule_order
2903                        || l_left_part_conv_fct
2904                        || l_expression
2905                        || l_right_part_conv_fct
2906                        || ' '
2907                        || l_asc_desc
2908                        || g_line_feed;
2909 
2910        -- Added for Bug 13448337
2911         g_rule_order_new  :=    g_rule_order_new
2912                          || l_left_part_conv_fct
2913                          || l_expression
2914                          || l_right_part_conv_fct
2915                          || ' '
2916                          || l_asc_desc
2917                          || g_line_feed;
2918         -- End of Bug 13448337
2919 
2920         --build the order_by_string for the select stmt
2921         IF (p_type_code = 2) THEN --pick
2922           IF (l_order_by_string IS NULL) THEN
2923             l_order_by_string  := l_left_part_conv_fct || l_expression || l_right_part_conv_fct;
2924             -- Added for Bug 13448337
2925                         l_order_by_string1 := l_left_part_conv_fct || l_expression || l_right_part_conv_fct;
2926                         l_order_by_string2 := l_left_part_conv_fct || l_expression || l_right_part_conv_fct;
2927           ELSE
2928             l_order_by_string  := l_order_by_string
2929                                    || '||'
2930                                    || l_left_part_conv_fct
2931                                    || l_expression
2932                                    || l_right_part_conv_fct;
2933             -- Added for Bug 13448337
2934             l_order_by_string1  := l_order_by_string1
2935                                    || '||'
2936                                    || l_left_part_conv_fct
2937                                    || l_expression
2938                                    || l_right_part_conv_fct;
2939             IF(l_order_by_string2 is NULL) THEN
2940                         l_order_by_string2 := l_left_part_conv_fct || l_expression || l_right_part_conv_fct;
2941             ELSE
2942                         l_order_by_string2  := l_order_by_string2
2943                                                || '||'
2944                                                || l_left_part_conv_fct
2945                                                || l_expression
2946                                                || l_right_part_conv_fct;
2947             END IF; -- End of Bug 13448337
2948           END IF;
2949 
2950           g_rule_group_by  := g_rule_group_by || ',' || l_expression;
2951 	  g_rule_group_by_new  := g_rule_group_by_new || ',' || l_expression; -- Added for Bug 13448337
2952         END IF;
2953       ELSE
2954         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2955           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2956           fnd_message.set_token('OPERAND_TYPE_CODE', l_parameter_type_code);
2957           log_error_msg(l_api_name, 'bad_param_type_code_sort');
2958           fnd_msg_pub.ADD;
2959         END IF;
2960 
2961         RAISE fnd_api.g_exc_error;
2962       END IF;
2963     END LOOP;
2964 
2965     CLOSE sortcrit;
2966     log_statement(l_api_name, 'end_sort_crit', 'end sort crit loop');
2967 
2968     --Pick UOM and Rule Consistencies are supported only for picking rules
2969     IF (p_type_code = 2) THEN
2970       l_consist_string  := NULL;
2971       --Get consistencies from cursor;
2972       -- These consistencies are concatenated together to form one
2973       --  string. This string is added to the select and order by for the
2974       --  rule sql, and are used in the Apply function.
2975       OPEN consistencies;
2976 
2977       LOOP
2978         FETCH consistencies INTO l_parameter_type_code, l_column_name, l_expression, l_table_alias;
2979         EXIT WHEN consistencies%NOTFOUND;
2980 
2981         -- if parameter is a db column
2982         IF l_parameter_type_code = 1 THEN
2983           IF l_consist_string IS NULL THEN
2984             l_consist_string  := l_table_alias || '.' || l_column_name;
2985           ELSE
2986             --parameter is expression
2987             l_consist_string  := l_consist_string
2988                                 || '||'
2989                                 || l_table_alias || '.' || l_column_name;
2990           END IF;
2991 
2992           -- include consistencies in the group by clause, so that
2993                 --  we can preserve them.  Used only when
2994                 --  detailing serial controlled items but not detailing serial
2995                 --  numbers.
2996           g_rule_group_by  := g_rule_group_by
2997                              || ','
2998                              || l_table_alias || '.' || l_column_name
2999                              || g_line_feed;
3000 	  -- Added for Bug 13448337
3001           g_rule_group_by_new  := g_rule_group_by_new
3002                              || ','
3003                              || l_table_alias || '.' || l_column_name
3004                              || g_line_feed;
3005           -- End of Bug 13448337
3006         -- if parameter is an expression
3007         ELSIF l_parameter_type_code = 2 THEN
3008           IF l_consist_string IS NULL THEN
3009             l_consist_string  := l_expression;
3010           ELSE
3011             l_consist_string  := l_consist_string || '||' || l_expression;
3012           END IF;
3013 
3014           g_rule_group_by  := g_rule_group_by || ',' || l_expression || g_line_feed;
3015 	  g_rule_group_by_new  := g_rule_group_by_new || ',' || l_expression || g_line_feed; -- Added for Bug 13448337
3016         ELSE
3017           fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
3018           fnd_message.set_token('OPERAND_TYPE_CODE', l_parameter_type_code);
3019           log_error_msg(l_api_name, 'bad_param_type_code_consist');
3020           fnd_msg_pub.ADD;
3021           RAISE fnd_api.g_exc_error;
3022         END IF;
3023       END LOOP;
3024 
3025       --add consist_string to the select clause
3026       -- Used in Apply procedure
3027       IF l_consist_string IS NOT NULL THEN
3028         IF g_rule_order IS NULL THEN
3029           g_rule_order  := l_consist_string || g_line_feed;
3030           g_rule_order_new  := l_consist_string || g_line_feed; -- Added for Bug 13448337
3031         ELSE
3032           g_rule_order  := g_rule_order || ',' || l_consist_string || g_line_feed;
3033           g_rule_order_new  := g_rule_order_new || ',' || l_consist_string || g_line_feed; -- Added for Bug 13448337
3034         END IF;
3035 
3036         /* No longer added consist_string to order_by_string
3037           IF l_order_by_string IS NULL THEN
3038              l_order_by_string := l_consist_string;
3039     ELSE
3040              l_order_by_string:=l_order_by_string || '||' || l_consist_string;
3041           END IF;
3042         */
3043         g_rule_select         := g_rule_select
3044                                 || ','
3045                                 || l_consist_string
3046                                 || ' consist_string'
3047                                 || g_line_feed;
3048         g_rule_select_serial  := g_rule_select_serial
3049                                 || ','
3050                                 || l_consist_string
3051                                 || ' consist_string'
3052                                 || g_line_feed;
3053         g_rule_group_by       := g_rule_group_by
3054                                 || ','
3055                                 || l_consist_string
3056                                 || g_line_feed;
3057       -- if no consistencies, don't add anything to order by
3058       ELSE
3059         g_rule_select         := g_rule_select || ',NULL consist_string' || g_line_feed;
3060         g_rule_select_serial  := g_rule_select_serial || ',NULL consist_string' || g_line_feed;
3061       END IF;
3062 
3063       --Add conversion_rate to sort criteria
3064       --if efficient pick flag is set, add conversion rate to front of order by;
3065       --otherwise, add to end of order by
3066       -- Bug#6802143: Serial Number is added in the order by and group by clause for Picking.
3067       IF (g_rule_order IS NULL) THEN
3068         -- conversion rate is only order by
3069         g_rule_order  := 'decode(base.project_id,g_project_id,1,NULL,2,3) asc' ||','||g_rule_order  -- Added for Bug 10379126
3070                           || g_base_table_alias
3071                           || '.SERIAL_NUMBER asc'
3072                           || ','
3073                           || g_base_table_alias
3074                           || '.CONVERSION_RATE desc'
3075                           || g_line_feed;
3076         g_rule_order_new := g_rule_order; -- Added for Bug 13448337
3077       ELSIF (p_allocation_mode_id IN (g_alloc_pick_uom, g_alloc_strict_pick_uom)) THEN
3078         g_rule_order  := 'decode(base.project_id,g_project_id,1,NULL,2,3) asc' ||','||g_base_table_alias -- Added for Bug 10379126
3079                           || '.CONVERSION_RATE desc'
3080                           || g_line_feed
3081                           || ','
3082                           || g_rule_order
3083                           || ','
3084                           || g_base_table_alias
3085                           || '.SERIAL_NUMBER asc'
3086                             || g_line_feed ;
3087         -- Added for Bug 13448337
3088            IF (g_pickuom_serial_flag = 1) THEN
3089                 g_rule_order_new  := 'decode(base.project_id,g_project_id,1,NULL,2,3) asc' ||','||g_rule_order_new ||','
3090                           ||g_base_table_alias
3091                           || '.CONVERSION_RATE desc'
3092                           || g_line_feed;
3093          ELSE
3094              g_rule_order_new := g_rule_order;
3095           END IF;
3096           -- End of Bug 13448337
3097       ELSE
3098         g_rule_order  := 'decode(base.project_id,g_project_id,1,NULL,2,3) asc' ||','||g_rule_order -- Added for Bug 10379126
3099                           || ','
3100                           || g_base_table_alias
3101                           || '.SERIAL_NUMBER asc'
3102                           || ','
3103                           || g_base_table_alias
3104                           || '.CONVERSION_RATE desc'
3105                           || g_line_feed;
3106 	-- Added for Bug 13448337
3107         IF (g_pickuom_serial_flag = 1) THEN
3108             g_rule_order_new := 'decode(base.project_id,g_project_id,1,NULL,2,3) asc' ||','||g_rule_order_new||','
3109                           ||g_base_table_alias -- Added for Bug 10379126
3110                           || '.CONVERSION_RATE desc'
3111                           || g_line_feed;
3112         ELSE
3113             g_rule_order_new := g_rule_order;
3114         END IF;
3115           -- End of Bug 13448337
3116       END IF;
3117 
3118       g_rule_group_by   := g_rule_group_by
3119                           || ','
3120                           || g_base_table_alias
3121                           || '.SERIAL_NUMBER'
3122                           || ','
3123                           || g_base_table_alias
3124                           || '.CONVERSION_RATE'
3125                           || g_line_feed;
3126       -- Added for Bug 13448337
3127         IF (g_pickuom_serial_flag = 1) THEN
3128          g_rule_group_by_new   := g_rule_group_by_new
3129                           || ','
3130                           || g_base_table_alias
3131                           || '.CONVERSION_RATE'
3132                           || g_line_feed;
3133           ELSE
3134            g_rule_group_by_new:=g_rule_group_by;
3135           END IF;
3136        -- End of Bug 13448337
3137 
3138       -- Add the order_by_string to the select and group by clauses.
3139       -- This string is used in the Apply procedure.
3140       g_rule_select_serial_new := g_rule_select_serial; -- Added for Bug 13448337
3141       IF (l_order_by_string IS NOT NULL) THEN
3142         g_rule_select         := g_rule_select
3143                                 || ','
3144                                 || l_order_by_string
3145                                 || ' order_by_string'
3146                                 || g_line_feed;
3147         g_rule_select_serial  := g_rule_select_serial
3148                                 || ','
3149                                 || l_order_by_string
3150                                 || ' order_by_string'
3151                                 || g_line_feed;
3152         g_rule_group_by       := g_rule_group_by || ',' || l_order_by_string || g_line_feed;
3153 	-- Added for Bug 13448337
3154          IF (g_pickuom_serial_flag = 1) THEN
3155            g_rule_select_serial_new  := g_rule_select_serial_new
3156                                 || ','
3157                                 || l_order_by_string1
3158                                 || ' order_by_string'
3159                                 || g_line_feed;
3160 
3161            IF l_order_by_string2 IS NOT null THEN
3162                 g_rule_group_by_new       := g_rule_group_by_new || ',' || l_order_by_string2 || g_line_feed;
3163            END IF;
3164          ELSE
3165                 g_rule_select_serial_new  := g_rule_select_serial;
3166                 g_rule_group_by_new       := g_rule_group_by;
3167          END IF;
3168        ELSE
3169         g_rule_select         := g_rule_select || ',NULL order_by_string' || g_line_feed;
3170         g_rule_select_serial  := g_rule_select_serial || ',NULL order_by_string' || g_line_feed;
3171         g_rule_select_serial_new  := g_rule_select_serial_new || ',NULL order_by_string' || g_line_feed;
3172       END IF;
3173       -- End of Bug 13448337
3174     ELSE --order by and consist string only useful in picking
3175       --3/13/02 added for PJM support
3176       -- Add project and task to sort criteria
3177       IF p_type_code = 1 THEN
3178         IF (g_rule_order IS NULL) THEN
3179           -- project and task  are only order by
3180           g_rule_order  :=
3181                      g_rule_order  || g_base_table_alias
3182                                    || '.PROJECT_ID' || g_line_feed
3183                                    || ',' || g_base_table_alias
3184                                    || '.TASK_ID' || g_line_feed;
3185         ELSE
3186           --bug 2983185 - g_rule_order was getting concatenated twice
3187           g_rule_order  :=    g_rule_order
3188                            || ','
3189                            || g_base_table_alias
3190                            || '.PROJECT_ID'
3191                            || g_line_feed
3192                            || ','
3193                            || g_base_table_alias
3194                            || '.TASK_ID'
3195                            || g_line_feed;
3196         END IF;
3197       END IF;
3198 
3199       g_rule_select         := g_rule_select || ',NULL consist_string' || g_line_feed;
3200       g_rule_select_serial  := g_rule_select_serial || ',NULL consist_string' || g_line_feed;
3201       g_rule_select_serial_new  := g_rule_select_serial_new || ',NULL consist_string' || g_line_feed; -- Added for Bug 13448337
3202       g_rule_select         := g_rule_select || ',NULL order_by_string' || g_line_feed;
3203       g_rule_select_serial  := g_rule_select_serial || ',NULL order_by_string' || g_line_feed;
3204       g_rule_select_serial_new  := g_rule_select_serial_new || ',NULL order_by_string' || g_line_feed; -- Added for Bug 13448337
3205     END IF;
3206 
3207     --
3208     -- Save the pointers, which mark the end of the rule sourced bind variables
3209     --inv_sql_binding_pvt.SaveBindPointers;
3210     --
3211     log_procedure(l_api_name, 'end', 'End BuildRuleSql');
3212   -- end of debugging section
3213   EXCEPTION
3214     WHEN fnd_api.g_exc_error THEN
3215       x_return_status  := fnd_api.g_ret_sts_error;
3216       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3217       --
3218       log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
3219     --
3220     WHEN fnd_api.g_exc_unexpected_error THEN
3221       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3222       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3223       --
3224       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
3225 
3226     WHEN OTHERS THEN
3227       IF objects%ISOPEN THEN
3228         CLOSE objects;
3229       END IF;
3230 
3231       IF conditions%ISOPEN THEN
3232         CLOSE conditions;
3233       END IF;
3234 
3235       IF qtyfnct%ISOPEN THEN
3236         CLOSE qtyfnct;
3237       END IF;
3238 
3239       IF RESTRICT%ISOPEN THEN
3240         CLOSE RESTRICT;
3241       END IF;
3242 
3243       IF sortcrit%ISOPEN THEN
3244         CLOSE sortcrit;
3245       END IF;
3246 
3247       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3248 
3249       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3250         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3251       END IF;
3252 
3253       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3254       --
3255       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3256   --
3257   END buildrulesql;
3258 
3259   --
3260   -- Name        : BuildInputSQL
3261   -- Function    : Adds the SQL to the where clause to handle
3262   --     input parameters
3263   -- Notes       : privat procedure for internal use only
3264   --
3265   PROCEDURE buildinputsql(
3266     x_return_status OUT NOCOPY    VARCHAR2
3267   , x_msg_count     OUT NOCOPY    NUMBER
3268   , x_msg_data      OUT NOCOPY    VARCHAR2
3269   , p_type_code     IN            NUMBER
3270   ) IS
3271     -- variables needed for dynamic SQL
3272     l_identifier VARCHAR2(10);
3273     l_api_name   VARCHAR2(30) := 'BuildIputSQL';
3274     l_is_mat_status_used  NUMBER := NVL(FND_PROFILE.VALUE('INV_MATERIAL_STATUS'), 2);
3275   BEGIN
3276     -- Initialize API return status to success
3277     x_return_status  := fnd_api.g_ret_sts_success;
3278 
3279     log_procedure(l_api_name, 'start', 'Start BuildInputSql');
3280     -- end of debugging section
3281     --
3282     --
3283     -- Add type code independent input parameters to where clause
3284     -- Notes: For picking, the sql statement already bound organization_id
3285     -- and inventory_item_id in BuildBaseSQL, so here it is redundant but
3286     -- no harm anyway
3287     g_input_where    := g_base_table_alias || '.ORGANIZATION_ID = ' || 'g_organization_id' || g_line_feed;
3288     g_input_where    := g_input_where || 'and ' || g_base_table_alias || '.INVENTORY_ITEM_ID = ' || 'g_inventory_item_id' || g_line_feed;
3289 
3290     -- the move order line can specify the subinventory, locator, revision,
3291     -- and/or lot number to use for the pick or put away. To allow for a
3292     -- generic sql cursor regardless of input values, we use the decode statments
3293     -- in the where clause.
3294     -- When Rule.Apply is called, it will look at these four input values. For
3295     -- all the input values which are Null, the Apply function will set those
3296     -- values to -9999 (or -99 for Revision). Then inside the cursor in the
3297     -- stored rule function, these decode statements make a check on the value
3298     -- of the inputs.  If the inputs = -9999 or -99 (i.e. Null), the decode
3299     -- statements create a line which always evaluate to true: a=a or 1=1.
3300     -- If the input has a non -9999 value, then that value is compared to the
3301     -- appropriate column.
3302 
3303     -- 2/21/02 - We no longer add subinventory code and locator id to the
3304     -- where clause here. for putaway.
3305     --The decode statements prevent the subinventory/locator indices from
3306     -- being used.  Instead, we add subinventory and locator to the where clause
3307     -- in GenerateRulePackage for cursors that are called only when those
3308     -- values are passed.
3309     IF (p_type_code = 2) THEN --picking only
3310       g_input_where  :=    g_input_where
3311                         || ' and '
3312                         || 'decode(g_subinventory_code, ''-9999'', ''a'', '
3313                         || g_base_table_alias
3314                         || '.SUBINVENTORY_CODE)'
3315                         || ' = '
3316                         || 'decode(g_subinventory_code, ''-9999'', ''a'', g_subinventory_code)'
3317                         || g_line_feed;
3318       --bug #1252345
3319       --if subinventory is null, we have to make sure we don't pick from
3320       --  non-reservable sub
3321       -- # 6917190
3322       -- 7280339 added check for status_id is null
3323       -- high volume project 8546026
3324      IF l_is_mat_status_used = 1 THEN
3325       g_input_where  :=    g_input_where
3326                         || ' and '
3327                         || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
3328                         || ' AND exists(select 1 from mtl_material_statuses where status_id = '
3329                         || g_base_table_alias
3330                         || '.STATUS_ID'
3331                         || ' AND RESERVABLE_TYPE = 1)) OR '
3332                         || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3333                         || ' or '
3334                         || g_base_table_alias
3335                         || '.STATUS_ID IS NULL)'
3336                         || ' and '
3337                         || 'decode(g_subinventory_code, ''-9999'', '
3338                         || g_base_table_alias
3339                         || '.RESERVABLE_TYPE, 1)'
3340                         || ' = 1))'
3341                         || g_line_feed;
3342 
3343       ELSE
3344           g_input_where  :=    g_input_where
3345                         || ' and '
3346                         || 'decode(g_subinventory_code, ''-9999'', '
3347                         || g_base_table_alias
3348                         || '.RESERVABLE_TYPE, 1)'
3349                         || ' = 1'
3350                         || g_line_feed;
3351       END IF;
3352 
3353       g_input_where  :=    g_input_where
3354                         || ' and '
3355                         || 'decode(g_locator_id, -9999, 1, '
3356                         || g_base_table_alias
3357                         || '.locator_id)'
3358                         || ' = '
3359                         || 'decode(g_locator_id,-9999, 1, g_locator_id)'
3360                         || g_line_feed;
3361       -- Bug 6719290, 6917190
3362       IF l_is_mat_status_used = 1 THEN
3363          g_input_where  :=    g_input_where
3364                           || ' and '
3365                           || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
3366                           || ' AND exists(select 1 from mtl_material_statuses where status_id = '
3367                           || g_base_table_alias
3368                           || '.STATUS_ID'
3369                           || ' AND RESERVABLE_TYPE = 1)) OR '
3370                           || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3371                           || 'or '
3372                           || g_base_table_alias
3373                           || '.STATUS_ID IS NULL)'
3374                           || ' and '
3375                           || 'decode(g_locator_id, -9999, '
3376                           || g_base_table_alias
3377                           || '.locreservable, 1)'
3378                           || ' = 1))'
3379                           || g_line_feed;
3380       END IF ;
3381 
3382     END IF;
3383 
3384      IF (p_type_code = 2) THEN
3385         g_input_where  :=    g_input_where
3386                           || ' and '
3387                           || 'decode(g_revision, ''-99'', ''a'', '
3388                           || g_base_table_alias
3389                           || '.REVISION)'
3390                           || ' = '
3391                           || 'decode(g_revision, ''-99'', ''a'', g_revision)'
3392                           || g_line_feed;
3393         g_input_where  :=    g_input_where
3394                           || ' and '
3395                           || 'decode(g_lot_number, ''-9999'', ''a'', '
3396                           || g_base_table_alias
3397                           || '.LOT_NUMBER)'
3398                           || ' = '
3399                           || 'decode(g_lot_number, ''-9999'', ''a'', g_lot_number)'
3400                           || g_line_feed;
3401        -- Bug 6719290, 6917190
3402       IF l_is_mat_status_used = 1 THEN
3403          g_input_where  :=    g_input_where
3404                             || ' and '
3405                             || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
3406                             || ' AND exists(select 1 from mtl_material_statuses where status_id = '
3407                             || g_base_table_alias
3408                             || '.STATUS_ID'
3409                             || ' AND RESERVABLE_TYPE = 1)) OR '
3410                             || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3411                             || 'or '
3412                             || g_base_table_alias
3413                             || '.STATUS_ID IS NULL)'
3414                             || ' and '
3415                             || 'decode(g_lot_number, ''-9999'', '
3416                             || 'decode (INV_Pick_Release_PVT.g_pick_nonrsv_lots,1,1,' --8719074
3417                             || g_base_table_alias
3418                             || '.lotreservable), 1)'
3419                             || ' = 1))'
3420                             || g_line_feed;
3421       END IF ;
3422 
3423         g_input_where  :=    g_input_where
3424                           || ' and '
3425                           || 'decode(g_lpn_id, -9999, 1, '
3426                           || g_base_table_alias
3427                           || '.lpn_id)'
3428                           || ' = '
3429                           || 'decode(g_lpn_id, -9999, 1, g_lpn_id)'
3430                           || g_line_feed;
3431         --cost group doesn't affect finding put away locations,
3432         -- so only check input for pick
3433         g_input_where  :=    g_input_where
3434                           || ' and '
3435                           || 'decode(g_cost_group_id, -9999, 1, '
3436                           || g_base_table_alias
3437                           || '.cost_group_id)'
3438                           || ' = '
3439                           || 'decode(g_cost_group_id, -9999, 1, g_cost_group_id)'
3440                           || g_line_feed;
3441         -- Adding project_id and task_id to support PJM-- Added for Bug 10379126, commented code
3442         /*g_input_where  :=    g_input_where
3443                           || ' and '
3444                           || '(decode(g_project_id, -9999, -1, '
3445                           || g_base_table_alias
3446                           || '.project_id)'
3447                           || ' = '
3448                           || 'decode(g_project_id, -9999, -1, g_project_id)'
3449                           || ' OR '
3450                           || '( g_project_id = -7777 '
3451                           || ' and '
3452                           || g_base_table_alias
3453                           || '.project_id IS NULL)) '
3454                           || g_line_feed;
3455         -- If Allow Cross Project Pick is set to NO then task must be exactly equal even if NULL
3456         g_input_where  :=    g_input_where
3457                           || ' and '
3458                           || '(g_project_id = -9999'
3459                           || ' OR '
3460                           || 'nvl('
3461                           || g_base_table_alias
3462                           || '.task_id, -9999)'
3463                           || ' = '
3464                           || 'g_task_id'
3465                           || ' OR '
3466                           || '(g_task_id = -7777'
3467                           || ' and '
3468                           || g_base_table_alias
3469                           || '.task_id IS NULL))'
3470                           || g_line_feed;*/ -- End of Commented code for Bug 10379126
3471     END IF;
3472 
3473     IF (p_type_code = 1) THEN
3474       -- Adding project_id and task_id to support PJM
3475       g_input_where  :=    g_input_where
3476                         || ' and ('
3477                         || 'g_project_id = '
3478                         || g_base_table_alias
3479                         || '.project_id OR '
3480                         || g_base_table_alias
3481                         || '.project_id IS NULL)'
3482                         || g_line_feed;
3483       g_input_where  :=    g_input_where
3484                         || ' and ('
3485                         || 'g_task_id = '
3486                         || g_base_table_alias
3487                         || '.task_id OR '
3488                         || g_base_table_alias
3489                         || '.task_id IS NULL)'
3490                         || g_line_feed;
3491     END IF;
3492 
3493     -- always join to the input table
3494     g_input_where    :=
3495                       g_input_where || ' and ' || g_input_table_alias || '.PP_TRANSACTION_TEMP_ID = ' || 'g_pp_transaction_temp_id' || g_line_feed;
3496 
3497      --Bug9669364
3498     g_input_where    :=
3499                       g_input_where || ' and ' || 'Wms_Rule_Pvt.Match_Planning_Group('
3500                       || 'base.ORGANIZATION_ID,base.locator_id, g_project_id,'
3501                       || ' mptdtv.project_id, mptdtv.task_id,g_transaction_type_id,g_inventory_item_id,base.project_id,base.task_id) = 1'-- Added for Bug 10379126
3502                       || g_line_feed;
3503 
3504     --Bug9669364 end
3505 
3506 
3507     -- end of debugging section
3508     log_procedure(l_api_name, 'end', 'End BuildInputSql');
3509   --
3510   EXCEPTION
3511     WHEN OTHERS THEN
3512       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3513 
3514       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3515         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3516       END IF;
3517 
3518       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3519       --
3520       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3521   --
3522   END buildinputsql;
3523 
3524   FUNCTION isruledebugon(p_simulation_mode IN NUMBER)
3525     RETURN BOOLEAN IS
3526     l_return_value BOOLEAN;
3527     l_debug NUMBER;
3528   BEGIN
3529    IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3530       g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3531    END IF;
3532     l_debug := g_debug;
3533     IF p_simulation_mode <> wms_engine_pvt.g_no_simulation THEN
3534       l_return_value  := TRUE;
3535     ELSIF  p_simulation_mode = wms_engine_pvt.g_no_simulation THEN
3536       if l_debug = 1 THEN
3537          l_return_value  := TRUE;
3538       ELSE
3539          l_return_value  := FALSE;
3540       END IF;
3541     ELSE
3542       null;
3543       --l_return_value  := fnd_log.test(log_level => fnd_log.level_unexpected, module => 'wms.plsql.' || g_pkg_name || '.' || 'Apply.test');
3544     END IF;
3545 
3546     IF l_return_value THEN
3547       if l_debug = 1 THEN
3548        log_statement('IsRuleDebugOn', 'true', 'Debug is on');
3549       END IF;
3550     ELSE
3551       IF l_debug = 1 THEN
3552          log_statement('IsRuleDebugOn', 'false', 'Debug is off');
3553       END IF;
3554     END IF;
3555 
3556     RETURN l_return_value;
3557   END isruledebugon;
3558 
3559   --
3560   -- Name        : FetchCursor
3561   -- Function    : Fetches one record at a time from the Rule's
3562   --     SQL statement, using the rule API
3563   -- Pre-reqs    : cursor has to be parsed and executed already.
3564   -- Notes       : private procedure for internal use only
3565   --
3566   PROCEDURE fetchcursor(
3567     x_return_status       OUT NOCOPY    VARCHAR2
3568   , x_msg_count           OUT NOCOPY    NUMBER
3569   , x_msg_data            OUT NOCOPY    VARCHAR2
3570   , p_cursor              IN            wms_rule_pvt.cv_pick_type
3571   , p_rule_id             IN            NUMBER
3572   , x_revision            OUT NOCOPY    VARCHAR2
3573   , x_lot_number          OUT NOCOPY    VARCHAR2
3574   , x_lot_expiration_date OUT NOCOPY    DATE
3575   , x_subinventory_code   OUT NOCOPY    VARCHAR2
3576   , x_locator_id          OUT NOCOPY    NUMBER
3577   , x_cost_group_id       OUT NOCOPY    NUMBER
3578   , x_uom_code            OUT NOCOPY    VARCHAR2
3579   , x_lpn_id              OUT NOCOPY    NUMBER
3580   , x_serial_number       OUT NOCOPY    VARCHAR2
3581   , x_possible_quantity   OUT NOCOPY    NUMBER
3582   , x_sec_possible_quantity  OUT NOCOPY NUMBER
3583   , x_grade_code             OUT NOCOPY VARCHAR2
3584   , x_consist_string      OUT NOCOPY    VARCHAR2
3585   , x_order_by_string     OUT NOCOPY    VARCHAR2
3586   , x_rows                OUT NOCOPY    NUMBER
3587   ) IS
3588     invalid_pkg_state  exception;
3589     Pragma Exception_Init(invalid_pkg_state, -6508);
3590 
3591     l_list_pkg     VARCHAR2(30);
3592 
3593     l_api_name     VARCHAR2(30)  := 'FetchCursor';
3594     l_rows         NUMBER;
3595     l_func_sql     VARCHAR(1000);
3596     l_cursor       NUMBER;
3597     l_dummy        NUMBER;
3598     l_package_name VARCHAR2(128);
3599     l_ctr          NUMBER        := 0;
3600 
3601     l_debug        NUMBER;
3602 
3603   BEGIN
3604     -- Initialize API return status to success
3605     x_return_status  := fnd_api.g_ret_sts_success;
3606     --get package name based on rule id
3607     getpackagename(p_rule_id, l_package_name);
3608     --- calling the static fetch cursor. The name of the rule package will be
3609     --- determined based on the rule_id
3610     --- If the ctr is 1 then there is no subscript ,
3611     --- if ctr = 2 then subscript = 1
3612     --- and if ctr = 3 then subscript = 2, this script is added to the package
3613     --- name.
3614 
3615 
3616     l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
3617     l_list_pkg   :=  'wms_rule_pick_pkg' || l_ctr ;
3618 
3619     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3620       g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3621     END IF;
3622     l_debug := g_debug;
3623 
3624     IF l_debug = 1  THEN
3625        log_procedure(l_api_name, 'start', 'Start FetchCursor');
3626     END IF;
3627 
3628     IF (l_ctr = 1) THEN
3629 
3630       wms_rule_pick_pkg1.execute_fetch_rule(
3631         p_cursor
3632       , p_rule_id
3633       , x_revision
3634       , x_lot_number
3635       , x_lot_expiration_date
3636       , x_subinventory_code
3637       , x_locator_id
3638       , x_cost_group_id
3639       , x_uom_code
3640       , x_lpn_id
3641       , x_serial_number
3642       , x_possible_quantity
3643       , x_sec_possible_quantity
3644       , x_grade_code
3645       , x_consist_string
3646       , x_order_by_string
3647       , x_rows
3648       );
3649     ELSIF (l_ctr = 2) THEN
3650 
3651       wms_rule_pick_pkg2.execute_fetch_rule(
3652         p_cursor
3653       , p_rule_id
3654       , x_revision
3655       , x_lot_number
3656       , x_lot_expiration_date
3657       , x_subinventory_code
3658       , x_locator_id
3659       , x_cost_group_id
3660       , x_uom_code
3661       , x_lpn_id
3662       , x_serial_number
3663       , x_possible_quantity
3664       , x_sec_possible_quantity
3665       , x_grade_code
3666       , x_consist_string
3667       , x_order_by_string
3668       , x_rows
3669       );
3670     ELSIF (l_ctr = 3) THEN
3671       wms_rule_pick_pkg3.execute_fetch_rule(
3672         p_cursor
3673       , p_rule_id
3674       , x_revision
3675       , x_lot_number
3676       , x_lot_expiration_date
3677       , x_subinventory_code
3678       , x_locator_id
3679       , x_cost_group_id
3680       , x_uom_code
3681       , x_lpn_id
3682       , x_serial_number
3683       , x_possible_quantity
3684       , x_sec_possible_quantity
3685       , x_grade_code
3686       , x_consist_string
3687       , x_order_by_string
3688       , x_rows
3689       );
3690     END IF;
3691 
3692     l_rows           := x_rows;
3693 
3694     IF l_rows = 0 THEN --no row found
3695       x_revision             := NULL;
3696       x_lot_number           := NULL;
3697       x_lot_expiration_date  := NULL;
3698       x_subinventory_code    := NULL;
3699       x_locator_id           := NULL;
3700       x_cost_group_id        := NULL;
3701       x_uom_code             := NULL;
3702       x_lpn_id               := NULL;
3703       x_serial_number        := NULL;
3704       x_possible_quantity    := 0;
3705       x_consist_string       := NULL;
3706       x_order_by_string      := NULL;
3707 
3708 
3709       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PICK_NO_ROWS'  ;
3710 
3711       IF l_debug = 1 THEN
3712          log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || p_rule_id);
3713          log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
3714        END IF;
3715 
3716     END IF;
3717 
3718     x_rows := l_rows;
3719     --
3720 
3721     IF l_debug = 1 THEN
3722          log_procedure(l_api_name, 'end', 'End FetchCursor');
3723     END IF;
3724   --
3725   EXCEPTION
3726     WHEN INVALID_PKG_STATE THEN
3727       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3728 
3729       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3730       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3731       fnd_message.set_token('RULE_NAME', l_package_name);
3732       fnd_msg_pub.ADD;
3733       IF l_debug = 1 THEN
3734          log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
3735                             || l_list_pkg || ' / ' || l_package_name);
3736       END IF;
3737       RAISE fnd_api.g_exc_unexpected_error;
3738 
3739     WHEN OTHERS THEN
3740       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3741 
3742       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3743         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3744       END IF;
3745 
3746       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3747       IF l_debug = 1 THEN
3748          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3749       END IF;
3750       RAISE fnd_api.g_exc_unexpected_error;
3751   END fetchcursor;
3752 
3753   --
3754   -- Name        : FetchPutAway
3755   -- Function    : Fetches one record at a time from the Rule's
3756   --     SQL statement, using the rule API. Called from putaway
3757   -- Pre-reqs    : cursor has to be parsed and executed already.
3758   -- Notes       : private procedure for internal use only
3759   --
3760   PROCEDURE fetchputaway(
3761     x_return_status     OUT NOCOPY    VARCHAR2
3762   , x_msg_count         OUT NOCOPY    NUMBER
3763   , x_msg_data          OUT NOCOPY    VARCHAR2
3764   , p_cursor            IN            wms_rule_pvt.cv_put_type
3765   , p_rule_id           IN            NUMBER
3766   , x_subinventory_code OUT NOCOPY    VARCHAR2
3767   , x_locator_id        OUT NOCOPY    NUMBER
3768   , x_project_id        OUT NOCOPY    NUMBER
3769   , x_task_id           OUT NOCOPY    NUMBER
3770   , x_rows              OUT NOCOPY    NUMBER
3771   ) IS
3772     invalid_pkg_state  exception;
3773     Pragma Exception_Init(invalid_pkg_state, -6508);
3774 
3775     l_list_pkg     VARCHAR2(30);
3776 
3777     l_api_name     VARCHAR2(30)  := 'FetchPutaway';
3778     l_rows         NUMBER;
3779     l_func_sql     VARCHAR(1000);
3780     l_cursor       NUMBER;
3781     l_dummy        NUMBER;
3782     l_package_name VARCHAR2(128);
3783     l_ctr          NUMBER        := 0;
3784 
3785     l_debug        NUMBER;
3786 
3787 
3788   BEGIN
3789     -- Initialize API return status to success
3790     x_return_status  := fnd_api.g_ret_sts_success;
3791 
3792    IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3793       g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3794    END IF;
3795    l_debug := g_debug;
3796 
3797    IF l_debug = 1 THEN
3798       log_procedure(l_api_name, 'start', 'Start FetchPutaway');
3799       log_procedure(l_api_name, 'start', 'Putaway rule id '||p_rule_id);
3800    END IF;
3801 
3802     --get package name based on rule id
3803     getpackagename(p_rule_id, l_package_name);
3804     l_ctr            := wms_rule_pvt.g_rule_list_put_ctr;
3805     l_list_pkg :=  'wms_rule_put_pkg' || l_ctr ;
3806 
3807     IF (l_ctr = 1) THEN
3808       wms_rule_put_pkg1.execute_fetch_rule
3809                     (p_cursor
3810                     , p_rule_id
3811                     , x_subinventory_code
3812                     , x_locator_id
3813                     , x_project_id
3814                     , x_task_id
3815                     , x_rows);
3816     ELSIF (l_ctr = 2) THEN
3817       wms_rule_put_pkg2.execute_fetch_rule
3818                     (p_cursor
3819                     , p_rule_id
3820                     , x_subinventory_code
3821                     , x_locator_id
3822                     , x_project_id
3823                     , x_task_id
3824                     , x_rows);
3825     ELSIF (l_ctr = 3) THEN
3826       wms_rule_put_pkg3.execute_fetch_rule
3827                     (p_cursor
3828                     , p_rule_id
3829                     , x_subinventory_code
3830                     , x_locator_id
3831                     , x_project_id
3832                     , x_task_id
3833                     , x_rows);
3834     END IF;
3835 
3836     --------
3837     --l_rows           := x_rows;
3838     IF l_debug = 1 THEN
3839        log_event(l_api_name, '*************************', '');
3840        log_event(l_api_name, 'x_subinventory_code', x_subinventory_code);
3841        log_event(l_api_name, 'x_locator_id', x_locator_id);
3842      END IF;
3843 
3844 
3845     IF  l_rows  = 0 THEN --no row found
3846       x_subinventory_code  := NULL;
3847       x_locator_id         := NULL;
3848       x_project_id         := NULL;
3849       x_task_id            := NULL;
3850 
3851       -- Bug # 3185073
3852       --WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
3853 
3854       IF l_debug = 1 THEN
3855          log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || p_rule_id);
3856       END IF;
3857 
3858       IF ( WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE = 'WMS_PICK_NO_ROWS' or
3859            WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE = NULL) then
3860 
3861            WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
3862       END IF;
3863 
3864        IF l_debug = 1 THEN
3865           log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
3866        END IF;
3867 
3868     END IF;
3869     --x_rows           := l_rows;
3870           IF l_debug = 1 THEN
3871              log_statement(l_api_name, 'put_sub',
3872                 'Subinventory: ' || x_subinventory_code);
3873              log_statement(l_api_name, 'put_loc',
3874                 'Locator: ' || x_locator_id);
3875              log_statement(l_api_name, 'put_proj',
3876                 'Project: ' || x_project_id);
3877              log_statement(l_api_name, 'put_task',
3878                 'Task: ' || x_task_id);
3879              log_statement(l_api_name, 'rows',
3880                 'Rows Returned: ' || x_rows);
3881           END IF;
3882 
3883     IF l_debug = 1 THEN
3884        log_procedure(l_api_name, 'end', 'End FetchPutaway');
3885     END IF;
3886   --
3887   EXCEPTION
3888     WHEN INVALID_PKG_STATE THEN
3889       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3890       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3891       fnd_message.set_token('LIST_PKG',  l_list_pkg);
3892       fnd_message.set_token('RULE_NAME', l_package_name);
3893       fnd_msg_pub.ADD;
3894 
3895       IF l_debug = 1 THEN
3896          log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
3897                             || l_list_pkg || ' / ' || l_package_name);
3898       END IF;
3899       RAISE fnd_api.g_exc_unexpected_error;
3900     WHEN OTHERS THEN
3901       x_return_status  := fnd_api.g_ret_sts_unexp_error;
3902 
3903       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3904         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3905       END IF;
3906 
3907       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3908       IF l_debug = 1 THEN
3909          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3910       END IF;
3911       RAISE fnd_api.g_exc_unexpected_error;
3912   END fetchputaway;
3913 
3914   ------------
3915   ---
3916   ---  Procedures to handle the static calls to open, fetch and close cursor
3917   ---  based on the Rule_id. The name of the API_call is decided based on the the
3918   ---  flag retrived from the table.
3919   ---
3920   --- For Pick rules
3921 
3922   PROCEDURE pick_open_rule(
3923     p_cursor                 IN OUT NOCOPY wms_rule_pvt.cv_pick_type
3924   , p_rule_id                IN            NUMBER
3925   , p_organization_id        IN            NUMBER
3926   , p_inventory_item_id      IN            NUMBER
3927   , p_transaction_type_id    IN            NUMBER
3928   , p_revision               IN            VARCHAR2
3929   , p_lot_number             IN            VARCHAR2
3930   , p_subinventory_code      IN            VARCHAR2
3931   , p_locator_id             IN            NUMBER
3932   , p_cost_group_id          IN            NUMBER
3933   , p_pp_transaction_temp_id IN            NUMBER
3934   , p_serial_controlled      IN            NUMBER
3935   , p_detail_serial          IN            NUMBER
3936   , p_detail_any_serial      IN            NUMBER
3937   , p_from_serial_number     IN            VARCHAR2
3938   , p_to_serial_number       IN            VARCHAR2
3939   , p_unit_number            IN            VARCHAR2
3940   , p_lpn_id                 IN            NUMBER
3941   , p_project_id             IN            NUMBER
3942   , p_task_id                IN            NUMBER
3943   , x_result                 OUT NOCOPY    NUMBER
3944   ) IS
3945 
3946     invalid_pkg_state  exception;
3947     Pragma Exception_Init(invalid_pkg_state, -6508);
3948     l_msg_data      VARCHAR2(240);
3949     l_msg_count     NUMBER;
3950     l_api_name      VARCHAR2(30);
3951 
3952     l_list_pkg     VARCHAR2(30);
3953     l_package_name VARCHAR2(128);
3954     l_ctr NUMBER := 0;
3955 
3956     l_debug        NUMBER;
3957 
3958   BEGIN
3959 
3960     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3961        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3962     END IF;
3963     l_debug := g_debug;
3964 
3965     IF wms_rule_pvt.g_rule_list_pick_ctr IS NULL THEN
3966        wms_rule_pvt.g_rule_list_pick_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('PICK');
3967     END IF;
3968     l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
3969 
3970     l_list_pkg :=  'wms_rule_pick_pkg' || l_ctr ;
3971     getpackagename(p_rule_id, l_package_name);
3972 
3973     IF (l_ctr = 1) THEN
3974 
3975          IF l_debug = 1 THEN
3976             log_statement(l_api_name, ' wms_rule_pick_pkg1.execute_open_rule', l_ctr);
3977          END IF;
3978       wms_rule_pick_pkg1.execute_open_rule(
3979         p_cursor
3980       , p_rule_id
3981       , p_organization_id
3982       , p_inventory_item_id
3983       , p_transaction_type_id
3984       , p_revision
3985       , p_lot_number
3986       , p_subinventory_code
3987       , p_locator_id
3988       , p_cost_group_id
3989       , p_pp_transaction_temp_id
3990       , p_serial_controlled
3991       , p_detail_serial
3992       , p_detail_any_serial
3993       , p_from_serial_number
3994       , p_to_serial_number
3995       , p_unit_number
3996       , p_lpn_id
3997       , p_project_id
3998       , p_task_id
3999       , x_result
4000       );
4001     ELSIF (l_ctr = 2) THEN
4002 
4003         IF l_debug = 1 THEN
4004            log_statement(l_api_name, ' wms_rule_pick_pkg2.execute_open_rule', l_ctr);
4005         END IF;
4006 
4007       wms_rule_pick_pkg2.execute_open_rule(
4008         p_cursor
4009       , p_rule_id
4010       , p_organization_id
4011       , p_inventory_item_id
4012       , p_transaction_type_id
4013       , p_revision
4014       , p_lot_number
4015       , p_subinventory_code
4016       , p_locator_id
4017       , p_cost_group_id
4018       , p_pp_transaction_temp_id
4019       , p_serial_controlled
4020       , p_detail_serial
4021       , p_detail_any_serial
4022       , p_from_serial_number
4023       , p_to_serial_number
4024       , p_unit_number
4025       , p_lpn_id
4026       , p_project_id
4027       , p_task_id
4028       , x_result
4029       );
4030     ELSIF (l_ctr = 3) THEN
4031        IF l_debug = 1 THEN
4032           log_statement(l_api_name, ' wms_rule_pick_pkg3.execute_open_rule', l_ctr);
4033        END IF;
4034 
4035       wms_rule_pick_pkg3.execute_open_rule(
4036         p_cursor
4037       , p_rule_id
4038       , p_organization_id
4039       , p_inventory_item_id
4040       , p_transaction_type_id
4041       , p_revision
4042       , p_lot_number
4043       , p_subinventory_code
4044       , p_locator_id
4045       , p_cost_group_id
4046       , p_pp_transaction_temp_id
4047       , p_serial_controlled
4048       , p_detail_serial
4049       , p_detail_any_serial
4050       , p_from_serial_number
4051       , p_to_serial_number
4052       , p_unit_number
4053       , p_lpn_id
4054       , p_project_id
4055       , p_task_id
4056       , x_result
4057       );
4058     END IF;
4059 
4060   EXCEPTION
4061     WHEN INVALID_PKG_STATE THEN
4062       x_result := 0;
4063       wms_rule_pvt.g_rule_list_pick_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('PICK');
4064 
4065       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4066       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4067       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4068       fnd_message.set_token('RULE_NAME', l_package_name);
4069       fnd_msg_pub.ADD;
4070 
4071       IF l_debug = 1 THEN
4072          log_error(l_api_name, 'execute_open_rule', 'Invalid Package, Contact your DBA - '
4073                             || l_list_pkg || ' / ' || l_package_name);
4074 
4075       END IF;
4076   END pick_open_rule;
4077 
4078   ---
4079   ---  Procedure Fetchcursor() is modified to handle static call to fetch a row from the
4080   ---  opened picking cursor
4081 
4082   ----------------
4083 
4084   PROCEDURE put_open_rule(
4085     p_cursor                 IN OUT NOCOPY wms_rule_pvt.cv_put_type
4086   , p_rule_id                IN            NUMBER
4087   , p_organization_id        IN            NUMBER
4088   , p_inventory_item_id      IN            NUMBER
4089   , p_transaction_type_id    IN            NUMBER
4090   , p_subinventory_code      IN            VARCHAR2
4091   , p_locator_id             IN            NUMBER
4092   , p_pp_transaction_temp_id IN            NUMBER
4093   , p_restrict_subs_code     IN            NUMBER
4094   , p_restrict_locs_code     IN            NUMBER
4095   , p_project_id             IN            NUMBER
4096   , p_task_id                IN            NUMBER
4097   , x_result                 OUT NOCOPY    NUMBER
4098   ) IS
4099 
4100     invalid_pkg_state  exception;
4101     Pragma Exception_Init(invalid_pkg_state, -6508);
4102     l_msg_data      VARCHAR2(240);
4103     l_msg_count     NUMBER;
4104     l_api_name      VARCHAR2(30);
4105 
4106     l_list_pkg     VARCHAR2(30);
4107     l_package_name VARCHAR2(128);
4108     l_ctr NUMBER := 0;
4109 
4110     l_debug       NUMBER;
4111 
4112   BEGIN
4113 
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 wms_rule_pvt.g_rule_list_put_ctr is null then
4120        wms_rule_pvt.g_rule_list_put_ctr  :=  wms_rule_gen_pkgs.get_count_no_lock('PUTAWAY');
4121     end if;
4122     l_ctr := wms_rule_pvt.g_rule_list_put_ctr;
4123 
4124     l_list_pkg :=  'wms_rule_put_pkg' || l_ctr ;
4125     getpackagename(p_rule_id, l_package_name);
4126 
4127     IF (l_ctr = 1) THEN
4128       wms_rule_put_pkg1.execute_open_rule(
4129         p_cursor
4130       , p_rule_id
4131       , p_organization_id
4132       , p_inventory_item_id
4133       , p_transaction_type_id
4134       , p_subinventory_code
4135       , p_locator_id
4136       , p_pp_transaction_temp_id
4137       , p_restrict_subs_code
4138       , p_restrict_locs_code
4139       , p_project_id
4140       , p_task_id
4141       , x_result
4142       );
4143     ELSIF (l_ctr = 2) THEN
4144       wms_rule_put_pkg2.execute_open_rule(
4145         p_cursor
4146       , p_rule_id
4147       , p_organization_id
4148       , p_inventory_item_id
4149       , p_transaction_type_id
4150       , p_subinventory_code
4151       , p_locator_id
4152       , p_pp_transaction_temp_id
4153       , p_restrict_subs_code
4154       , p_restrict_locs_code
4155       , p_project_id
4156       , p_task_id
4157       , x_result
4158       );
4159     ELSIF (l_ctr = 3) THEN
4160       wms_rule_put_pkg3.execute_open_rule(
4161         p_cursor
4162       , p_rule_id
4163       , p_organization_id
4164       , p_inventory_item_id
4165       , p_transaction_type_id
4166       , p_subinventory_code
4167       , p_locator_id
4168       , p_pp_transaction_temp_id
4169       , p_restrict_subs_code
4170       , p_restrict_locs_code
4171       , p_project_id
4172       , p_task_id
4173       , x_result
4174       );
4175     END IF;
4176 
4177   EXCEPTION
4178     WHEN INVALID_PKG_STATE THEN
4179       x_result := 0;
4180       wms_rule_pvt.g_rule_list_put_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('PUTAWAY');
4181 
4182       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4183       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4184       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4185       fnd_message.set_token('RULE_NAME', l_package_name);
4186       fnd_msg_pub.ADD;
4187 
4188       IF l_debug = 1 THEN
4189          log_error(l_api_name, 'execute_open_rule', 'Invalid Package, Contact your DBA - '
4190                             || l_list_pkg || ' / ' || l_package_name);
4191       END IF;
4192   END put_open_rule;
4193 
4194   -----------------
4195   ---  Procedure FetchPutaway() is modified to handle static call to fetch a row from the
4196   ---  opened Putaway cursor
4197 
4198   PROCEDURE execute_op_rule(p_rule_id IN NUMBER, p_task_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
4199 
4200     invalid_pkg_state  exception;
4201     Pragma Exception_Init(invalid_pkg_state, -6508);
4202     l_msg_data      VARCHAR2(240);
4203     l_msg_count     NUMBER;
4204     l_api_name      VARCHAR2(30);
4205     l_list_pkg      VARCHAR2(30);
4206     l_package_name  VARCHAR2(128);
4207     l_ctr             NUMBER := 0;
4208 
4209   BEGIN
4210     if wms_rule_pvt.g_rule_list_op_ctr is null then
4211        wms_rule_pvt.g_rule_list_op_ctr :=  wms_rule_gen_pkgs.get_count_no_lock('OPERATION_PLAN');
4212     end if;
4213     l_ctr := wms_rule_pvt.g_rule_list_op_ctr;
4214 
4215     l_list_pkg :=  'wms_rule_op_pkg' || l_ctr ;
4216     getpackagename(p_rule_id, l_package_name);
4217 
4218     IF (l_ctr = 1) THEN
4219       wms_rule_op_pkg1.execute_op_rule(p_rule_id, p_task_id, x_return_status);
4220     ELSIF (l_ctr = 2) THEN
4221       wms_rule_op_pkg2.execute_op_rule(p_rule_id, p_task_id, x_return_status);
4222     ELSIF (l_ctr = 3) THEN
4223       wms_rule_op_pkg3.execute_op_rule(p_rule_id, p_task_id, x_return_status);
4224     END IF;
4225     IF x_return_status  IS NULL THEN
4226            x_return_status := 1;
4227     END IF;
4228   EXCEPTION
4229     WHEN INVALID_PKG_STATE THEN
4230        --x_return_status := 0;
4231        x_return_status := -1 ;
4232       wms_rule_pvt.g_rule_list_op_ctr :=   wms_rule_gen_pkgs.get_count_no_lock('OPERATION_PLAN');
4233       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4234       x_return_status  := fnd_api.g_ret_sts_unexp_error;
4235       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4236       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4237       fnd_message.set_token('RULE_NAME', l_package_name);
4238       fnd_msg_pub.ADD;
4239       /*log_error(l_api_name, 'execute_op_rule', 'Invalid Package, Contact your DBA - '
4240                             || l_list_pkg || ' / ' || l_package_name); */
4241   END execute_op_rule;
4242 
4243   ----- Open cursor and fetch cursor for task rules
4244 
4245   PROCEDURE execute_task_rule(p_rule_id IN NUMBER, p_task_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
4246 
4247     invalid_pkg_state  exception;
4248     Pragma Exception_Init(invalid_pkg_state, -6508);
4249     l_msg_data      VARCHAR2(240);
4250     l_msg_count     NUMBER;
4251     l_api_name      VARCHAR2(30);
4252 
4253     l_list_pkg     VARCHAR2(30);
4254     l_package_name VARCHAR2(128);
4255 
4256     l_ctr NUMBER := 0;
4257 
4258 
4259   BEGIN
4260      if wms_rule_pvt.g_rule_list_task_ctr is null then
4261         wms_rule_pvt.g_rule_list_task_ctr :=   wms_rule_gen_pkgs.get_count_no_lock('TASK');
4262      end if;
4263      l_ctr := wms_rule_pvt.g_rule_list_task_ctr;
4264 
4265     l_list_pkg :=  'wms_rule_task_pkg' || l_ctr ;
4266     getpackagename(p_rule_id, l_package_name);
4267 
4268     IF (l_ctr = 1) THEN
4269       wms_rule_task_pkg1.execute_task_rule(p_rule_id, p_task_id, x_return_status);
4270     ELSIF (l_ctr = 2) THEN
4271       wms_rule_task_pkg2.execute_task_rule(p_rule_id, p_task_id, x_return_status);
4272     ELSIF (l_ctr = 3) THEN
4273       wms_rule_task_pkg3.execute_task_rule(p_rule_id, p_task_id, x_return_status);
4274     END IF;
4275     IF x_return_status  IS NULL THEN
4276        x_return_status := 1;
4277     END IF;
4278   EXCEPTION
4279     WHEN INVALID_PKG_STATE THEN
4280       --x_return_status := 0;
4281       x_return_status := -1 ;
4282       wms_rule_pvt.g_rule_list_task_ctr :=   wms_rule_gen_pkgs.get_count_no_lock('TASK');
4283       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4284       x_return_status  := fnd_api.g_ret_sts_unexp_error;
4285       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4286       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4287       fnd_message.set_token('RULE_NAME', l_package_name);
4288       fnd_msg_pub.ADD;
4289       /*log_error(l_api_name, 'execute_task_rule', 'Invalid Package, Contact your DBA - '
4290                             || l_list_pkg || ' / ' || l_package_name); */
4291 
4292   END execute_task_rule;
4293 
4294   ---
4295 
4296   ----- Open cursor and fetch cursor for task rules
4297 
4298   PROCEDURE execute_label_rule(p_rule_id IN NUMBER, p_label_request_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
4299 
4300     invalid_pkg_state  exception;
4301     Pragma Exception_Init(invalid_pkg_state, -6508);
4302     l_msg_data      VARCHAR2(240);
4303     l_msg_count     NUMBER;
4304     l_api_name      VARCHAR2(30);
4305 
4306     l_list_pkg     VARCHAR2(30);
4307     l_package_name VARCHAR2(128);
4308     l_ctr NUMBER := 0;
4309 
4310   BEGIN
4311 
4312     if wms_rule_pvt.g_rule_list_label_ctr is null then
4313        wms_rule_pvt.g_rule_list_label_ctr := wms_rule_gen_pkgs.get_count_no_lock('LABEL');
4314     end if;
4315     l_ctr := wms_rule_pvt.g_rule_list_label_ctr;
4316 
4317     l_list_pkg :=  'wms_rule_label_pkg' || l_ctr ;
4318     getpackagename(p_rule_id, l_package_name);
4319 
4320     IF (l_ctr = 1) THEN
4321       wms_rule_label_pkg1.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
4322     ELSIF (l_ctr = 2) THEN
4323       wms_rule_label_pkg2.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
4324     ELSIF (l_ctr = 3) THEN
4325       wms_rule_label_pkg3.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
4326     END IF;
4327 
4328     IF x_return_status  IS NULL THEN
4329            x_return_status := 1;
4330     END IF;
4331   EXCEPTION
4332     WHEN INVALID_PKG_STATE THEN
4333       --x_return_status := 0;
4334       x_return_status := -1 ;
4335       wms_rule_pvt.g_rule_list_label_ctr := wms_rule_gen_pkgs.get_count_no_lock('LABEL');
4336       WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4337       x_return_status  := fnd_api.g_ret_sts_unexp_error;
4338       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4339       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4340       fnd_message.set_token('RULE_NAME', l_package_name);
4341       fnd_msg_pub.ADD;
4342       /*log_error(l_api_name, 'execute_label_rule', 'Invalid Package, Contact your DBA - '
4343                             || l_list_pkg || ' / ' || l_package_name); */
4344 
4345   END execute_label_rule;
4346 
4347   ---  Procedure to Close Pick rule Cursor --
4348   ---
4349 
4350   PROCEDURE close_pick_rule(p_rule_id IN NUMBER, p_cursor IN OUT NOCOPY wms_rule_pvt.cv_pick_type) IS
4351 
4352     invalid_pkg_state  exception;
4353     Pragma Exception_Init(invalid_pkg_state, -6508);
4354     l_msg_data      VARCHAR2(240);
4355     l_msg_count     NUMBER;
4356     l_api_name      VARCHAR2(30);
4357 
4358     l_list_pkg     VARCHAR2(30);
4359     l_package_name VARCHAR2(128);
4360 
4361     l_ctr NUMBER := 0;
4362 
4363   BEGIN
4364 
4365     l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
4366     l_list_pkg :=  'wms_rule_pick_pkg' || l_ctr ;
4367     getpackagename(p_rule_id, l_package_name);
4368 
4369     IF (l_ctr = 1) THEN
4370       wms_rule_pick_pkg1.execute_close_rule(p_rule_id, p_cursor);
4371     ELSIF (l_ctr = 2) THEN
4372       wms_rule_pick_pkg2.execute_close_rule(p_rule_id, p_cursor);
4373     ELSIF (l_ctr = 3) THEN
4374       wms_rule_pick_pkg3.execute_close_rule(p_rule_id, p_cursor);
4375     END IF;
4376 
4377   EXCEPTION
4378     WHEN INVALID_PKG_STATE THEN
4379     /* -- WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4380       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4381       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4382       fnd_message.set_token('RULE_NAME', l_package_name);
4383       fnd_msg_pub.ADD;
4384       log_error(l_api_name, 'execute_close_rule', 'Invalid Package, Contact your DBA - '
4385                             || l_list_pkg || ' / ' || l_package_name); */
4386        RAISE fnd_api.g_exc_unexpected_error;
4387   END close_pick_rule;
4388 
4389   -- Procedure to close Putaway rule Cursor ---
4390   --
4391   PROCEDURE close_put_rule(p_rule_id IN NUMBER, p_cursor IN OUT NOCOPY wms_rule_pvt.cv_put_type) IS
4392 
4393     invalid_pkg_state  exception;
4394     Pragma Exception_Init(invalid_pkg_state, -6508);
4395     l_msg_data      VARCHAR2(240);
4396     l_msg_count     NUMBER;
4397     l_api_name      VARCHAR2(30);
4398     l_list_pkg     VARCHAR2(30);
4399     l_package_name VARCHAR2(128);
4400     l_ctr NUMBER := 0;
4401   BEGIN
4402     l_ctr := wms_rule_pvt.g_rule_list_put_ctr;
4403     l_list_pkg :=  'wms_rule_put_pkg' || l_ctr ;
4404     getpackagename(p_rule_id, l_package_name);
4405 
4406     IF (l_ctr = 1) THEN
4407       wms_rule_put_pkg1.execute_close_rule(p_rule_id, p_cursor);
4408     ELSIF (l_ctr = 2) THEN
4409       wms_rule_put_pkg2.execute_close_rule(p_rule_id, p_cursor);
4410     ELSIF (l_ctr = 3) THEN
4411       wms_rule_put_pkg3.execute_close_rule(p_rule_id, p_cursor);
4412     END IF;
4413 
4414   EXCEPTION
4415     WHEN INVALID_PKG_STATE THEN
4416      /*WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4417       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4418       fnd_message.set_token('LIST_PKG',  l_list_pkg);
4419       fnd_message.set_token('RULE_NAME', l_package_name);
4420       fnd_msg_pub.ADD;
4421       log_error(l_api_name, 'execute_close_rule', 'Invalid Package, Contact your DBA - '
4422                             || l_list_pkg || ' / ' || l_package_name);*/
4423       RAISE fnd_api.g_exc_unexpected_error;
4424   END close_put_rule;
4425 
4426   --------------
4427   --
4428   -- Name        : Rollback_Capacity_Update
4429   -- Function    : Used in Apply for Put Away rules.
4430   --     In Apply, the update_loc_suggested_capacity procedure gets
4431   --     called to update the capacity for a locator.  This
4432   --     procedure is an autonomous transaction, so it issues
4433   --     a commit.  If some sort of error occurs in Apply, we need to
4434   --     undo those changes.  We call revert_loc_suggested_capacity
4435   --     to decrement the suggested capacity field.  The procedure
4436   --     is also a autonomous transaction
4437   -- Pre-reqs    : cursor has to be parsed and executed already.
4438   -- Notes       : private procedure for internal use only
4439   --
4440   PROCEDURE rollback_capacity_update(
4441     x_return_status     OUT NOCOPY    VARCHAR2
4442   , x_msg_count         OUT NOCOPY    NUMBER
4443   , x_msg_data          OUT NOCOPY    VARCHAR2
4444   , p_organization_id   IN            NUMBER
4445   , p_inventory_item_id IN            NUMBER
4446   ) IS
4447     l_return_status VARCHAR2(1);
4448     l_msg_data      VARCHAR2(240);
4449     l_msg_count     NUMBER;
4450     l_no_error      BOOLEAN;
4451     l_api_name      VARCHAR2(30)  := 'rollback_capacity_update';
4452 
4453     l_debug         NUMBER;
4454 
4455     -- gets all of the put away suggestions already created;
4456     -- The locator capacity would have been updated for each of these
4457     -- records
4458     -- type_code 1 = put away; line_type_code 2 = output
4459     CURSOR l_output_lines IS
4460       SELECT   to_locator_id
4461              , SUM(primary_quantity) quantity
4462           FROM wms_transactions_temp
4463          WHERE type_code = 1
4464            AND line_type_code = 2
4465       GROUP BY to_locator_id;
4466   BEGIN
4467     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
4468         g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
4469     END IF;
4470     l_debug := g_debug;
4471 
4472     If l_debug  = 1 THEN
4473        log_procedure(l_api_name, 'start', 'Start rollback_capacity_update');
4474     END IF;
4475 
4476     l_return_status  := fnd_api.g_ret_sts_success;
4477     l_no_error       := TRUE;
4478 
4479     FOR l_line IN l_output_lines LOOP
4480       -- We don't track capacity at Subinventory level, so no need
4481       -- to update if locator_id is null
4482       IF l_line.to_locator_id IS NOT NULL THEN
4483 
4484         IF l_debug = 1 THEN
4485            log_statement(l_api_name, 'calling_revert', 'Calling inv_loc_wms_utils.revert_loc_suggested_capacity');
4486            log_statement(l_api_name, 'revert_org', 'Org: ' || p_organization_id);
4487            log_statement(l_api_name, 'revert_item', 'Item: ' || p_inventory_item_id);
4488            log_statement(l_api_name, 'revert_loc', 'Loc: ' || l_line.to_locator_id);
4489            log_statement(l_api_name, 'revert_qty', 'Qty: ' || l_line.quantity);
4490         END IF;
4491         inv_loc_wms_utils.revert_loc_suggested_capacity(
4492           x_return_status              => l_return_status
4493         , x_msg_count                  => l_msg_count
4494         , x_msg_data                   => l_msg_data
4495         , p_organization_id            => p_organization_id
4496         , p_inventory_location_id      => l_line.to_locator_id
4497         , p_inventory_item_id          => p_inventory_item_id
4498         , p_primary_uom_flag           => 'Y'
4499         , p_transaction_uom_code       => NULL
4500         , p_quantity                   => l_line.quantity
4501         );
4502 
4503         --return only the first error message
4504         IF  l_no_error
4505             AND l_return_status <> fnd_api.g_ret_sts_success THEN
4506           x_return_status  := l_return_status;
4507           x_msg_count      := l_msg_count;
4508           x_msg_data       := l_msg_data;
4509           l_no_error       := FALSE;
4510 
4511           IF l_debug = 1 THEN
4512              log_statement(l_api_name, 'first_error', 'Error in inv_loc_wms_utils.revert_loc_suggested_capacity');
4513           END IF;
4514        END IF;
4515      END IF;
4516     END LOOP;
4517     IF l_debug = 1 THEN
4518        log_procedure(l_api_name, 'end', 'End rollback_capacity_update');
4519     END IF;
4520 
4521    EXCEPTION
4522     WHEN OTHERS THEN
4523       x_return_status  := fnd_api.g_ret_sts_unexp_error;
4524 
4525       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
4526         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
4527       END IF;
4528 
4529       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4530 
4531       IF l_debug = 1 THEN
4532          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
4533       END IF;
4534    END rollback_capacity_update;
4535 
4536   -- Bug# 4099907 -- Modifying the fix done in the Bug 3609380
4537   -- Pass the value for transfer_to_sub incase of Subinventory transfer
4538   -- allocations (i.e. with transaction action as 2)
4539   -- Private function
4540   FUNCTION chk_for_passing_xfer_sub
4541                (   p_transaction_temp_id   IN  NUMBER
4542                  , p_to_subinventory_code  IN  VARCHAR2
4543                )
4544   RETURN VARCHAR2
4545   IS
4546    l_to_subinventory_code     MTL_SECONDARY_INVENTORIES.SECONDARY_INVENTORY_NAME%TYPE := NULL ;
4547    l_transaction_action_id    NUMBER := 0 ;
4548    l_debug                    NUMBER := g_debug ;
4549    l_api_name                 VARCHAR2(30) := 'chk_for_passing_xfer_sub';
4550    l_transaction_type_id      NUMBER := 0 ;
4551 
4552   BEGIN
4553 
4554     IF inv_cache.set_mol_rec(p_transaction_temp_id) THEN
4555      l_transaction_type_id  := inv_cache.mol_rec.transaction_type_id;
4556     END IF;
4557 
4558     IF l_transaction_type_id <> 0 THEN
4559      IF inv_cache.set_mtt_rec(l_transaction_type_id) THEN
4560        l_transaction_action_id := inv_cache.mtt_rec.transaction_action_id;
4561      END IF;
4562     END IF;
4563 
4564     IF l_transaction_action_id = 2 THEN
4565       l_to_subinventory_code := p_to_subinventory_code;
4566     END IF;
4567 
4568     IF l_debug = 1  THEN
4569       log_statement(l_api_name, 'l_transaction_action_id', 'l_transaction_action_id : ' || l_transaction_action_id );
4570       log_statement(l_api_name, 'l_to_subinventory_code', 'l_to_subinventory_code: ' || l_to_subinventory_code);
4571     END IF;
4572 
4573     RETURN l_to_subinventory_code ;
4574 
4575   END chk_for_passing_xfer_sub ;
4576   -- End of function definition for fixing Bug 4099907
4577 
4578   PROCEDURE validate_and_insert(
4579     x_return_status          OUT NOCOPY    VARCHAR2
4580   , x_msg_count              OUT NOCOPY    NUMBER
4581   , x_msg_data               OUT NOCOPY    VARCHAR2
4582   , p_record_id              IN            NUMBER
4583   , p_needed_quantity        IN            NUMBER
4584   , p_use_pick_uom           IN            BOOLEAN
4585   , p_organization_id        IN            NUMBER
4586   , p_inventory_item_id      IN            NUMBER
4587   , p_to_subinventory_code   IN            VARCHAR2
4588   , p_to_locator_id          IN            NUMBER
4589   , p_to_cost_group_id       IN            NUMBER
4590   , p_primary_uom            IN            VARCHAR2
4591   , p_transaction_uom        IN            VARCHAR2
4592   , p_transaction_temp_id    IN            NUMBER
4593   , p_type_code              IN            NUMBER
4594   , p_rule_id                IN            NUMBER
4595   , p_reservation_id         IN            NUMBER
4596   , p_tree_id                IN            NUMBER
4597   , p_debug_on               IN            BOOLEAN
4598   , p_needed_sec_quantity    IN            NUMBER
4599   , p_secondary_uom          IN            VARCHAR2
4600   , p_grade_code             IN            VARCHAR2
4601   , p_orig_needed_quantity   IN            NUMBER -- Added for 14699845 (Flexible lot allocation)
4602   , p_orig_needed_sec_qty    IN            NUMBER -- Added for 14699845 (Flexible lot allocation)
4603   , p_simulation_mode        IN            NUMBER -- Added for 14699845 (Flexible lot allocation)
4604   , x_inserted_record        OUT NOCOPY    BOOLEAN
4605   , x_allocated_quantity     OUT NOCOPY    NUMBER
4606   , x_remaining_quantity     OUT NOCOPY    NUMBER
4607   , x_sec_allocated_quantity OUT NOCOPY    NUMBER
4608   , x_sec_remaining_quantity OUT NOCOPY    NUMBER
4609   ) IS
4610     l_api_name                  VARCHAR2(30) := 'validate_and_insert';
4611     l_qoh                       NUMBER;
4612     l_rqoh                      NUMBER;
4613     l_qr                        NUMBER;
4614     l_qs                        NUMBER;
4615     l_att                       NUMBER;
4616     l_atr                       NUMBER;
4617     l_allocation_quantity       NUMBER;
4618     l_needed_quantity           NUMBER;
4619     l_pri_conv_qty              NUMBER := 0;
4620     l_sqoh                      NUMBER;
4621     l_srqoh                     NUMBER;
4622     l_sqr                       NUMBER;
4623     l_sqs                       NUMBER;
4624     l_satt                      NUMBER;
4625     l_satr                      NUMBER;
4626     l_sallocation_quantity      NUMBER;
4627     l_needed_sec_quantity       NUMBER;
4628     l_orig_allocation_quantity  NUMBER;
4629     l_sorig_allocation_quantity NUMBER;
4630     l_found                     BOOLEAN;
4631     l_possible_uom_qty          NUMBER;
4632     l_orig_poss_uom_qty         NUMBER;
4633     l_possible_trx_qty          NUMBER;
4634     l_sec_possible_trx_qty      NUMBER;
4635     l_serial_index              NUMBER;
4636     l_lot_divisible_flag        VARCHAR2(1);
4637     l_lot_control_code          NUMBER;
4638     l_to_locator_id             NUMBER;
4639     l_dual_uom_ctl              NUMBER;
4640     l_rsv_id                    NUMBER;
4641     -- Added for bug 8665496
4642     l_rsv_lot_number            VARCHAR2(80);
4643     l_rsv_qty                   NUMBER;
4644     l_rsv_dtl_qty               NUMBER;
4645     l_rsv_uom                   VARCHAR2(3);
4646     l_sec_rsv_qty               NUMBER;
4647     l_sec_dtl_qty               NUMBER;
4648 
4649     l_debug                     NUMBER;
4650     l_indiv_lot_allowed         VARCHAR2(1);
4651     l_use_pick_uom              BOOLEAN;
4652     l_sec_uom_class             VARCHAR2(10);
4653     l_pick_uom_class            VARCHAR2(10);
4654 
4655     -- bug 9378888 start
4656     l_indivisible_flag          VARCHAR2(1);
4657     l_top_model_line_id         NUMBER;
4658     l_floored_att               NUMBER;
4659     --bug 9378888 end
4660 
4661     l_floored_satt              NUMBER;
4662 
4663     -- Added for Bug 8570601 start
4664     l_to_subinventory_code       VARCHAR2(10);
4665     l_transaction_type_id        NUMBER;
4666     l_transaction_action_id      NUMBER;
4667     l_transaction_source_type_id NUMBER;
4668     -- Added for Bug 8570601 end
4669 
4670     -- Bug 8638386
4671     l_lot_allocation_quantity    NUMBER;
4672     l_lot_sallocation_quantity   NUMBER;
4673     l_pri_res_qty                NUMBER;
4674     l_lot_conv_factor_flag       PLS_INTEGER := 0;
4675     l_are_qties_valid            PLS_INTEGER;
4676 
4677     l_already_allocated_pri_qty  NUMBER;
4678     l_already_allocated_sec_qty  NUMBER;
4679 
4680     l_allocate_lot_flag          VARCHAR2(1) := 'Y';               -- Added for 14699845 (Flexible lot allocation)
4681     l_entire_lpn_alloc           VARCHAR2(1) := 'N';               -- Added for 14699845 (Flexible lot allocation)
4682     l_reserved_lot               VARCHAR2(200) := NULL;            -- Added for 14699845 (Flexible lot allocation)
4683     l_mo_lot                     VARCHAR2(200) := NULL;            -- Added for 14699845 (Flexible lot allocation)
4684     l_transaction_temp_id        NUMBER;                           -- Added for 14699845 (Flexible lot allocation)
4685     l_orig_needed_quantity       NUMBER := p_orig_needed_quantity; -- Added for 14699845 (Flexible lot allocation)
4686     l_orig_needed_sec_qty        NUMBER := p_orig_needed_sec_qty;  -- Added for 14699845 (Flexible lot allocation)
4687 
4688     CURSOR check_if_lot_conv_exists IS
4689       SELECT 1 FROM dual
4690        WHERE EXISTS
4691            ( SELECT 1
4692                FROM mtl_lot_uom_class_conversions
4693               WHERE lot_number        = g_locs(p_record_id).lot_number
4694                 AND inventory_item_id = p_inventory_item_id
4695                 AND organization_id   = p_organization_id
4696                 AND (disable_date IS NULL or disable_date > sysdate)
4697            );
4698 
4699     -- end bug 8638386
4700 
4701     CURSOR c_detailed_reservation IS
4702       SELECT reservation_id
4703       -- Added for bug 8665496
4704            , lot_number
4705            , reservation_quantity
4706            , primary_reservation_quantity
4707            , detailed_quantity
4708            , reservation_uom_code
4709            , secondary_reservation_quantity
4710            , secondary_detailed_quantity
4711         FROM mtl_reservations
4712        WHERE reservation_id = p_reservation_id;
4713       -- and lot_number = g_locs(p_record_id).lot_number; -- Bug 7587155 - the reservation could be
4714                                                           -- high level rather than detail.
4715 
4716     CURSOR c_uom_class(p_uom IN VARCHAR2) IS
4717       SELECT uom_class
4718         FROM mtl_units_of_measure_vl
4719        WHERE uom_code = p_uom;
4720 
4721   BEGIN
4722     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
4723        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
4724     END IF;
4725     l_debug := g_debug;
4726 
4727     x_return_status := fnd_api.g_ret_sts_success;
4728 
4729     IF l_debug = 1 THEN
4730        log_statement(l_api_name, 'validate and insert', 'Entered with parameters: '             ||
4731                                  '  p_record_id: '                || p_record_id                ||
4732                                  ', p_needed_quantity: '          || p_needed_quantity          ||
4733                                  ', p_organization_id: '          || p_organization_id          ||
4734                                  ', p_inventory_item_id: '        || p_inventory_item_id        ||
4735                                  ', p_to_subinventory_code: '     || p_to_subinventory_code     ||
4736                                  ', p_to_locator_id: '            || p_to_locator_id            ||
4737                                  ', p_to_cost_group_id: '         || p_to_cost_group_id         ||
4738                                  ', p_primary_uom: '              || p_primary_uom              ||
4739                                  ', p_transaction_uom: '          || p_transaction_uom          ||
4740                                  ', p_transaction_temp_id: '      || p_transaction_temp_id      ||
4741                                  ', p_type_code: '                || p_type_code                ||
4742                                  ', p_rule_id: '                  || p_rule_id                  ||
4743                                  ', p_reservation_id: '           || p_reservation_id           ||
4744                                  ', p_tree_id: '                  || p_tree_id                  ||
4745                                  ', p_needed_sec_quantity: '      || p_needed_sec_quantity      ||
4746                                  ', p_secondary_uom: '            || p_secondary_uom            ||
4747                                  ', l_orig_needed_quantity: '     || l_orig_needed_quantity     ||
4748                                  ', l_orig_needed_sec_qty: '      || l_orig_needed_sec_qty      ||
4749                                  ', p_grade_code: '               || p_grade_code               ||
4750                                  ', p_simulation_mode: '          || p_simulation_mode
4751 
4752                     );
4753     END IF;
4754 
4755     l_needed_quantity := p_needed_quantity;
4756     l_needed_sec_quantity := p_needed_sec_quantity;
4757     l_use_pick_uom := p_use_pick_uom;
4758 
4759     -- bug 9378888
4760     l_indivisible_flag     := NVL(inv_cache.item_rec.indivisible_flag,'N');
4761 
4762     l_allocate_lot_flag    := get_allocate_lot_flag
4763                                 ( p_organization_id    => p_organization_id
4764                                 , p_move_order_line_id => p_transaction_temp_id
4765                                 , p_inventory_item_id  => p_inventory_item_id
4766                                 , p_subinventory_code  => g_locs(p_record_id).subinventory_code
4767                                 , p_locator_id         => g_locs(p_record_id).locator_id
4768                                 , p_revision           => g_locs(p_record_id).revision
4769                                 , p_lpn_id             => g_locs(p_record_id).lpn_id
4770                                 );  -- Added for 14699845 (Flexible lot allocation)
4771 
4772     -- Start changes for 14699845 (Flexible lot allocation)
4773     IF l_debug = 1 THEN
4774        log_statement(l_api_name, 'validate and insert', 'l_allocate_lot_flag: '|| l_allocate_lot_flag);
4775        log_statement(l_api_name, 'validate and insert', 'l_indivisible_flag: '|| l_indivisible_flag);
4776     END IF;
4777 
4778     --
4779     -- If alternate qty requested is 0 or -ve, recalculate it from fulfillment UOM qty.
4780     --
4781     IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
4782     THEN
4783         IF(l_allocate_lot_flag = 'N') THEN
4784             l_pri_conv_qty := inv_convert.inv_um_convert(
4785                                    item_id          => p_inventory_item_id
4786                                  , precision        => NULL
4787                                  , from_quantity    => p_needed_sec_quantity
4788                                  , from_unit        => p_secondary_uom
4789                                  , to_unit          => p_primary_uom
4790                                  , from_name        => NULL
4791                                  , to_name          => NULL
4792                                  );
4793         ELSE
4794             l_pri_conv_qty := inv_convert.inv_um_convert(
4795                                    item_id          => p_inventory_item_id
4796                                  , lot_number       => g_locs(p_record_id).lot_number
4797                                  , organization_id  => p_organization_id
4798                                  , precision        => NULL
4799                                  , from_quantity    => p_needed_sec_quantity
4800                                  , from_unit        => p_secondary_uom
4801                                  , to_unit          => p_primary_uom
4802                                  , from_name        => NULL
4803                                  , to_name          => NULL
4804                                  );
4805         END IF;
4806 
4807        IF l_needed_quantity <= 0 THEN
4808           l_needed_quantity := l_pri_conv_qty;
4809        ELSE
4810           l_needed_quantity := LEAST(l_needed_quantity,l_pri_conv_qty);
4811        END IF;
4812        IF l_use_pick_uom THEN
4813           OPEN c_uom_class(p_secondary_uom);
4814           FETCH c_uom_class INTO l_sec_uom_class;
4815           CLOSE c_uom_class;
4816 
4817           OPEN c_uom_class(g_locs(p_record_id).uom_code);
4818           FETCH c_uom_class INTO l_pick_uom_class;
4819           CLOSE c_uom_class;
4820 
4821           IF l_sec_uom_class <> l_pick_uom_class THEN
4822              l_use_pick_uom := FALSE;
4823           END IF;
4824        END IF;
4825     ELSIF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_needed_sec_quantity <= 0
4826     THEN
4827        l_needed_sec_quantity := inv_convert.inv_um_convert(
4828                                     item_id          => p_inventory_item_id
4829                                   , lot_number       => g_locs(p_record_id).lot_number
4830                                   , organization_id  => p_organization_id
4831                                   , precision        => NULL
4832                                   , from_quantity    => p_needed_quantity
4833                                   , from_unit        => p_primary_uom
4834                                   , to_unit          => p_secondary_uom
4835                                   , from_name        => NULL
4836                                   , to_name          => NULL
4837                                   );
4838     END IF;
4839 
4840     l_allocation_quantity  := l_needed_quantity;
4841     l_sallocation_quantity := l_needed_sec_quantity;
4842     l_to_locator_id        := p_to_locator_id;
4843 
4844     l_lot_divisible_flag   := inv_cache.item_rec.lot_divisible_flag;
4845     l_lot_control_code     := inv_cache.item_rec.lot_control_code;
4846     l_dual_uom_ctl         := inv_cache.item_rec.dual_uom_control;
4847     l_rsv_id               := 0;
4848 
4849     IF g_locs(p_record_id).lpn_id IS NOT NULL THEN
4850        IF l_debug = 1 THEN
4851           log_statement(l_api_name, 'validate and insert', 'g_locs(p_record_id).lpn_id : '|| g_locs(p_record_id).lpn_id);
4852        END IF;
4853        IF g_lpns.EXISTS(g_locs(p_record_id).lpn_id) THEN
4854           IF l_debug = 1 THEN
4855              log_statement(l_api_name, 'validate and insert', g_locs(p_record_id).lpn_id || ' exists in g_lpns ');
4856              log_statement(l_api_name, 'validate and insert', 'g_lpns(g_locs(p_record_id).lpn_id).quantity: '
4857                                                               || g_lpns(g_locs(p_record_id).lpn_id).quantity);
4858              log_statement(l_api_name, 'validate and insert', 'g_lpns(g_locs(p_record_id).lpn_id).total_quantity: '
4859                                                               || g_lpns(g_locs(p_record_id).lpn_id).total_quantity);
4860              log_statement(l_api_name, 'validate and insert', 'g_lpns(g_locs(p_record_id).lpn_id).secondary_quantity: '
4861                                                               || g_lpns(g_locs(p_record_id).lpn_id).secondary_quantity);
4862              log_statement(l_api_name, 'validate and insert', 'g_lpns(g_locs(p_record_id).lpn_id).secondary_total_quantity: '
4863                                                               || g_lpns(g_locs(p_record_id).lpn_id).secondary_total_quantity);
4864           END IF;
4865 
4866           IF ( ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P')
4867                  AND (g_lpns(g_locs(p_record_id).lpn_id).total_quantity
4868                         = g_lpns(g_locs(p_record_id).lpn_id).quantity) )
4869                OR
4870                ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S')
4871                  AND (g_lpns(g_locs(p_record_id).lpn_id).secondary_total_quantity
4872                         = g_lpns(g_locs(p_record_id).lpn_id).secondary_quantity) ) )
4873           THEN
4874              l_entire_lpn_alloc := 'Y';
4875           END IF;
4876        END IF;
4877     ELSE
4878        IF l_debug = 1 THEN
4879           log_statement(l_api_name, 'validate and insert', 'g_locs(p_record_id).lpn_id IS NULL. ');
4880        END IF;
4881     END IF;
4882 
4883     IF l_debug = 1 THEN
4884        log_statement(l_api_name, 'validate and insert', 'l_entire_lpn_alloc: '|| l_entire_lpn_alloc);
4885     END IF;
4886 
4887     IF (p_reservation_id IS NOT NULL) THEN  -- Added for 14699845 (Flexible lot allocation)
4888        BEGIN
4889           SELECT lot_number
4890             INTO l_reserved_lot
4891             FROM mtl_reservations
4892            WHERE reservation_id = p_reservation_id;
4893        EXCEPTION
4894           WHEN NO_DATA_FOUND THEN
4895                l_reserved_lot := NULL;
4896        END;
4897        IF l_debug = 1 THEN
4898           log_statement(l_api_name, 'validate and insert', ' l_reserved_lot '||l_reserved_lot);
4899        END IF;
4900     END IF;
4901 
4902     IF (p_transaction_temp_id IS NOT NULL) THEN
4903        BEGIN
4904           SELECT lot_number
4905             INTO l_mo_lot
4906             FROM mtl_txn_request_lines
4907            WHERE line_id = p_transaction_temp_id;
4908        EXCEPTION
4909           WHEN NO_DATA_FOUND THEN
4910              l_mo_lot := NULL;
4911        END;
4912        IF l_debug = 1 THEN
4913           log_statement(l_api_name, 'validate and insert', ' l_mo_lot '||l_mo_lot);
4914        END IF;
4915     END IF;
4916 
4917     IF (l_reserved_lot IS NOT NULL OR l_mo_lot IS NOT NULL) THEN
4918        l_allocate_lot_flag := 'Y';
4919        IF l_debug = 1 THEN
4920           log_statement(l_api_name, 'validate and insert', 'Either the RSV or MO has lot, so allocating lot.');
4921        END IF;
4922     END IF;
4923 
4924     IF (l_allocate_lot_flag = 'Y') THEN  -- Added for 14699845 (Flexible lot allocation)
4925        OPEN  check_if_lot_conv_exists;
4926        FETCH check_if_lot_conv_exists INTO l_lot_conv_factor_flag;
4927        CLOSE check_if_lot_conv_exists;
4928     ELSE
4929        l_lot_conv_factor_flag := 0;
4930     END IF;
4931 
4932     -- End changes for 14699845 (Flexible lot allocation)
4933 
4934     IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
4935     THEN --{ secondary based allocation
4936        -- Adjust primary based on lot conversion, reservation, etc.
4937        IF g_alloc_qty.EXISTS(p_reservation_id) THEN
4938           l_rsv_id := p_reservation_id;
4939           l_rsv_lot_number := l_reserved_lot;
4940        ELSE --{
4941           OPEN c_detailed_reservation;
4942           FETCH c_detailed_reservation
4943            INTO l_rsv_id
4944               , l_rsv_lot_number
4945               , l_rsv_qty
4946               , l_pri_res_qty
4947               , l_rsv_dtl_qty
4948               , l_rsv_uom
4949               , l_sec_rsv_qty
4950               , l_sec_dtl_qty;
4951           CLOSE c_detailed_reservation;
4952           IF NVL(l_rsv_id,0) > 0 THEN --{
4953              IF l_debug = 1 THEN
4954                 log_statement(l_api_name,'reservation exists for dual UOM item.','');
4955                 log_statement(l_api_name,'l_rsv_id        ', l_rsv_id);
4956                 log_statement(l_api_name,'l_rsv_lot_number', l_rsv_lot_number);
4957                 log_statement(l_api_name,'l_rsv_qty       ', l_rsv_qty);
4958                 log_statement(l_api_name,'l_pri_res_qty   ', l_pri_res_qty);
4959                 log_statement(l_api_name,'l_rsv_dtl_qty   ', l_rsv_dtl_qty);
4960                 log_statement(l_api_name,'l_rsv_uom       ', l_rsv_uom);
4961                 log_statement(l_api_name,'l_sec_rsv_qty   ', l_sec_rsv_qty);
4962                 log_statement(l_api_name,'l_sec_dtl_qty   ', l_sec_dtl_qty);
4963              END IF;
4964              g_alloc_qty(l_rsv_id)     := l_pri_res_qty - NVL(l_rsv_dtl_qty,0);
4965              g_sec_alloc_qty(l_rsv_id) := l_sec_rsv_qty - NVL(l_sec_dtl_qty,0);
4966           --}
4967           ELSE
4968              l_rsv_id := 0;
4969           END IF;
4970        END IF; --} g_sec_alloc_qty.EXISTS
4971 
4972        -- bug 8638386 - Start - reorganize/extend fix 8665496 - for lot conversion + deviation
4973        IF l_rsv_id > 0 THEN --{
4974           IF l_debug = 1 THEN
4975              log_statement(l_api_name,'l_needed_quantity                 ', l_needed_quantity);
4976              log_statement(l_api_name,'l_needed_sec_quantity             ', l_needed_sec_quantity);
4977              log_statement(l_api_name,'remaining pri [g_alloc_qty(l_rsv_id)]    ', g_alloc_qty(l_rsv_id));
4978              log_statement(l_api_name,'remaining sec [g_sec_alloc_qty(l_rsv_id)]', g_sec_alloc_qty(l_rsv_id));
4979              log_statement(l_api_name,'l_rsv_lot_number                  ', l_rsv_lot_number);
4980           END IF;
4981           --
4982           -- see if the reservation is high level or detailed at lot level.
4983           --
4984           IF (l_rsv_lot_number IS NOT NULL) THEN
4985              --
4986              -- lot level reservation exists
4987              --   may or may not have a lot specific conversion
4988              --     user may or may not have played with the deviation on top.
4989              --
4990              IF g_sec_alloc_qty(l_rsv_id) > l_needed_sec_quantity THEN
4991                 -- distribute sec in the same ratio as secondary
4992                 l_allocation_quantity :=
4993                    LEAST(ROUND((l_needed_sec_quantity/g_sec_alloc_qty(l_rsv_id)) * g_alloc_qty(l_rsv_id),5),
4994                          l_allocation_quantity);
4995              ELSIF g_sec_alloc_qty(l_rsv_id) = l_needed_sec_quantity THEN
4996                 l_allocation_quantity := LEAST(g_alloc_qty(l_rsv_id),l_allocation_quantity);
4997              ELSE
4998                 l_allocation_quantity := l_needed_quantity;
4999              END IF;
5000 
5001              IF l_debug = 1 THEN
5002                 log_statement(l_api_name,'l_allocation_quantity ', l_allocation_quantity);
5003              END IF;
5004           ELSE --{ (l_rsv_lot_number IS NULL)
5005              --
5006              -- No lot level reservation exists (high level/partial)
5007              -- The candidate lot may or may not have a lot specific conversion
5008              -- User may or may not have played with the deviation.
5009              --
5010              IF l_debug = 1 THEN
5011                 log_statement(l_api_name,'g_locs(p_record_id).lot_number ', g_locs(p_record_id).lot_number);
5012              END IF;
5013 
5014              IF l_debug = 1 THEN
5015                 log_statement(l_api_name, 'l_lot_conv_factor_flag ', l_lot_conv_factor_flag);
5016                 log_statement(l_api_name, 'l_lot_control_code     ', l_lot_control_code);
5017              END IF;
5018 
5019              IF (l_lot_control_code = 2 AND l_lot_conv_factor_flag > 0 ) THEN --{
5020                 -- use lot specific conversion
5021                 l_lot_allocation_quantity  := inv_convert.inv_um_convert(
5022                                                   item_id          => p_inventory_item_id
5023                                                 , lot_number       => g_locs(p_record_id).lot_number
5024                                                 , organization_id  => p_organization_id
5025                                                 , precision        => NULL
5026                                                 , from_quantity    => l_sallocation_quantity
5027                                                 , from_unit        => p_secondary_uom
5028                                                 , to_unit          => p_primary_uom
5029                                                 , from_name        => NULL
5030                                                 , to_name          => NULL
5031                                                 );
5032                 IF (l_lot_allocation_quantity = -99999) THEN
5033                    IF l_debug = 1 THEN
5034                       log_statement(l_api_name, 'lot uom conversion error','');
5035                    END IF;
5036                    FND_MESSAGE.SET_NAME('INV','INV_NO_CONVERSION_ERR');
5037                    fnd_msg_pub.ADD;
5038                    RAISE FND_API.G_EXC_ERROR;
5039                 END IF;
5040                 IF l_debug = 1 THEN
5041                    log_statement(l_api_name,'l_allocation_quantity from UOM conversion ', l_allocation_quantity);
5042                                    log_statement(l_api_name,'l_lot_allocation_quantity from UOM conversion ', l_lot_allocation_quantity);
5043                                    log_statement(l_api_name,'g_alloc_qty(l_rsv_id) from UOM conversion ', g_alloc_qty(l_rsv_id));
5044                 END IF;
5045 
5046                 IF (g_alloc_qty(l_rsv_id) <> l_lot_allocation_quantity) THEN
5047                    --
5048                    -- if user played with the deviation on top of the lot specific
5049                    --
5050                    l_are_qties_valid := INV_CONVERT.within_deviation(
5051                                             p_organization_id     => p_organization_id
5052                                           , p_inventory_item_id   => p_inventory_item_id
5053                                           , p_lot_number          => g_locs(p_record_id).lot_number
5054                                           , p_precision           => NULL
5055                                           , p_quantity            => g_alloc_qty(l_rsv_id)
5056                                           , p_uom_code1           => p_primary_uom
5057                                           , p_quantity2           => l_sallocation_quantity
5058                                           , p_uom_code2           => p_secondary_uom
5059                                           , p_unit_of_measure1    => NULL
5060                                           , p_unit_of_measure2    => NULL);
5061 
5062                    IF (l_are_qties_valid = 0) THEN
5063                       -- outside deviation
5064                       l_allocation_quantity := l_lot_allocation_quantity;
5065                    ELSE
5066                       l_allocation_quantity := LEAST(g_alloc_qty(l_rsv_id),l_allocation_quantity);
5067                    END IF;
5068                 END IF;
5069 
5070                 IF l_debug = 1 THEN
5071                    log_statement(l_api_name,'(with lot conv) l_allocation_quantity ', l_allocation_quantity);
5072                 END IF;
5073              --}
5074              ELSE
5075                 --
5076                 -- no lot specific conversion but accomodate user playing with deviation
5077                 IF g_sec_alloc_qty(l_rsv_id) > l_needed_sec_quantity THEN
5078                    -- distribute sec in the same ratio as primary
5079                    l_allocation_quantity :=
5080                       LEAST(ROUND((l_needed_sec_quantity/g_sec_alloc_qty(l_rsv_id)) * g_alloc_qty(l_rsv_id),5),
5081                             l_allocation_quantity);
5082 
5083                    -- Added for 14699845 (Flexible lot allocation)
5084                    IF (l_orig_needed_sec_qty > 0 AND l_orig_needed_sec_qty <> p_needed_sec_quantity) THEN
5085                       l_orig_needed_quantity :=
5086                         LEAST(ROUND((l_orig_needed_sec_qty/g_sec_alloc_qty(l_rsv_id)) * g_alloc_qty(l_rsv_id),5),
5087                               l_orig_needed_quantity);
5088                    END IF;
5089                 ELSIF g_sec_alloc_qty(l_rsv_id) = l_needed_sec_quantity THEN
5090                    l_allocation_quantity := LEAST(g_alloc_qty(l_rsv_id),l_allocation_quantity);
5091                    -- Added for 14699845 (Flexible lot allocation)
5092                    l_orig_needed_quantity := LEAST(g_alloc_qty(l_rsv_id),l_orig_needed_quantity);
5093                 ELSE
5094                    l_allocation_quantity := l_needed_quantity;
5095                    -- Added for 14699845 (Flexible lot allocation)
5096                    l_orig_needed_quantity := p_needed_quantity;
5097                 END IF;
5098 
5099                 IF l_debug = 1 THEN
5100                    log_statement(l_api_name,'(no lot conv) l_allocation_quantity: ', l_allocation_quantity);
5101                    -- Added for 14699845 (Flexible lot allocation)
5102                    log_statement(l_api_name,'(no lot conv) l_orig_needed_quantity: ', l_orig_needed_quantity);
5103                 END IF;
5104              END IF;
5105           END IF; --} l_rsv_lot_number
5106        --} l_rsv_id > 0
5107        ELSE
5108           --{ No reservation exists
5109           IF (l_lot_control_code = 2 AND l_lot_conv_factor_flag > 0 ) THEN
5110              l_lot_allocation_quantity  := inv_convert.inv_um_convert(
5111                                                item_id          => p_inventory_item_id
5112                                              , lot_number       => g_locs(p_record_id).lot_number
5113                                              , organization_id  => p_organization_id
5114                                              , precision        => NULL
5115                                              , from_quantity    => l_sallocation_quantity
5116                                              , from_unit        => p_secondary_uom
5117                                              , to_unit          => p_primary_uom
5118                                              , from_name        => NULL
5119                                              , to_name          => NULL
5120                                              );
5121              IF (l_lot_allocation_quantity = -99999) THEN
5122                 IF l_debug = 1 THEN
5123                    log_statement(l_api_name, 'lot uom conversion error','');
5124                 END IF;
5125                 FND_MESSAGE.SET_NAME('INV','INV_NO_CONVERSION_ERR');
5126                 fnd_msg_pub.ADD;
5127                 RAISE FND_API.G_EXC_ERROR;
5128              END IF;
5129              l_allocation_quantity := l_lot_allocation_quantity;
5130              IF l_debug = 1 THEN
5131                 log_statement(l_api_name,'(no rsv) l_allocation_quantity ', l_allocation_quantity);
5132              END IF;
5133           ELSE
5134              -- Bug 8665496- sec allocation qty should always be
5135              -- equal to requested quantity by user.
5136              l_allocation_quantity := l_needed_quantity;
5137           END IF;
5138        END IF; --}
5139     --}
5140     ELSE --{
5141        -- fulfillment based on primary
5142        /* lot specific conversion  3986955*/
5143        IF (l_dual_uom_ctl > 1 AND inv_cache.item_rec.tracking_quantity_ind = 'PS') --{
5144        -- Bug 7587155 - item could be PS but not lot controlled!
5145        -- and nvl(g_locs(p_record_id).lot_number,'-9999') <> '-9999'
5146        THEN
5147           IF wms_engine_pvt.g_sec_qty_round_mode IS NOT NULL THEN --{
5148              IF l_allocation_quantity <= g_locs(p_record_id).quantity THEN --{
5149 
5150                 IF (l_lot_control_code = 2 AND l_lot_conv_factor_flag > 0 ) THEN --{
5151                    l_lot_sallocation_quantity := inv_convert.inv_um_convert(
5152                                                      item_id          => p_inventory_item_id
5153                                                    , lot_number       => g_locs(p_record_id).lot_number
5154                                                    , organization_id  => p_organization_id
5155                                                    , precision        => NULL
5156                                                    , from_quantity    => l_allocation_quantity
5157                                                    , from_unit        => p_primary_uom
5158                                                    , to_unit          => p_secondary_uom
5159                                                    , from_name        => NULL
5160                                                    , to_name          => NULL
5161                                                    );
5162                    IF l_debug = 1 THEN
5163                       log_statement(l_api_name,'validate and insert'
5164                           ,'Secondary quantity from UOM conversion: ' || l_lot_sallocation_quantity);
5165                    END IF;
5166 
5167                    IF (l_lot_sallocation_quantity <> -99999) THEN
5168                       l_sallocation_quantity := l_lot_sallocation_quantity;
5169                    ELSE
5170                       IF l_debug = 1 THEN
5171                          log_error(l_api_name,'validate and insert','UOM conversion error');
5172                       END IF;
5173                       FND_MESSAGE.SET_NAME('INV','INV_NO_CONVERSION_ERR');
5174                       fnd_msg_pub.ADD;
5175                       RAISE FND_API.G_EXC_ERROR;
5176                    END IF;
5177                 END IF; --}
5178 
5179                 IF wms_engine_pvt.g_sec_qty_round_mode = 'R' THEN
5180                    l_sallocation_quantity := ROUND(l_sallocation_quantity);
5181                 ELSIF wms_engine_pvt.g_sec_qty_round_mode = 'F' THEN
5182                    l_sallocation_quantity := FLOOR(l_sallocation_quantity);
5183                 ELSIF wms_engine_pvt.g_sec_qty_round_mode = 'C' THEN
5184                    l_sallocation_quantity := CEIL(l_sallocation_quantity);
5185                 END IF;
5186 
5187                 IF l_sallocation_quantity <= 0 THEN
5188                    IF l_debug = 1 THEN
5189                       log_statement(l_api_name,'validate and insert'
5190                           ,'Allocating integer secondary, and no secondary remaining');
5191                    END IF;
5192                    x_remaining_quantity     := 0;
5193                    x_sec_remaining_quantity := 0;
5194                    x_allocated_quantity     := 0;
5195                    x_sec_allocated_quantity := 0;
5196                    x_inserted_record        := FALSE;
5197                    RETURN;
5198                 ELSE
5199                    IF (l_lot_control_code = 2 AND l_lot_conv_factor_flag > 0 ) THEN
5200                       l_allocation_quantity := inv_convert.inv_um_convert(
5201                                                    item_id          => p_inventory_item_id
5202                                                  , lot_number       => g_locs(p_record_id).lot_number
5203                                                  , organization_id  => p_organization_id
5204                                                  , precision        => NULL
5205                                                  , from_quantity    => l_sallocation_quantity
5206                                                  , from_unit        => p_secondary_uom
5207                                                  , to_unit          => p_primary_uom
5208                                                  , from_name        => NULL
5209                                                  , to_name          => NULL
5210                                                  );
5211                       IF l_debug = 1 THEN
5212                          log_statement(l_api_name,'validate and insert'
5213                              ,'Primary quantity from UOM conversion: ' || l_allocation_quantity);
5214                       END IF;
5215                    ELSE
5216                       l_allocation_quantity :=
5217                         ROUND((l_sallocation_quantity/l_needed_sec_quantity) * l_needed_quantity,5);
5218                    END IF;
5219                 END IF;
5220              END IF; --} if l_allocation_quantity <= g_locs(p_record_id).quantity
5221           --}
5222           ELSE --{ g_sec_qty_round_mode is null
5223 
5224              /* bug 5441849, if detailed reservation exist, meaning that user has made the
5225               * correct 2nd qty either by system defaults on the lot
5226               * or manually changed it with the appropriate value, this value on the reservation
5227               * should be carried over to the allocation
5228               */
5229 
5230              -- Bug 8247123: check if sec qty already allocated.  This can happen
5231              -- either from other locators for the current pick rule, or from previous rules.
5232              IF g_sec_alloc_qty.EXISTS(p_reservation_id) THEN
5233                 l_rsv_id := p_reservation_id;
5234                 l_rsv_lot_number := l_reserved_lot;  -- Added for 14699845 (Flexible lot allocation)
5235              ELSE --{
5236                 OPEN c_detailed_reservation;
5237                 FETCH c_detailed_reservation
5238                  INTO l_rsv_id
5239                     , l_rsv_lot_number
5240                     , l_rsv_qty
5241                     , l_pri_res_qty
5242                     , l_rsv_dtl_qty
5243                     , l_rsv_uom
5244                     , l_sec_rsv_qty
5245                     , l_sec_dtl_qty;
5246                 CLOSE c_detailed_reservation;
5247                 IF NVL(l_rsv_id,0) > 0 THEN --{
5248                    IF l_debug = 1 THEN
5249                       log_statement(l_api_name,'reservation exists for dual UOM item.','');
5250                       log_statement(l_api_name,'l_rsv_id        ', l_rsv_id);
5251                       log_statement(l_api_name,'l_rsv_lot_number', l_rsv_lot_number);
5252                       log_statement(l_api_name,'l_rsv_qty       ', l_rsv_qty);
5253                       log_statement(l_api_name,'l_pri_res_qty   ', l_pri_res_qty);
5254                       log_statement(l_api_name,'l_rsv_dtl_qty   ', l_rsv_dtl_qty);
5255                       log_statement(l_api_name,'l_rsv_uom       ', l_rsv_uom);
5256                       log_statement(l_api_name,'l_sec_rsv_qty   ', l_sec_rsv_qty);
5257                       log_statement(l_api_name,'l_sec_dtl_qty   ', l_sec_dtl_qty);
5258                    END IF;
5259                    -- Added for bug 8665496
5260                    g_alloc_qty(l_rsv_id)     := l_pri_res_qty - NVL(l_rsv_dtl_qty,0);
5261                    g_sec_alloc_qty(l_rsv_id) := l_sec_rsv_qty - NVL(l_sec_dtl_qty,0);
5262                 --}
5263                 ELSE
5264                    l_rsv_id := 0;
5265                 END IF;
5266              END IF; --} end of g_sec_alloc_qty.EXISTS(p_reservation_id)
5267 
5268              -- bug 8638386 - Start - reorganize/extend fix 8665496 - for lot conversion + deviation
5269              IF l_rsv_id > 0 THEN --{
5270                 IF l_debug = 1 THEN
5271                    log_statement(l_api_name,'l_needed_quantity                 ', l_needed_quantity);
5272                    log_statement(l_api_name,'l_needed_sec_quantity             ', l_needed_sec_quantity);
5273                    log_statement(l_api_name,'remaining pri [g_alloc_qty(l_rsv_id)]    ', g_alloc_qty(l_rsv_id));
5274                    log_statement(l_api_name,'remaining sec [g_sec_alloc_qty(l_rsv_id)]', g_sec_alloc_qty(l_rsv_id));
5275                    log_statement(l_api_name,'l_rsv_lot_number                  ', l_rsv_lot_number);
5276                 END IF;
5277                 --
5278                 -- see if the reservation is high level or detailed at lot level.
5279                 --
5280                 IF (l_rsv_lot_number IS NOT NULL) THEN
5281                    --
5282                    -- lot level reservation exists
5283                    --   may or may not have a lot specific conversion
5284                    --     user may or may not have played with the deviation on top.
5285                    --
5286                    IF g_alloc_qty(l_rsv_id) > l_needed_quantity THEN
5287                       -- distribute sec in the same ratio as primary
5288                    l_sallocation_quantity :=
5289                       ROUND((l_needed_quantity/g_alloc_qty(l_rsv_id)) * g_sec_alloc_qty(l_rsv_id),5);
5290                    ELSIF g_alloc_qty(l_rsv_id) = l_needed_quantity THEN
5291                       l_sallocation_quantity := g_sec_alloc_qty(l_rsv_id);
5292                    ELSE
5293                       l_sallocation_quantity := l_needed_sec_quantity;
5294                    END IF;
5295 
5296                    IF l_debug = 1 THEN
5297                       log_statement(l_api_name,'(1) l_sallocation_quantity   ', l_sallocation_quantity);
5298                    END IF;
5299                 ELSE --{ (l_rsv_lot_number IS NULL)
5300                    --
5301                    -- No lot level reservation exists (high level/partial)
5302                    --   the candidate lot may or may not have a lot specific conversion
5303                    --     user may or may not have played with the deviation.
5304                    --
5305                    IF l_debug = 1 THEN
5306                       log_statement(l_api_name,'g_locs(p_record_id).lot_number ', g_locs(p_record_id).lot_number);
5307                    END IF;
5308 
5309                    IF l_debug = 1 THEN
5310                       log_statement(l_api_name, 'l_lot_conv_factor_flag         ', l_lot_conv_factor_flag);
5311                       log_statement(l_api_name, 'l_lot_control_code             ', l_lot_control_code);
5312                    END IF;
5313 
5314                    IF (l_lot_control_code = 2 AND l_lot_conv_factor_flag > 0 ) THEN --{
5315                       -- use lot specific conversion
5316                       l_lot_sallocation_quantity  := inv_convert.inv_um_convert(
5317                                   item_id          => p_inventory_item_id
5318                                 , lot_number       => g_locs(p_record_id).lot_number
5319                                 , organization_id  => p_organization_id
5320                                 , precision        => null
5321                                 , from_quantity    => l_allocation_quantity
5322                                 , from_unit        => p_primary_uom
5323                                 , to_unit          => p_secondary_uom
5324                                 , from_name        => NULL
5325                                 , to_name          => NULL
5326                                 );
5327                       IF (l_lot_sallocation_quantity = -99999) THEN
5328                          IF l_debug = 1 THEN
5329                             log_statement(l_api_name, '(2)lot uom conversion error','');
5330                          END IF;
5331                          FND_MESSAGE.SET_NAME('INV','INV_NO_CONVERSION_ERR');
5332                          fnd_msg_pub.ADD;
5333                          RAISE FND_API.G_EXC_ERROR;
5334                       END IF;
5335                       IF l_debug = 1 THEN
5336                          log_statement(l_api_name,'(1) l_lot_sallocation_quantity ', l_lot_sallocation_quantity);
5337                       END IF;
5338 
5339                       IF (g_sec_alloc_qty(l_rsv_id) <> l_lot_sallocation_quantity) THEN
5340                          --
5341                          -- if user played with the deviation on top of the lot specific
5342                          --
5343                          l_are_qties_valid := INV_CONVERT.within_deviation(
5344                                 p_organization_id     => p_organization_id
5345                               , p_inventory_item_id   => p_inventory_item_id
5346                               , p_lot_number          => g_locs(p_record_id).lot_number
5347                               , p_precision           => NULL
5348                               , p_quantity            => l_allocation_quantity
5349                               , p_uom_code1           => p_primary_uom
5350                               , p_quantity2           => g_sec_alloc_qty(l_rsv_id)
5351                               , p_uom_code2           => p_secondary_uom
5352                               , p_unit_of_measure1    => NULL
5353                               , p_unit_of_measure2    => NULL);
5354 
5355                          IF (l_are_qties_valid = 0) THEN
5356                             -- outside deviation
5357                             l_sallocation_quantity := l_lot_sallocation_quantity;
5358                          ELSE
5359                             l_sallocation_quantity := g_sec_alloc_qty(l_rsv_id);
5360                          END IF;
5361                       END IF;
5362 
5363                       IF l_debug = 1 THEN
5364                          log_statement(l_api_name,'(with lot conv) l_sallocation_quantity  ', l_sallocation_quantity);
5365                       END IF;
5366                    --}
5367                    ELSE
5368                       --
5369                       -- no lot specific conversion but accomodate user playing with deviation
5370                       IF g_alloc_qty(l_rsv_id) > l_needed_quantity THEN
5371                          -- distribute sec in the same ratio as primary
5372                          l_sallocation_quantity :=
5373                             ROUND((l_needed_quantity/g_alloc_qty(l_rsv_id)) * g_sec_alloc_qty(l_rsv_id),5);
5374 
5375                          -- Added for 14699845 (Flexible lot allocation)
5376                          IF (l_orig_needed_quantity > 0 AND l_orig_needed_quantity <> p_needed_quantity) THEN
5377                              l_orig_needed_sec_qty :=
5378                                 ROUND((l_orig_needed_quantity/g_alloc_qty(l_rsv_id)) * g_sec_alloc_qty(l_rsv_id),5);
5379                          END IF;
5380                       ELSIF g_alloc_qty(l_rsv_id) = l_needed_quantity THEN
5381                          l_sallocation_quantity := g_sec_alloc_qty(l_rsv_id);
5382                          -- Added for 14699845 (Flexible lot allocation)
5383                          l_orig_needed_sec_qty := g_sec_alloc_qty(l_rsv_id);
5384                       ELSE
5385                          l_sallocation_quantity := l_needed_sec_quantity;
5386                          -- Added for 14699845 (Flexible lot allocation)
5387                          l_orig_needed_sec_qty := p_needed_sec_quantity;
5388                       END IF;
5389 
5390                       IF l_debug = 1 THEN
5391                          log_statement(l_api_name,'(no lot conv) l_sallocation_quantity: ', l_sallocation_quantity);
5392                          -- Added for 14699845 (Flexible lot allocation)
5393                          log_statement(l_api_name,'(no lot conv) l_orig_needed_sec_qty: ', l_orig_needed_sec_qty);
5394                       END IF;
5395                    END IF;
5396                 END IF; --} end else l_rsv_lot_number is not null
5397              --} l_rsv_id > 0
5398              ELSE
5399                 -- No reservation exists
5400                 IF (l_lot_control_code = 2 AND l_lot_conv_factor_flag > 0 ) THEN
5401                    l_lot_sallocation_quantity  := inv_convert.inv_um_convert(
5402                                item_id          => p_inventory_item_id
5403                              , lot_number       => g_locs(p_record_id).lot_number
5404                              , organization_id  => p_organization_id
5405                              , precision        => NULL
5406                              , from_quantity    => l_allocation_quantity
5407                              , from_unit        => p_primary_uom
5408                              , to_unit          => p_secondary_uom
5409                              , from_name        => NULL
5410                              , to_name          => NULL
5411                              );
5412                    IF (l_lot_sallocation_quantity = -99999) THEN
5413                       IF l_debug = 1 THEN
5414                          log_statement(l_api_name, '(2)lot uom conversion error','');
5415                       END IF;
5416                       FND_MESSAGE.SET_NAME('INV','INV_NO_CONVERSION_ERR');
5417                       fnd_msg_pub.ADD;
5418                       RAISE FND_API.G_EXC_ERROR;
5419                    END IF;
5420                    l_sallocation_quantity := l_lot_sallocation_quantity;
5421                    IF l_debug = 1 THEN
5422                       log_statement(l_api_name,'(no rsv) l_sallocation_quantity ', l_sallocation_quantity);
5423                    END IF;
5424                 ELSE
5425                    -- Bug 8665496- sec allocation qty should always be
5426                    -- equal to requested quantity by user.
5427                    l_sallocation_quantity := l_needed_sec_quantity;
5428                 END IF;
5429              END IF;
5430           END IF; --} end ELSE g_sec_qty_round_mode is not null
5431        END IF; --} l_dual_uom_ctl > 1
5432        -- bug 8638386 - end
5433     END IF; --} g_fulfillment_base
5434 
5435     IF l_dual_uom_ctl = 1 THEN
5436        l_sallocation_quantity := NULL;
5437        l_orig_needed_sec_qty := NULL; -- Added for 14699845 (Flexible lot allocation)
5438     END IF;
5439 
5440     IF l_debug = 1 THEN
5441        log_statement(l_api_name, 'p_record_id            ', p_record_id);
5442        log_statement(l_api_name, 'lot_divisible_flag     ', l_lot_divisible_flag);
5443        log_statement(l_api_name, 'needed quantity        ', l_needed_quantity);
5444        log_statement(l_api_name, 'sec_needed quantity    ', l_needed_sec_quantity);
5445        log_statement(l_api_name, 'l_allocation_quantity  ', l_allocation_quantity);
5446        log_statement(l_api_name, 'l_sallocation_quantity ', l_sallocation_quantity);
5447        -- Added for 14699845 (Flexible lot allocation)
5448        log_statement(l_api_name, '(2) l_orig_needed_sec_qty ', l_orig_needed_sec_qty);
5449        log_statement(l_api_name, 'g_locs(p_record_id).quantity           ', g_locs(p_record_id).quantity);
5450        log_statement(l_api_name, 'g_locs(p_record_id).secondary_quantity ', g_locs(p_record_id).secondary_quantity);
5451     END IF;
5452 
5453     /* bug 3972784, remove locator_id if no locator control */
5454     IF ( wms_engine_pvt.g_org_loc_control in (1,4)                   -- no loc ctl org level
5455          AND ( wms_engine_pvt.g_sub_loc_control = 1                  -- no loc ctl sub level
5456             OR (wms_engine_pvt.g_sub_loc_control = 5
5457                  AND wms_engine_pvt.g_item_loc_control = 1           -- no loc ctl item level
5458                )
5459              )
5460        )
5461     THEN
5462         l_to_locator_id := null;
5463         log_statement(l_api_name, 'non locator controled',' Non locator controled');
5464     END IF;
5465 
5466     IF l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1
5467        AND (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
5468                AND g_locs(p_record_id).quantity <= l_allocation_quantity)
5469            OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
5470                AND  g_locs(p_record_id).secondary_quantity <= l_sallocation_quantity)
5471            )
5472     THEN -- lot ctl and indivisible
5473        l_allocation_quantity  := g_locs(p_record_id).quantity;
5474        l_sallocation_quantity := g_locs(p_record_id).secondary_quantity;
5475 
5476        -- Added for 14699845 (Flexible lot allocation)
5477        IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
5478           IF l_entire_lpn_alloc = 'Y' THEN
5479              l_orig_needed_quantity := g_locs(p_record_id).quantity;
5480           ELSIF (l_orig_needed_sec_qty > 0
5481                  AND l_orig_needed_sec_qty <> p_needed_sec_quantity
5482                  AND g_locs(p_record_id).secondary_quantity <= l_orig_needed_sec_qty)
5483           THEN
5484              l_orig_needed_quantity := LEAST(l_orig_needed_quantity, g_locs(p_record_id).quantity);
5485           END IF;
5486        ELSE
5487           IF l_entire_lpn_alloc = 'Y' THEN
5488              l_orig_needed_sec_qty := g_locs(p_record_id).secondary_quantity;
5489           ELSIF (l_orig_needed_quantity > 0
5490                  AND l_orig_needed_quantity <> p_needed_quantity
5491                  AND g_locs(p_record_id).quantity <= l_orig_needed_quantity)
5492           THEN
5493              l_orig_needed_sec_qty := LEAST(l_orig_needed_sec_qty, g_locs(p_record_id).secondary_quantity);
5494           END IF;
5495        END IF;
5496     ELSE
5497        IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
5498              AND l_allocation_quantity > g_locs(p_record_id).quantity)
5499           OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
5500              AND l_sallocation_quantity >= g_locs(p_record_id).secondary_quantity)
5501           OR l_entire_lpn_alloc = 'Y'
5502           )
5503        THEN
5504           IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
5505              l_sallocation_quantity := g_locs(p_record_id).secondary_quantity;
5506              l_pri_conv_qty := inv_convert.inv_um_convert(
5507                                    item_id          => p_inventory_item_id
5508                                  , lot_number       => g_locs(p_record_id).lot_number
5509                                  , organization_id  => p_organization_id
5510                                  , precision        => NULL
5511                                  , from_quantity    => l_sallocation_quantity
5512                                  , from_unit        => p_secondary_uom
5513                                  , to_unit          => p_primary_uom
5514                                  , from_name        => NULL
5515                                  , to_name          => NULL
5516                                  );
5517              l_allocation_quantity := LEAST(g_locs(p_record_id).quantity,l_pri_conv_qty);
5518              -- Added for 14699845 (Flexible lot allocation)
5519              l_orig_needed_quantity := l_allocation_quantity;
5520           ELSE
5521              l_allocation_quantity  := g_locs(p_record_id).quantity;
5522              l_sallocation_quantity := g_locs(p_record_id).secondary_quantity;
5523              -- Added for 14699845 (Flexible lot allocation)
5524              l_orig_needed_sec_qty  := l_sallocation_quantity;
5525           END IF;
5526        END IF;
5527     END IF;
5528     -- BUG 3609380 :  Removing p_to_subinevntory_code.
5529     -- query quantity tree
5530     IF l_debug = 1  THEN
5531        log_statement(l_api_name, 'p_revision                                  ', g_locs(p_record_id).revision);
5532        log_statement(l_api_name, 'p_lot_number                                ', g_locs(p_record_id).lot_number);
5533        log_statement(l_api_name, 'p_subinventory                              ', g_locs(p_record_id).subinventory_code);
5534        log_statement(l_api_name, 'record quantity (l_allocation_quantity)     ', l_allocation_quantity);
5535        log_statement(l_api_name, 'sec_record_quantity (l_sallocation_quantity)', l_sallocation_quantity);
5536 
5537        -- Added for 14699845 (Flexible lot allocation)
5538        log_statement(l_api_name, 'l_orig_needed_quantity: ', l_orig_needed_quantity);
5539        log_statement(l_api_name, 'l_orig_needed_sec_qty: ', l_orig_needed_sec_qty);
5540 
5541        log_statement(l_api_name, 'query_tree', 'calling Query Tree');
5542        log_statement(l_api_name, 'tree_id                                     ', p_tree_id);
5543     END IF;
5544 
5545     -- Added for Bug 8570601 start
5546      IF l_debug = 1  THEN
5547         log_statement(l_api_name, 'p_transaction_temp_id', 'p_transaction_temp_id: ' || p_transaction_temp_id);
5548         log_statement(l_api_name, 'p_type_code', 'p_type_code: ' || p_type_code);
5549      END IF;
5550      IF inv_cache.set_mol_rec(p_transaction_temp_id) THEN
5551         l_transaction_type_id  := inv_cache.mol_rec.transaction_type_id;
5552      END IF;
5553      IF l_debug = 1  THEN
5554         log_statement(l_api_name, 'l_transaction_type_id', 'l_transaction_type_id: ' || l_transaction_type_id);
5555      END IF;
5556      IF l_transaction_type_id <> 0 THEN
5557         IF inv_cache.set_mtt_rec(l_transaction_type_id) THEN
5558            l_transaction_action_id := inv_cache.mtt_rec.transaction_action_id;
5559            l_transaction_source_type_id := inv_cache.mtt_rec.transaction_source_type_id;
5560         END IF;
5561      END IF;
5562      l_to_subinventory_code := chk_for_passing_xfer_sub ( TO_NUMBER(p_transaction_temp_id) ,
5563                                                            p_to_subinventory_code );
5564 
5565     IF l_debug = 1  THEN
5566        log_statement(l_api_name, 'l_to_subinventory_code', 'l_to_subinventory_code: ' || l_to_subinventory_code);
5567        log_statement(l_api_name, 'p_to_subinventory_code', 'p_to_subinventory_code: ' || p_to_subinventory_code);
5568        log_statement(l_api_name, 'l_transaction_action_id', 'l_transaction_action_id: ' || l_transaction_action_id);
5569        log_statement(l_api_name, 'l_transaction_action_id', 'l_transaction_source_type_id: ' || l_transaction_source_type_id);
5570        log_statement(l_api_name, 'p_type_code', 'p_type_code: ' || p_type_code);
5571        log_statement(l_api_name, 'g_locs(p_record_id).subinventory_code', 'g_locs(p_record_id).subinventory_code: '
5572                                   || g_locs(p_record_id).subinventory_code);
5573        log_statement(l_api_name, 'g_locs(p_record_id).serial_number', 'g_locs(p_record_id).serial_number: '
5574                                   || g_locs(p_record_id).serial_number);
5575     END IF;
5576 
5577     IF ( l_transaction_action_id = inv_globals.g_action_subxfr AND
5578          l_transaction_source_type_id = inv_globals.g_sourcetype_moveorder AND
5579          l_to_subinventory_code IS NULL)
5580     THEN
5581        /*For MO XFER Putaway , we will use the src sub as dest sub*/
5582        l_to_subinventory_code := g_locs(p_record_id).subinventory_code;
5583     END IF;
5584 
5585     IF l_debug = 1  THEN
5586        log_statement(l_api_name, 'l_to_subinventory_code', 'l_to_subinventory_code: ' || l_to_subinventory_code);
5587     END IF;
5588     -- Added for Bug 8570601 end
5589 
5590     inv_quantity_tree_pvt.query_tree(
5591         p_api_version_number         =>   g_qty_tree_api_version
5592       , p_init_msg_lst               =>   fnd_api.g_false
5593       , x_return_status              =>   x_return_status
5594       , x_msg_count                  =>   x_msg_count
5595       , x_msg_data                   =>   x_msg_data
5596       , p_tree_id                    =>   p_tree_id
5597       , p_revision                   =>   g_locs(p_record_id).revision
5598       , p_lot_number                 =>   g_locs(p_record_id).lot_number
5599       , p_subinventory_code          =>   g_locs(p_record_id).subinventory_code
5600       , p_locator_id                 =>   g_locs(p_record_id).locator_id
5601       , x_qoh                        =>   l_qoh
5602       , x_sqoh                       =>   l_sqoh
5603       , x_rqoh                       =>   l_rqoh
5604       , x_srqoh                      =>   l_srqoh
5605       , x_qr                         =>   l_qr
5606       , x_sqr                        =>   l_sqr
5607       , x_qs                         =>   l_qs
5608       , x_sqs                        =>   l_sqs
5609       , x_att                        =>   l_att
5610       , x_satt                       =>   l_satt
5611       , x_atr                        =>   l_atr
5612       , x_satr                       =>   l_satr
5613       , p_transfer_subinventory_code =>   l_to_subinventory_code -- Modified for Bug 8570601
5614       , p_cost_group_id              =>   g_locs(p_record_id).cost_group_id
5615       , p_lpn_id                     =>   g_locs(p_record_id).lpn_id
5616       );
5617     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5618        IF l_debug = 1 THEN
5619           log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
5620        END IF;
5621        RAISE fnd_api.g_exc_unexpected_error;
5622     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5623        IF l_debug = 1 THEN
5624           log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
5625        END IF;
5626        RAISE fnd_api.g_exc_error;
5627     END IF;
5628 
5629     IF l_debug = 1 THEN
5630        log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
5631        log_statement(l_api_name, 'satt_qty', 'Secondary Available quantity = ' || l_satt);
5632        log_statement(l_api_name, 'grade_code', 'grade_code = ' || p_grade_code);
5633     END IF;
5634 
5635     -- bug 9378888 start
5636     IF l_debug = 1 THEN
5637        log_statement(l_api_name, 'validate and insert', 'Fetch the l_top_model_line_id using txn_source_line_id: '
5638                                   || inv_cache.mol_rec.txn_source_line_id);
5639     END IF;
5640     IF (p_type_code = 2
5641         AND l_transaction_action_id = inv_globals.g_action_stgxfr
5642         AND inv_cache.set_oola_rec(inv_cache.mol_rec.txn_source_line_id))
5643     THEN
5644        l_top_model_line_id := inv_cache.oola_rec.top_model_line_id;
5645     ELSE
5646        l_top_model_line_id := NULL;
5647     END IF;
5648 
5649     IF l_debug = 1 THEN
5650        log_statement(l_api_name, 'validate and insert', 'Fetched l_top_model_line_id: ' || l_top_model_line_id);
5651     END IF;
5652 
5653    /* Following code  is added for bug 9378888.It derives the
5654     * top_model_line_id for the order line
5655     * for which allocation is to be done.
5656     * If  top_model_line_id is not null (which indicates item is
5657     * the component of PTO item ) for which l_indivisible_flag should
5658     * always be Y as allocation
5659     * quantity has to be in integer number. */
5660     IF (l_top_model_line_id IS NOT NULL ) THEN
5661        l_indivisible_flag  := 'Y';
5662     END IF;
5663 
5664     IF l_debug = 1 THEN
5665        log_statement(l_api_name, 'validate and insert', 'Final l_indivisible_flag: ' || l_indivisible_flag);
5666     END IF;
5667     IF (l_indivisible_flag = 'Y' AND l_att <> 0)
5668     THEN  -- Bug12381218
5669        l_floored_att := FLOOR(l_att);
5670        -- Scale the secondary quantity
5671        IF (inv_cache.item_rec.tracking_quantity_ind = 'PS') --16500984
5672        THEN
5673           l_satt := (l_satt/l_att) * l_floored_att;
5674           l_satt := ROUND(l_satt,5);
5675        END IF;
5676        l_att := l_floored_att;
5677     ELSIF wms_engine_pvt.g_sec_qty_round_mode IS NOT NULL
5678           AND NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
5679     THEN
5680        l_floored_satt := FLOOR(l_satt);
5681        -- Scale the primary quantity
5682        IF inv_cache.item_rec.secondary_default_ind = 'F'
5683        THEN
5684           l_att := (l_att/l_satt) * l_floored_satt;
5685           l_att := ROUND(l_att,5);
5686        END IF;
5687        l_satt := l_floored_satt;
5688     END IF;
5689 
5690     IF l_debug = 1 THEN
5691        log_statement(l_api_name, 'validate and insert', 'New l_att: ' || l_att);
5692        log_statement(l_api_name, 'validate and insert', 'New l_satt: ' || l_satt);
5693     END IF;
5694     -- bug 9378888 end
5695 
5696     -- [ LOT_INDIV
5697     -- Checking ,
5698     -- a. If the pre suggestion record fetched from the rule is greater than the max qty allowed
5699     --    after adjusting the for upper tolerance .
5700     -- b. If ATT qty is equal to ON hand Qty to that of the pre suggestions record qty.
5701     --    It may be different due to partial reservations.
5702     -- The pre suggestions record will be skipped, if any of the above condition is false
5703     -- and fetch the next rec
5704     -- ]
5705     IF l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1
5706        AND (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
5707                AND g_locs(p_record_id).quantity  <= l_allocation_quantity)
5708            OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
5709                AND g_locs(p_record_id).secondary_quantity <= l_sallocation_quantity)
5710            )
5711     THEN
5712        --
5713        -- lot ctl and indivisible
5714        -- For allocation based on secondary, do not allow primary to go -ve
5715        --
5716        IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
5717               AND l_att = g_locs(p_record_id).quantity AND l_qoh = l_att)
5718           OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
5719               AND l_satt = g_locs(p_record_id).secondary_quantity AND l_sqoh = l_satt AND l_att > 0)
5720           )
5721        THEN
5722           l_indiv_lot_allowed := 'Y';
5723        ELSE
5724           l_indiv_lot_allowed := 'N';
5725           IF l_debug = 1 THEN
5726              log_statement(l_api_name, '', 'All the material is not available for this rec.');
5727           END IF;
5728        END IF;
5729     ELSE
5730        l_indiv_lot_allowed := 'N' ;
5731     END IF;
5732 
5733     -- update record quantity
5734     IF l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1  THEN  --{ lot ctl and indivisible
5735        IF l_indiv_lot_allowed = 'Y' THEN
5736           -- Start changes for 14699845 (Flexible lot allocation)
5737           IF ( (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
5738                    AND l_orig_needed_quantity > 0 AND l_orig_needed_quantity <> p_needed_quantity)
5739                OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
5740                    AND l_orig_needed_sec_qty > 0 AND l_orig_needed_sec_qty <> p_needed_sec_quantity)
5741                )
5742              AND l_allocate_lot_flag = 'N')
5743           THEN
5744              g_locs(p_record_id).quantity := LEAST(l_att, l_orig_needed_quantity);
5745              g_locs(p_record_id).secondary_quantity := LEAST(l_satt, l_orig_needed_sec_qty);
5746              -- update possible allocate quantity
5747              l_allocation_quantity := LEAST(l_att, l_orig_needed_quantity);
5748              l_sallocation_quantity := LEAST(l_satt, l_orig_needed_sec_qty);
5749           ELSIF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_orig_needed_sec_qty > 0
5750                  AND l_allocate_lot_flag = 'N')
5751           THEN
5752              g_locs(p_record_id).quantity := l_att;
5753              g_locs(p_record_id).secondary_quantity := LEAST(l_satt, l_orig_needed_sec_qty);
5754              -- update possible allocate quantity
5755              l_allocation_quantity := l_att;
5756              l_sallocation_quantity := LEAST(l_satt, l_orig_needed_sec_qty);
5757           ELSIF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_orig_needed_quantity > 0
5758                  AND l_allocate_lot_flag = 'N')
5759           THEN
5760              g_locs(p_record_id).quantity := LEAST(l_att, l_orig_needed_quantity);
5761              g_locs(p_record_id).secondary_quantity := l_satt;
5762              -- update possible allocate quantity
5763              l_allocation_quantity := LEAST(l_att, l_orig_needed_quantity);
5764              l_sallocation_quantity := l_satt;
5765           ELSE
5766              g_locs(p_record_id).quantity := l_att;
5767              g_locs(p_record_id).secondary_quantity := l_satt;
5768              -- update possible allocate quantity
5769              l_allocation_quantity := l_att;
5770              l_sallocation_quantity := l_satt;
5771           END IF;
5772           g_locs(p_record_id).grade_code := p_grade_code;
5773           -- End changes for 14699845 (Flexible lot allocation)
5774        ELSE
5775           l_allocation_quantity   := 0;
5776           l_sallocation_quantity  := 0;
5777        END IF;
5778 
5779        IF l_debug = 1 THEN
5780           log_statement(l_api_name, 'Lot Indiv', ' lot IS NOT divisible -- indivsible' );
5781           log_statement(l_api_name, 'Lot Indiv', 'New possible qty: ' || l_allocation_quantity);
5782           log_statement(l_api_name, 'Lot Indiv', 'New possible sec qty: ' || l_sallocation_quantity);
5783        END IF;
5784     --}
5785     ELSE --{
5786        IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_att < g_locs(p_record_id).quantity)
5787           OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND ( (l_satt < g_locs(p_record_id).secondary_quantity)
5788                                                              OR (l_att < g_locs(p_record_id).quantity) ) )
5789           )
5790        THEN
5791           g_locs(p_record_id).quantity := l_att;
5792           g_locs(p_record_id).secondary_quantity := l_satt;
5793           g_locs(p_record_id).grade_code := p_grade_code;
5794        END IF;
5795        -- update possible allocate quantity
5796        IF ( (l_att < l_allocation_quantity) OR (l_satt < l_sallocation_quantity) )
5797        THEN --{
5798           IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
5799              AND wms_engine_pvt.g_sec_qty_round_mode IS NOT NULL
5800           THEN --{
5801              l_sallocation_quantity := inv_convert.inv_um_convert(
5802                                            item_id          => p_inventory_item_id
5803                                          , lot_number       => (CASE WHEN l_lot_conv_factor_flag = 0 THEN
5804                                                                           NULL
5805                                                                      ELSE g_locs(p_record_id).lot_number
5806                                                                      END)  -- Added for 14699845 (Flexible lot allocation)
5807                                          , organization_id  => p_organization_id
5808                                          , precision        => NULL
5809                                          , from_quantity    => l_att
5810                                          , from_unit        => p_primary_uom
5811                                          , to_unit          => p_secondary_uom
5812                                          , from_name        => NULL
5813                                          , to_name          => NULL
5814                                          );
5815              IF l_debug = 1 THEN
5816                 log_statement(l_api_name,'validate and insert'
5817                     ,'Secondary quantity from UOM conversion (att < requested): ' || l_sallocation_quantity);
5818              END IF;
5819              IF (l_sallocation_quantity <> -99999)
5820              THEN --{
5821                 l_sallocation_quantity := FLOOR(l_sallocation_quantity);
5822 
5823                 IF l_sallocation_quantity <= 0 THEN
5824                    IF l_debug = 1 THEN
5825                       log_statement(l_api_name,'validate and insert'
5826                           ,'Allocating integer secondary, and no secondary remaining (att < requested)');
5827                    END IF;
5828                    x_remaining_quantity     := 0;
5829                    x_sec_remaining_quantity := 0;
5830                    x_allocated_quantity     := 0;
5831                    x_sec_allocated_quantity := 0;
5832                    x_inserted_record        := FALSE;
5833                    RETURN;
5834                 ELSE
5835                    l_allocation_quantity := inv_convert.inv_um_convert(
5836                                                 item_id          => p_inventory_item_id
5837                                               , lot_number       => (CASE WHEN l_lot_conv_factor_flag = 0 THEN
5838                                                                                NULL
5839                                                                           ELSE g_locs(p_record_id).lot_number
5840                                                                           END)  -- Added for 14699845 (Flexible lot allocation)
5841                                               , organization_id  => p_organization_id
5842                                               , precision        => NULL
5843                                               , from_quantity    => l_sallocation_quantity
5844                                               , from_unit        => p_secondary_uom
5845                                               , to_unit          => p_primary_uom
5846                                               , from_name        => NULL
5847                                               , to_name          => NULL
5848                                               );
5849                    IF l_debug = 1 THEN
5850                       log_statement(l_api_name,'validate and insert'
5851                           ,'Primary quantity from UOM conversion (att < requested): ' || l_allocation_quantity);
5852                    END IF;
5853                 END IF;
5854              --}
5855              ELSE
5856                 IF l_debug = 1 THEN
5857                    log_error(l_api_name,'validate and insert','UOM conversion error');
5858                 END IF;
5859                 l_sallocation_quantity := l_satt;
5860              END IF;
5861           --}
5862           ELSE
5863              IF l_att < l_allocation_quantity THEN
5864                 l_allocation_quantity := GREATEST(l_att,0);
5865              END IF;
5866              IF l_satt < l_sallocation_quantity THEN
5867                 l_sallocation_quantity := GREATEST(l_satt,0);
5868              END IF;
5869           END IF;
5870        END IF; --} att < alloc
5871     END IF; --} l_lot_divisible_flag
5872 
5873     IF l_debug = 1 THEN
5874        log_statement(l_api_name, 'tree_qty', 'ATT < possible quantity.  New possible qty: ' || g_locs(p_record_id).quantity);
5875        log_statement(l_api_name, 'tree_qty', 'New possible sec qty: ' || g_locs(p_record_id).secondary_quantity);
5876     END IF;
5877 
5878    /*Bug13361151 -Added following custom hook call for customer to validate the LPN being picked.*/
5879     IF ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_allocation_quantity > 0)
5880          OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sallocation_quantity > 0 AND l_allocation_quantity > 0)
5881        )
5882        AND p_type_code = 2 AND NVL(g_locs(p_record_id).lpn_id,0) > 0
5883     THEN --{
5884        l_already_allocated_pri_qty := 0;
5885        l_already_allocated_sec_qty := 0;
5886        SELECT SUM(primary_quantity), SUM(secondary_quantity)
5887          INTO l_already_allocated_pri_qty, l_already_allocated_sec_qty
5888          FROM wms_transactions_temp
5889         WHERE transaction_temp_id = p_transaction_temp_id
5890           AND type_code      = 2
5891           AND line_type_code = 2  ;
5892 
5893         IF l_debug = 1 THEN
5894            log_statement(l_api_name, 'custom_validate', 'l_needed_quantity :' || l_needed_quantity);
5895            log_statement(l_api_name, 'custom_validate', 'l_needed_sec_quantity :' || l_needed_sec_quantity);
5896            log_statement(l_api_name, 'custom_validate', 'l_allocation_quantity :' || l_allocation_quantity);
5897            log_statement(l_api_name, 'custom_validate', 'l_sallocation_quantity :' || l_sallocation_quantity);
5898            log_statement(l_api_name, 'custom_validate', 'p_transaction_temp_id :' || p_transaction_temp_id);
5899            log_statement(l_api_name, 'custom_validate', 'p_organization_id :' || p_organization_id);
5900            log_statement(l_api_name, 'custom_validate', 'p_inventory_item_id :' || p_inventory_item_id);
5901            log_statement(l_api_name, 'custom_validate', 'g_locs(p_record_id).revision :' || g_locs(p_record_id).revision);
5902            log_statement(l_api_name, 'custom_validate', 'g_locs(p_record_id).subinventory_code :' || g_locs(p_record_id).subinventory_code);
5903            log_statement(l_api_name, 'custom_validate', 'g_locs(p_record_id).locator_id :' || g_locs(p_record_id).locator_id);
5904            log_statement(l_api_name, 'custom_validate', 'g_locs(p_record_id).lot_number :' || g_locs(p_record_id).lot_number);
5905            log_statement(l_api_name, 'custom_validate', 'g_locs(p_record_id).cost_group_id :' || g_locs(p_record_id).cost_group_id);
5906            log_statement(l_api_name, 'custom_validate', 'g_locs(p_record_id).lpn_id :' || g_locs(p_record_id).lpn_id);
5907            log_statement(l_api_name, 'custom_validate', 'p_rule_id :' || p_rule_id);
5908            log_statement(l_api_name, 'custom_validate', 'l_att:' || l_att );
5909            log_statement(l_api_name, 'custom_validate', 'l_satt :' || l_satt);
5910            log_statement(l_api_name, 'custom_validate', 'l_already_allocated_pri_qty :' || l_already_allocated_pri_qty);
5911            log_statement(l_api_name, 'custom_validate', 'l_already_allocated_sec_qty :' || l_already_allocated_sec_qty);
5912        END IF;
5913 
5914        IF NOT WMS_RE_CUSTOM_PUB.custom_validate_picking_sku (
5915                     p_organization_id             => p_organization_id,
5916                     p_inventory_item_id           => p_inventory_item_id,
5917                     p_revision                    => g_locs(p_record_id).revision,
5918                     p_subinventory_code           => g_locs(p_record_id).subinventory_code,
5919                     p_locator_id                  => g_locs(p_record_id).locator_id,
5920                     p_lot_number                  => g_locs(p_record_id).lot_number ,
5921                     p_cost_group_id               => g_locs(p_record_id).cost_group_id ,
5922                     p_lpn_id                      => g_locs(p_record_id).lpn_id ,
5923                     p_rule_id                     => p_rule_id,
5924                     p_move_order_line_id          => p_transaction_temp_id ,
5925                     p_needed_primary_quantity     => l_needed_quantity ,
5926                     p_needed_secondary_quantity   => l_needed_sec_quantity,
5927                     p_picking_primary_quantity    => l_allocation_quantity,
5928                     p_picking_secondary_quantity  => l_sallocation_quantity,
5929                     p_lpn_available_primary_qty   => l_att,
5930                     p_lpn_available_secondary_qty => l_satt,
5931                     p_already_allocated_pri_qty   => l_already_allocated_pri_qty ,
5932                     p_already_allocated_sec_qty   => l_already_allocated_sec_qty
5933                   )
5934        THEN
5935           IF l_debug = 1 THEN
5936              log_statement(l_api_name, 'custom_validate', 'customer validation returns false..So skipping this LPN ' );
5937           END IF;
5938 
5939           x_allocated_quantity     := 0;
5940           x_sec_allocated_quantity := 0;
5941           x_remaining_quantity     := 0;
5942           x_sec_remaining_quantity := 0;
5943           x_inserted_record        := FALSE;
5944           RETURN;
5945        END IF;
5946     END IF; --} End of 13361151
5947 
5948     -- if no available quantity, return
5949     IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_allocation_quantity <= 0)
5950        OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND (l_sallocation_quantity <= 0 OR l_allocation_quantity <= 0))
5951     THEN
5952        -- if reading from table, go to next record
5953        IF l_debug = 1 THEN
5954           log_event(l_api_name, 'zero_tree_qty', 'Available quantity ' || 'returned from quantity tree is zero');
5955        END IF;
5956        IF p_debug_on THEN
5957           g_trace_recs(p_record_id).att_qty           := l_att;
5958           g_trace_recs(p_record_id).secondary_att_qty := l_satt;
5959           g_trace_recs(p_record_id).att_qty_flag      := 'N';
5960        END IF;
5961        x_allocated_quantity     := 0;
5962        x_sec_allocated_quantity := 0;
5963        x_remaining_quantity     := 0;
5964        x_sec_remaining_quantity := 0;
5965        x_inserted_record        := FALSE;
5966        RETURN;
5967     END IF;
5968 
5969     IF p_debug_on THEN
5970        g_trace_recs(p_record_id).att_qty           := l_att;
5971        g_trace_recs(p_record_id).secondary_att_qty := l_satt;
5972        g_trace_recs(p_record_id).att_qty_flag      := 'Y';
5973     END IF;
5974 
5975     -- check to see if serial number has already been used
5976     IF (g_locs(p_record_id).serial_number IS NOT NULL
5977         AND g_locs(p_record_id).serial_number <> FND_API.G_MISS_CHAR)
5978     THEN
5979        IF l_debug = 1 THEN
5980           log_statement(l_api_name, 'search_sn', 'Calling Search Serial Numbers');
5981        END IF;
5982 
5983        inv_detail_util_pvt.search_serial_numbers(
5984          p_organization_id            => p_organization_id
5985        , p_inventory_item_id          => p_inventory_item_id
5986        , p_serial_number              => g_locs(p_record_id).serial_number
5987        , x_found                      => l_found
5988        , x_return_status              => x_return_status
5989        , x_msg_count                  => x_msg_count
5990        , x_msg_data                   => x_msg_data
5991        );
5992 
5993        IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5994           IF l_debug = 1 THEN
5995              log_statement(l_api_name, 'uerr_search_sn', 'Unexpected error in search_serial_numbers');
5996           END IF;
5997           RAISE fnd_api.g_exc_unexpected_error;
5998        ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5999           IF l_debug = 1 THEN
6000              log_statement(l_api_name, 'err_search_sn', 'Error in search_serial_numbers');
6001           END IF;
6002           RAISE fnd_api.g_exc_error;
6003        END IF;
6004 
6005        IF l_found THEN
6006           IF p_debug_on THEN
6007              g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
6008           END IF;
6009           IF l_debug = 1 THEN
6010              log_event(l_api_name, 'sn_used', 'Serial Number has been used');
6011           END IF;
6012           g_locs(p_record_id).quantity := 0;
6013           g_locs(p_record_id).secondary_quantity := 0;
6014           x_allocated_quantity     := 0;
6015           x_sec_allocated_quantity := 0;
6016           x_remaining_quantity     := 0;
6017           x_sec_remaining_quantity := 0;
6018           x_inserted_record        := FALSE;
6019           RETURN;
6020        END IF;
6021 
6022        IF p_debug_on THEN
6023           g_trace_recs(p_record_id).serial_number_used_flag  := 'Y';
6024        END IF;
6025     END IF;
6026 
6027     -- If we are factoring in Pick UOM, convert quantity into Pick UOM.
6028     -- Then, find the the largest non-decimal quantity in Pick UOM.  Convert
6029     -- back to primary UOM
6030     -- if Uom code is null, than use primary uom
6031     -- if pick uom = primary uom, skip conversions
6032 
6033     l_orig_allocation_quantity  := l_allocation_quantity;
6034     l_sorig_allocation_quantity := l_sallocation_quantity;
6035 
6036     IF l_use_pick_uom
6037        AND g_locs(p_record_id).uom_code IS NOT NULL
6038        AND ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND g_locs(p_record_id).uom_code <> p_primary_uom)
6039              OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND g_locs(p_record_id).uom_code <> p_secondary_uom) )
6040     THEN --{
6041        IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN --{
6042           -- convert from secondary uom to pick uom
6043           l_possible_uom_qty := inv_convert.inv_um_convert(
6044                                     item_id         => p_inventory_item_id
6045                                   , lot_number      => (CASE WHEN l_lot_conv_factor_flag = 0 THEN
6046                                                                   NULL
6047                                                              ELSE g_locs(p_record_id).lot_number
6048                                                              END)  -- Added for 14699845 (Flexible lot allocation)
6049                                   , organization_id => p_organization_id
6050                                   , precision       => NULL
6051                                   , from_quantity   => l_sallocation_quantity
6052                                   , from_unit       => p_secondary_uom
6053                                   , to_unit         => g_locs(p_record_id).uom_code
6054                                   , from_name       => NULL
6055                                   , to_name         => NULL);
6056 
6057           IF l_debug = 1 THEN
6058              log_statement(l_api_name, 'start_uom_conversion', 'Pick UOM possible qty: ' || l_possible_uom_qty);
6059              log_statement(l_api_name, 'start_uom_conversion', 'Pick UOM: ' || g_locs(p_record_id).uom_code);
6060           END IF;
6061 
6062           -- if no conversion defined or some error in conversion,
6063           -- inv_um_convert returns -99999.  In this case, don't carry
6064           -- out any more conversion functions.  possible quantity
6065           -- remains unchanged
6066           IF (l_possible_uom_qty <> -99999) THEN
6067              -- don't want to pick fractional amounts of pick uom
6068              l_orig_poss_uom_qty := l_possible_uom_qty;
6069              l_possible_uom_qty := FLOOR(l_possible_uom_qty);
6070 
6071              IF l_debug = 1 THEN
6072                 log_statement(l_api_name, 'to_secondary_uom', 'Pick UOM qty before rounding down: ' || l_orig_poss_uom_qty);
6073                 log_statement(l_api_name, 'to_secondary_uom', 'Pick UOM qty after rounding down: ' || l_possible_uom_qty);
6074              END IF;
6075 
6076              -- Bug 10388819: only honor pick UOM if we are not allocating
6077              -- partial quantity for an indivisible lot
6078              IF (NOT (l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1 AND l_indiv_lot_allowed = 'Y'))
6079                 OR (l_possible_uom_qty = l_orig_poss_uom_qty)
6080              THEN
6081                 l_sallocation_quantity := ROUND( (l_possible_uom_qty/l_orig_poss_uom_qty)
6082                                                  * l_sallocation_quantity, 5);
6083                 -- Added for bug 8665496
6084                 l_allocation_quantity :=
6085                       ROUND(((l_sallocation_quantity/l_sorig_allocation_quantity) * l_orig_allocation_quantity),5);
6086 
6087                 IF l_debug = 1 THEN
6088                    log_statement(l_api_name, 'after_pick_uom_convert', 'l_allocation_quantity: ' || l_allocation_quantity);
6089                    log_statement(l_api_name, 'after_pick_uom_convert', 'l_sallocation_quantity: ' || l_sallocation_quantity);
6090                 END IF;
6091              END IF;
6092           END IF;
6093        --}
6094        ELSE --{
6095           -- fulfillment base is primary
6096           -- convert from primary uom to pick uom
6097           -- 8809951 calling uom_convert from wms_cache
6098           IF (wms_engine_pvt.g_sec_qty_round_mode IS NULL
6099               OR (g_locs(p_record_id).uom_code <> p_secondary_uom))
6100           THEN --{
6101              l_possible_uom_qty := inv_convert.inv_um_convert(
6102                                        item_id         => p_inventory_item_id
6103                                      , lot_number      => (CASE WHEN l_lot_conv_factor_flag = 0 THEN
6104                                                                      NULL
6105                                                                 ELSE g_locs(p_record_id).lot_number
6106                                                                 END)  -- Added for 14699845 (Flexible lot allocation)
6107                                      , organization_id => p_organization_id
6108                                      , precision       => NULL
6109                                      , from_quantity   => l_allocation_quantity
6110                                      , from_unit       => p_primary_uom
6111                                      , to_unit         => g_locs(p_record_id).uom_code
6112                                      , from_name       => NULL
6113                                      , to_name         => NULL);
6114 
6115              IF l_debug = 1 THEN
6116                 log_statement(l_api_name, 'start_uom_conversion', 'Pick UOM possible qty: ' || l_possible_uom_qty);
6117                 log_statement(l_api_name, 'start_uom_conversion', 'Pick UOM: ' || g_locs(p_record_id).uom_code);
6118              END IF;
6119 
6120              -- if no conversion defined or some error in conversion,
6121              -- inv_um_convert returns -99999.  In this case, don't carry
6122              -- out any more conversion functions.  possible quantity
6123              -- remains unchanged
6124              IF (l_possible_uom_qty <> -99999) THEN --{
6125                 -- don't want to pick fractional amounts of pick uom
6126                 l_orig_poss_uom_qty := l_possible_uom_qty;
6127                 l_possible_uom_qty := FLOOR(l_possible_uom_qty);
6128 
6129                 IF l_debug = 1 THEN
6130                    log_statement(l_api_name, 'to_primary_uom', 'Pick UOM qty before rounding down: ' || l_orig_poss_uom_qty);
6131                    log_statement(l_api_name, 'to_primary_uom', 'Pick UOM qty after rounding down: ' || l_possible_uom_qty);
6132                 END IF;
6133 
6134                 -- Bug 10388819: only honor pick UOM if we are not allocating
6135                 -- partial quantity for an indivisible lot
6136                 IF (NOT (l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1 AND l_indiv_lot_allowed = 'Y'))
6137                    OR (l_possible_uom_qty = l_orig_poss_uom_qty)
6138                 THEN
6139                    l_allocation_quantity := ROUND( (l_possible_uom_qty/l_orig_poss_uom_qty)
6140                                                    * l_allocation_quantity, 5);
6141                    -- Added for bug 8665496
6142                    l_sallocation_quantity :=
6143                          ROUND(((l_allocation_quantity/l_orig_allocation_quantity) * l_sorig_allocation_quantity),5);
6144 
6145                    IF l_debug = 1 THEN
6146                       log_statement(l_api_name, 'after_pick_uom_convert', 'l_allocation_quantity: ' || l_allocation_quantity);
6147                       log_statement(l_api_name, 'after_pick_uom_convert', 'l_sallocation_quantity: ' || l_sallocation_quantity);
6148                    END IF;
6149                 END IF;
6150              END IF; --} UOM conversion <> -99999
6151           END IF; --} sec qty rounding
6152        END IF; --} g_fulfillment_base
6153     END IF; --} l_use_pick_uom
6154 
6155     -- populate remaining quantity
6156     x_remaining_quantity     := l_orig_allocation_quantity - l_allocation_quantity;
6157     x_sec_remaining_quantity := l_sorig_allocation_quantity - l_sallocation_quantity;
6158 
6159     IF l_debug = 1 THEN
6160        log_statement(l_api_name, 'rem_qty', 'remaining quantity : ' || x_remaining_quantity);
6161        log_statement(l_api_name, 'rem_qty', 'remaining sec qty : ' || x_sec_remaining_quantity);
6162     END IF;
6163 
6164     IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_allocation_quantity <= 0)
6165        OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sallocation_quantity <= 0)
6166     THEN
6167        IF l_debug = 1 THEN
6168           log_statement(l_api_name, 'no_alloc_qty', 'Quantity remaining to allocate.  Exiting.');
6169        END IF;
6170        x_allocated_quantity      := 0;
6171        x_sec_allocated_quantity  := 0;
6172        x_inserted_record         := FALSE;
6173        RETURN;
6174     END IF;
6175 
6176     -- Lock Serial number, so that no other detailing process
6177     -- can use it.
6178     IF (g_locs(p_record_id).serial_number IS NOT NULL
6179         AND g_locs(p_record_id).serial_number <> FND_API.G_MISS_CHAR)
6180     THEN
6181        l_found  := inv_detail_util_pvt.lock_serial_number(p_inventory_item_id, g_locs(p_record_id).serial_number);
6182 
6183        IF l_found = FALSE THEN
6184           IF l_debug = 1 THEN
6185              log_statement(l_api_name, 'lock_sn', 'Could not lock Serial Number. Exiting.');
6186           END IF;
6187 
6188           IF p_debug_on THEN
6189              g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
6190           END IF;
6191 
6192           x_remaining_quantity  := g_locs(p_record_id).quantity;
6193           x_allocated_quantity  := 0;
6194           x_sec_remaining_quantity  := null;
6195           x_sec_allocated_quantity  := null;
6196           x_inserted_record     := FALSE;
6197           RETURN;
6198        END IF;
6199 
6200        -- add serial number to pl/sql table of detailed serials
6201        inv_detail_util_pvt.add_serial_number(
6202            p_inventory_item_id
6203          , p_organization_id
6204          , g_locs(p_record_id).serial_number
6205          , l_serial_index
6206          );
6207     END IF;
6208 
6209     -- Update quantity tree for this suggested quantity
6210     IF l_debug = 1 THEN
6211        log_statement(l_api_name, 'update_tree', 'Updating qty tree');
6212     END IF;
6213 
6214     inv_quantity_tree_pvt.update_quantities(
6215         p_api_version_number         => g_qty_tree_api_version
6216       , p_init_msg_lst               => fnd_api.g_false
6217       , x_return_status              => x_return_status
6218       , x_msg_count                  => x_msg_count
6219       , x_msg_data                   => x_msg_data
6220       , p_tree_id                    => p_tree_id
6221       , p_revision                   => g_locs(p_record_id).revision
6222       , p_lot_number                 => g_locs(p_record_id).lot_number
6223       , p_subinventory_code          => g_locs(p_record_id).subinventory_code
6224       , p_locator_id                 => g_locs(p_record_id).locator_id
6225       , p_primary_quantity           => l_allocation_quantity
6226       , p_secondary_quantity         => l_sallocation_quantity                 -- INVCONV
6227       , p_quantity_type              => inv_quantity_tree_pvt.g_qs_txn
6228       , x_qoh                        => l_qoh
6229       , x_rqoh                       => l_rqoh
6230       , x_qr                         => l_qr
6231       , x_qs                         => l_qs
6232       , x_att                        => l_att
6233       , x_atr                        => l_atr
6234       , x_sqoh                       => l_sqoh                                 -- INVCONV
6235       , x_srqoh                      => l_srqoh                                -- INVCONV
6236       , x_sqr                        => l_sqr                                  -- INVCONV
6237       , x_sqs                        => l_sqs                                  -- INVCONV
6238       , x_satt                       => l_satt                                 -- INVCONV
6239       , x_satr                       => l_satr                                 -- INVCONV
6240       , p_transfer_subinventory_code => p_to_subinventory_code
6241       , p_cost_group_id              => g_locs(p_record_id).cost_group_id
6242       , p_lpn_id                     => g_locs(p_record_id).lpn_id
6243       );
6244 
6245     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6246        IF l_debug = 1 THEN
6247           log_statement(l_api_name, 'uerr_update_qty', 'Unexpected error in inv_quantity_tree_pvt.update_quantities');
6248        END IF;
6249 
6250        RAISE fnd_api.g_exc_unexpected_error;
6251     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6252        IF l_debug = 1 THEN
6253           log_statement(l_api_name, 'err_update_qty', 'Error in inv_quantity_tree_pvt.update_quantities');
6254        END IF;
6255        RAISE fnd_api.g_exc_error;
6256     END IF;
6257 
6258     -- If quantity remaining to allocate is greater than 0, update the
6259     -- quantity tree and insert the record into WTT
6260     IF p_transaction_uom = p_primary_uom THEN
6261        l_possible_trx_qty := l_allocation_quantity;
6262     ELSIF p_transaction_uom = p_secondary_uom THEN
6263        l_possible_trx_qty := l_sallocation_quantity;
6264     ELSE
6265        IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
6266           l_possible_trx_qty := inv_convert.inv_um_convert(
6267                                     item_id         => p_inventory_item_id
6268                                   , lot_number      => (CASE WHEN l_lot_conv_factor_flag = 0 THEN
6269                                                                   NULL
6270                                                              ELSE g_locs(p_record_id).lot_number
6271                                                              END)  -- Added for 14699845 (Flexible lot allocation)
6272                                   , organization_id => p_organization_id
6273                                   , precision       => NULL
6274                                   , from_quantity   => l_sallocation_quantity
6275                                   , from_unit       => p_secondary_uom
6276                                   , to_unit         => p_transaction_uom
6277                                   , from_name       => NULL
6278                                   , to_name         => NULL
6279                                   );
6280        ELSE
6281           l_possible_trx_qty := inv_convert.inv_um_convert(
6282                                     item_id         => p_inventory_item_id
6283                                   , lot_number      => (CASE WHEN l_lot_conv_factor_flag = 0 THEN
6284                                                                   NULL
6285                                                              ELSE g_locs(p_record_id).lot_number
6286                                                              END)  -- Added for 14699845 (Flexible lot allocation)
6287                                   , organization_id => p_organization_id
6288                                   , precision       => NULL
6289                                   , from_quantity   => l_allocation_quantity
6290                                   , from_unit       => p_primary_uom
6291                                   , to_unit         => p_transaction_uom
6292                                   , from_name       => NULL
6293                                   , to_name         => NULL
6294                                   );
6295        END IF;
6296     END IF;
6297     l_sec_possible_trx_qty := l_sallocation_quantity;
6298 
6299     IF l_debug = 1 THEN
6300        log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Trx Qty: ' || l_possible_trx_qty);
6301        log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Sec Trx Qty: ' || l_sec_possible_trx_qty);
6302     END IF;
6303 
6304     -- Added for 14699845 (Flexible lot allocation)
6305     IF l_allocate_lot_flag = 'Y'
6306        OR l_lot_control_code = 1
6307        OR p_simulation_mode = wms_engine_pvt.g_no_simulation
6308     THEN
6309        -- insert temporary suggestion
6310        INSERT INTO wms_transactions_temp
6311                  ( pp_transaction_temp_id
6312                  , transaction_temp_id
6313                  , type_code
6314                  , line_type_code
6315                  , transaction_quantity
6316                  , primary_quantity
6317                  , secondary_quantity
6318                  , grade_code
6319                  , revision
6320                  , lot_number
6321                  , lot_expiration_date
6322                  , from_subinventory_code
6323                  , from_locator_id
6324                  , rule_id
6325                  , reservation_id
6326                  , serial_number
6327                  , to_subinventory_code
6328                  , to_locator_id
6329                  , from_cost_group_id
6330                  , to_cost_group_id
6331                  , lpn_id
6332                  )
6333           VALUES ( wms_transactions_temp_s.NEXTVAL
6334                  , p_transaction_temp_id
6335                  , p_type_code
6336                  , 2 -- line type code is output
6337                  , l_possible_trx_qty
6338                  , l_allocation_quantity
6339                  , l_sallocation_quantity
6340                  , g_locs(p_record_id).grade_code
6341                  , g_locs(p_record_id).revision
6342                  , g_locs(p_record_id).lot_number
6343                  , g_locs(p_record_id).lot_expiration_date
6344                  , g_locs(p_record_id).subinventory_code
6345                  , g_locs(p_record_id).locator_id
6346                  , p_rule_id
6347                  , p_reservation_id
6348                  , g_locs(p_record_id).serial_number
6349                  , p_to_subinventory_code
6350                  , l_to_locator_id
6351                  , g_locs(p_record_id).cost_group_id
6352                  , p_to_cost_group_id
6353                  , g_locs(p_record_id).lpn_id
6354                  );
6355     ELSE
6356        -- Start changes for 14699845 (Flexible lot allocation)
6357        BEGIN
6358           SELECT pp_transaction_temp_id
6359           INTO l_transaction_temp_id
6360           FROM wms_transactions_temp
6361           WHERE transaction_temp_id = p_transaction_temp_id
6362             AND type_code = p_type_code
6363             AND line_type_code = 2
6364             AND NVL(grade_code, '-9999') = NVL(g_locs(p_record_id).grade_code, '-9999')
6365             AND NVL(revision, '-99') = NVL(g_locs(p_record_id).revision, '-99')
6366             AND lot_number IS NULL
6367             AND lot_expiration_date IS NULL
6368             AND NVL(from_subinventory_code, '@@@@') = NVL(g_locs(p_record_id).subinventory_code, '@@@@')
6369             AND NVL(from_locator_id, '-9999') = NVL(g_locs(p_record_id).locator_id, '-9999')
6370             AND rule_id =  p_rule_id
6371             AND NVL(reservation_id, '-9999') = NVL(p_reservation_id, '-9999')
6372             AND serial_number IS NULL
6373             AND NVL(to_subinventory_code, '@@@@') = NVL(p_to_subinventory_code, '@@@@')
6374             AND NVL(to_locator_id, '-9999') = NVL(l_to_locator_id, '-9999')
6375             AND NVL(from_cost_group_id, '-9999') = NVL(g_locs(p_record_id).cost_group_id, '-9999')
6376             AND NVL(to_cost_group_id, '-9999') = NVL(p_to_cost_group_id, '-9999')
6377             AND NVL(lpn_id, '-9999') = NVL(g_locs(p_record_id).lpn_id, '-9999')
6378             AND ROWNUM < 2;
6379 
6380           UPDATE wms_transactions_temp
6381              SET transaction_quantity = NVL(transaction_quantity, 0) + NVL(l_possible_trx_qty, 0),
6382                  primary_quantity = NVL(primary_quantity, 0) + NVL(l_allocation_quantity, 0),
6383                  secondary_quantity = NVL(secondary_quantity, 0) + NVL(l_sallocation_quantity, 0)
6384            WHERE pp_transaction_temp_id = l_transaction_temp_id;
6385        EXCEPTION
6386          WHEN NO_DATA_FOUND THEN
6387               INSERT INTO wms_transactions_temp
6388                         ( pp_transaction_temp_id
6389                         , transaction_temp_id
6390                         , type_code
6391                         , line_type_code
6392                         , transaction_quantity
6393                         , primary_quantity
6394                         , secondary_quantity
6395                         , grade_code
6396                         , revision
6397                         , lot_number
6398                         , lot_expiration_date
6399                         , from_subinventory_code
6400                         , from_locator_id
6401                         , rule_id
6402                         , reservation_id
6403                         , serial_number
6404                         , to_subinventory_code
6405                         , to_locator_id
6406                         , from_cost_group_id
6407                         , to_cost_group_id
6408                         , lpn_id
6409                         )
6410                  VALUES ( wms_transactions_temp_s.NEXTVAL
6411                         , p_transaction_temp_id
6412                         , p_type_code
6413                         , 2 -- line type code is output
6414                         , l_possible_trx_qty
6415                         , l_allocation_quantity
6416                         , l_sallocation_quantity
6417                         , g_locs(p_record_id).grade_code
6418                         , g_locs(p_record_id).revision
6419                         , NULL
6420                         , NULL
6421                         , g_locs(p_record_id).subinventory_code
6422                         , g_locs(p_record_id).locator_id
6423                         , p_rule_id
6424                         , p_reservation_id
6425                         , NULL --g_locs(p_record_id).serial_number
6426                         , p_to_subinventory_code
6427                         , l_to_locator_id
6428                         , g_locs(p_record_id).cost_group_id
6429                         , p_to_cost_group_id
6430                         , g_locs(p_record_id).lpn_id
6431                         );
6432        END;
6433     END IF;
6434 
6435     -- End changes for 14699845 (Flexible lot allocation)
6436 
6437     IF l_debug = 1 THEN
6438        log_statement(l_api_name, 'finish_insert_wtt', 'Finished inserting wtt recs.');
6439        log_statement(l_api_name, 'alloc_qty', 'Alloc qty: ' || l_allocation_quantity);
6440        log_statement(l_api_name, 'sec_alloc_qty', 'sec_Alloc qty: ' || l_sallocation_quantity);
6441     END IF;
6442 
6443     -- Bug 8665496: update remaining qty to allocate
6444     IF l_rsv_id > 0 AND g_alloc_qty.EXISTS(l_rsv_id) AND g_sec_alloc_qty.EXISTS(l_rsv_id)
6445     THEN
6446        g_alloc_qty(l_rsv_id) := g_alloc_qty(l_rsv_id) - l_allocation_quantity;
6447        g_sec_alloc_qty(l_rsv_id) := g_sec_alloc_qty(l_rsv_id) - l_sallocation_quantity;
6448        IF l_debug = 1 THEN
6449           log_statement(l_api_name, 'g_alloc_qty', 'Remaining alloc qty: '
6450                                      || g_alloc_qty(l_rsv_id));
6451            log_statement(l_api_name, 'g_sec_alloc_qty', 'Remaining rsv sec alloc qty: '
6452                                      || g_sec_alloc_qty(l_rsv_id));
6453        END IF;
6454     END IF;
6455 
6456     IF p_debug_on THEN
6457        g_trace_recs(p_record_id).suggested_qty  := l_allocation_quantity;
6458        g_trace_recs(p_record_id).secondary_suggested_qty  := l_sallocation_quantity;
6459     END IF;
6460 
6461     x_inserted_record           := TRUE;
6462     x_allocated_quantity        := l_allocation_quantity;
6463     x_sec_allocated_quantity    := l_sallocation_quantity;
6464 
6465     IF l_debug = 1 THEN
6466        log_statement(l_api_name, 'alloc_qty', 'Allocated quantity: ' || x_allocated_quantity);
6467        log_statement(l_api_name, 'sec_alloc_qty', 'sec_Allocated quantity: ' || x_sec_allocated_quantity);
6468        log_procedure(l_api_name, 'end', 'End Validate_and_Insert');
6469     END IF;
6470 
6471   EXCEPTION
6472     WHEN fnd_api.g_exc_error THEN
6473       x_return_status  := fnd_api.g_ret_sts_error;
6474       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6475       --
6476       IF l_debug = 1 THEN
6477          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
6478       END IF;
6479 
6480     WHEN fnd_api.g_exc_unexpected_error THEN
6481       x_return_status  := fnd_api.g_ret_sts_unexp_error;
6482       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6483       IF l_debug = 1 THEN
6484          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
6485       END IF;
6486 
6487     WHEN OTHERS THEN
6488       x_return_status  := fnd_api.g_ret_sts_unexp_error;
6489 
6490       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6491         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
6492       END IF;
6493 
6494       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6495       IF l_debug = 1 THEN
6496          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
6497       END IF;
6498 
6499   END validate_and_insert;
6500 
6501 
6502   -- Overloaded for 14699845 (Flexible lot allocation)
6503   PROCEDURE validate_and_insert(
6504     x_return_status          OUT NOCOPY    VARCHAR2
6505   , x_msg_count              OUT NOCOPY    NUMBER
6506   , x_msg_data               OUT NOCOPY    VARCHAR2
6507   , p_record_id              IN            NUMBER
6508   , p_needed_quantity        IN            NUMBER
6509   , p_use_pick_uom           IN            BOOLEAN
6510   , p_organization_id        IN            NUMBER
6511   , p_inventory_item_id      IN            NUMBER
6512   , p_to_subinventory_code   IN            VARCHAR2
6513   , p_to_locator_id          IN            NUMBER
6514   , p_to_cost_group_id       IN            NUMBER
6515   , p_primary_uom            IN            VARCHAR2
6516   , p_transaction_uom        IN            VARCHAR2
6517   , p_transaction_temp_id    IN            NUMBER
6518   , p_type_code              IN            NUMBER
6519   , p_rule_id                IN            NUMBER
6520   , p_reservation_id         IN            NUMBER
6521   , p_tree_id                IN            NUMBER
6522   , p_debug_on               IN            BOOLEAN
6523   , p_needed_sec_quantity    IN            NUMBER
6524   , p_secondary_uom          IN            VARCHAR2
6525   , p_grade_code             IN            VARCHAR2
6526   , x_inserted_record        OUT NOCOPY    BOOLEAN
6527   , x_allocated_quantity     OUT NOCOPY    NUMBER
6528   , x_remaining_quantity     OUT NOCOPY    NUMBER
6529   , x_sec_allocated_quantity OUT NOCOPY    NUMBER
6530   , x_sec_remaining_quantity OUT NOCOPY    NUMBER
6531   ) IS
6532   BEGIN
6533      validate_and_insert(
6534         x_return_status          =>   x_return_status
6535       , x_msg_count              =>   x_msg_count
6536       , x_msg_data               =>   x_msg_data
6537       , p_record_id              =>   p_record_id
6538       , p_needed_quantity        =>   p_needed_quantity
6539       , p_use_pick_uom           =>   p_use_pick_uom
6540       , p_organization_id        =>   p_organization_id
6541       , p_inventory_item_id      =>   p_inventory_item_id
6542       , p_to_subinventory_code   =>   p_to_subinventory_code
6543       , p_to_locator_id          =>   p_to_locator_id
6544       , p_to_cost_group_id       =>   p_to_cost_group_id
6545       , p_primary_uom            =>   p_primary_uom
6546       , p_transaction_uom        =>   p_transaction_uom
6547       , p_transaction_temp_id    =>   p_transaction_temp_id
6548       , p_type_code              =>   p_type_code
6549       , p_rule_id                =>   p_rule_id
6550       , p_reservation_id         =>   p_reservation_id
6551       , p_tree_id                =>   p_tree_id
6552       , p_debug_on               =>   p_debug_on
6553       , p_needed_sec_quantity    =>   p_needed_sec_quantity
6554       , p_secondary_uom          =>   p_secondary_uom
6555       , p_grade_code             =>   p_grade_code
6556       , p_orig_needed_quantity   =>   p_needed_quantity
6557       , p_orig_needed_sec_qty    =>   p_needed_sec_quantity
6558       , p_simulation_mode        =>   wms_engine_pvt.g_no_simulation
6559       , x_inserted_record        =>   x_inserted_record
6560       , x_allocated_quantity     =>   x_allocated_quantity
6561       , x_remaining_quantity     =>   x_remaining_quantity
6562       , x_sec_allocated_quantity =>   x_sec_allocated_quantity
6563       , x_sec_remaining_quantity =>   x_sec_remaining_quantity );
6564   END validate_and_insert;
6565 
6566 
6567   --- Added the following procedure for bug #4006426
6568 
6569   -- This procedure is used to get the quantity available to transact
6570   -- for a sub-transfer from a non-reservable subinventory.
6571   -- It assumed that pending transactions only exist at locator and lpn level
6572   -- The quantity is calculated with onhand quantity from
6573   -- MTL_ONHAND_QUANTITIES_DETAIL and pending transactions from
6574   -- MTL_MATERIAL_TRANSACTIONS_TEMP
6575   -- First get onhand and pending transactions at LPN level
6576   -- If LPN level availability > 0 then get pending transactions at Locator level
6577   -- return onhand less pending transactions
6578   -- NOTES :-
6579   -- 1) The quantities calculated do not include suggestions
6580   -- 2) Transfer SUB and locator are not needed in this query as this should be used
6581   --    only to get availability in a locator controlled SUB.
6582   -- 3) LOT expiration dates are not considered as this is to be used only for inventory moves
6583 
6584  PROCEDURE get_avail_qty_for_xfer
6585  (   p_organization_id        IN  NUMBER
6586     ,  p_inventory_item_id    IN  NUMBER
6587     ,  p_revision             IN  VARCHAR2
6588     ,  p_lot_number           IN  VARCHAR2
6589     ,  p_subinventory_code    IN  VARCHAR2
6590     ,  p_locator_id           IN  NUMBER
6591     ,  p_lpn_id               IN  NUMBER
6592     ,  x_qoh                  OUT NOCOPY NUMBER
6593     ,  x_att                  OUT NOCOPY NUMBER
6594     ,  x_return_status        OUT NOCOPY VARCHAR2
6595     ,  x_msg_count            OUT NOCOPY NUMBER
6596     ,  x_msg_data             OUT NOCOPY VARCHAR2
6597  )
6598  AS
6599  l_qoh     NUMBER;
6600  l_att     NUMBER;
6601  l_lpn_qoh   NUMBER;
6602  l_lpn_att   NUMBER;
6603  l_loc_qoh   NUMBER;
6604  l_loc_att   NUMBER;
6605  l_moq_qty   NUMBER;
6606  l_mmtt_qty_src  NUMBER;
6607  l_mmtt_qty_dest  NUMBER;
6608 
6609  l_debug  NUMBER := 1;
6610 
6611  BEGIN
6612 
6613    IF(l_debug=1) THEN
6614       inv_log_util.trace('Inside :GET_AVAIL_QTY_FOR_XFER '  , 'Start', 9);
6615       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_organization_id :'||p_organization_id, 9);
6616       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_inventory_item_id :'||p_inventory_item_id, 9);
6617       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_revision :'||p_revision, 9);
6618       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_subinventory_code :'||p_subinventory_code, 9);
6619       inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_lot_number :'||p_lot_number, 9);
6620        inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER '  , 'p_lpn_id :'||p_lpn_id, 9);
6621   END IF;
6622 
6623    IF p_lpn_id IS NOT NULL THEN
6624      -- LPN level
6625        SELECT SUM(moq.primary_transaction_quantity)
6626        INTO   l_moq_qty
6627        FROM   mtl_onhand_quantities_detail moq
6628        WHERE  moq.organization_id = p_organization_id
6629        AND    moq.inventory_item_id = p_inventory_item_id
6630        AND    nvl(moq.revision,'@@') = nvl(p_revision,'@@')
6631        AND    moq.subinventory_code = p_subinventory_code
6632        AND    decode(p_lot_number,null,'@@',moq.lot_number) = nvl(p_lot_number,'@@')
6633        AND    moq.locator_id = p_locator_id
6634        AND    moq.lpn_id = p_lpn_id;
6635 
6636        IF(l_debug=1) THEN
6637          inv_log_util.trace('Total MOQ quantity LPN Level: ' || to_char(l_moq_qty), 'GET_AVAIL_QTY_FOR_XFER', 9);
6638        END IF;
6639 
6640        SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
6641                  Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
6642                        Sign(mmtt.primary_quantity)))
6643                * round(Abs(mmtt.primary_quantity),5))
6644        INTO   l_mmtt_qty_src
6645        FROM   mtl_material_transactions_temp mmtt
6646        WHERE  mmtt.organization_id = p_organization_id
6647        AND    mmtt.inventory_item_id = p_inventory_item_id
6648        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
6649        AND    mmtt.subinventory_code = p_subinventory_code
6650        AND    mmtt.locator_id = p_locator_id
6651        AND    NVL(mmtt.content_lpn_id,mmtt.transfer_lpn_id) = p_lpn_id
6652        AND    mmtt.posting_flag = 'Y'
6653        AND    mmtt.subinventory_code IS NOT NULL
6654        AND (Nvl(mmtt.transaction_status,0) <> 2 OR
6655                Nvl(mmtt.transaction_status,0) = 2 AND
6656                mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
6657               )
6658        AND    mmtt.transaction_action_id NOT IN (5,6,24,30);
6659 
6660        IF(l_debug=1) THEN
6661            inv_log_util.trace('Total MMTT Trx quantity Source Org Sub : ' || to_char(l_mmtt_qty_src), 'GET_AVAIL_QTY_FOR_XFER', 9);
6662        END IF;
6663 
6664        SELECT SUM(Abs(mmtt.primary_quantity))
6665        INTO   l_mmtt_qty_dest
6666        FROM   mtl_material_transactions_temp mmtt
6667        WHERE  decode(mmtt.transaction_action_id,3,
6668                mmtt.transfer_organization,mmtt.organization_id) = p_organization_id
6669        AND    mmtt.inventory_item_id = p_inventory_item_id
6670        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
6671        AND    mmtt.transfer_subinventory = p_subinventory_code
6672        AND    mmtt.transfer_to_location = p_locator_id
6673        AND    NVL(mmtt.content_lpn_id,mmtt.transfer_lpn_id) = p_lpn_id
6674        AND    mmtt.posting_flag = 'Y'
6675        AND    Nvl(mmtt.transaction_status,0) <> 2
6676        AND    mmtt.transaction_action_id  in (2,28,3)
6677        AND    mmtt.wip_supply_type IS NULL;
6678 
6679        IF(l_debug=1) THEN
6680            inv_log_util.trace('Total MMTT Trx quantity Dest Org Sub : ' || to_char(l_mmtt_qty_dest), 'GET_AVAIL_QTY_FOR_XFER', 9);
6681        END IF;
6682 
6683        l_lpn_qoh :=  nvl(l_moq_qty,0);
6684        l_lpn_att :=  nvl(l_moq_qty,0) + nvl(l_mmtt_qty_src,0) + nvl(l_mmtt_qty_dest,0);
6685 
6686     END IF;
6687 
6688     -- Only check onhand and pending at locator level if there is availability at LPN
6689     -- or no lpn passed in
6690     IF (nvl(l_lpn_att,0) > 0)  OR (p_lpn_id IS NULL) THEN
6691 
6692        SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
6693                  Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
6694                        Sign(mmtt.primary_quantity)))
6695                * round(Abs(mmtt.primary_quantity),5))
6696        INTO   l_mmtt_qty_src
6697        FROM   mtl_material_transactions_temp mmtt
6698        WHERE  mmtt.organization_id = p_organization_id
6699        AND    mmtt.inventory_item_id = p_inventory_item_id
6700        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
6701        AND    mmtt.subinventory_code = p_subinventory_code
6702        AND    mmtt.locator_id = p_locator_id
6703        AND    mmtt.posting_flag = 'Y'
6704        AND    mmtt.subinventory_code IS NOT NULL
6705        AND (Nvl(mmtt.transaction_status,0) <> 2 OR
6706                Nvl(mmtt.transaction_status,0) = 2 AND
6707                mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
6708               )
6709        AND    mmtt.transaction_action_id NOT IN (5,6,24,30);
6710 
6711        IF(l_debug=1) THEN
6712            inv_log_util.trace('Total MMTT Trx quantity Source Org Sub : ' || to_char(l_mmtt_qty_src), 'GET_AVAIL_QTY_FOR_XFER', 9);
6713        END IF;
6714 
6715        SELECT SUM(moq.primary_transaction_quantity)
6716        INTO   l_moq_qty
6717        FROM   mtl_onhand_quantities_detail moq
6718        WHERE  moq.organization_id = p_organization_id
6719        AND    moq.inventory_item_id = p_inventory_item_id
6720        AND    nvl(moq.revision,'@@') = nvl(p_revision,'@@')
6721        AND    moq.subinventory_code = p_subinventory_code
6722        AND    decode(p_lot_number,null,'@@',moq.lot_number) = nvl(p_lot_number,'@@')
6723        AND    moq.locator_id = p_locator_id;
6724 
6725        IF(l_debug=1) THEN
6726          inv_log_util.trace('Total MOQ quantity LPN Level: ' || to_char(l_moq_qty), 'GET_AVAIL_QTY_FOR_XFER', 9);
6727        END IF;
6728 
6729        SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
6730                  Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
6731                        Sign(mmtt.primary_quantity)))
6732                * round(Abs(mmtt.primary_quantity),5))
6733        INTO   l_mmtt_qty_src
6734        FROM   mtl_material_transactions_temp mmtt
6735        WHERE  mmtt.organization_id = p_organization_id
6736        AND    mmtt.inventory_item_id = p_inventory_item_id
6737        AND    nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
6738        AND    mmtt.subinventory_code = p_subinventory_code
6739        AND    mmtt.locator_id = p_locator_id
6740        AND    mmtt.posting_flag = 'Y'
6741        AND    mmtt.subinventory_code IS NOT NULL
6742        AND (Nvl(mmtt.transaction_status,0) <> 2 OR
6743                Nvl(mmtt.transaction_status,0) = 2 AND
6744                mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
6745               )
6746        AND    mmtt.transaction_action_id NOT IN (5,6,24,30);
6747        l_loc_qoh :=  nvl(l_moq_qty,0);
6748        l_loc_att :=  nvl(l_moq_qty,0) + nvl(l_mmtt_qty_src,0) + nvl(l_mmtt_qty_dest,0);
6749     END IF;
6750 
6751 
6752     -- Quantity available for transfer is the minimum of availability at LPN and locator levels
6753     IF p_lpn_id IS NULL THEN
6754         x_qoh := l_loc_qoh;
6755         x_att := l_loc_att;
6756     ELSE
6757       x_qoh := l_lpn_qoh;
6758       IF nvl(l_lpn_att,0) > nvl(l_loc_att,0) THEN
6759          x_att := l_loc_att;
6760       ELSE
6761          x_att := l_lpn_att;
6762       END IF;
6763     END IF;
6764 
6765     IF(l_debug=1) THEN
6766         inv_log_util.trace('Total quantity on-hand: ' || to_char(l_qoh), 'GET_AVAIL_QTY_FOR_XFER', 9);
6767     END IF;
6768  END GET_AVAIL_QTY_FOR_XFER;
6769 
6770 
6771   ---
6772    PROCEDURE ValidNinsert(
6773         x_return_status        OUT NOCOPY    VARCHAR2
6774       , x_msg_count            OUT NOCOPY    NUMBER
6775       , x_msg_data             OUT NOCOPY    VARCHAR2
6776       , p_record_id            IN            NUMBER
6777       , p_needed_quantity      IN            NUMBER
6778       , p_use_pick_uom         IN            BOOLEAN
6779       , p_organization_id      IN            NUMBER
6780       , p_inventory_item_id    IN            NUMBER
6781       , p_to_subinventory_code IN            VARCHAR2
6782       , p_to_locator_id        IN            NUMBER
6783       , p_to_cost_group_id     IN            NUMBER
6784       , p_primary_uom          IN            VARCHAR2
6785       , p_transaction_uom      IN            VARCHAR2
6786       , p_transaction_temp_id  IN            NUMBER
6787       , p_type_code            IN            NUMBER
6788       , p_rule_id              IN            NUMBER
6789       , p_reservation_id       IN            NUMBER
6790       , p_tree_id              IN            NUMBER
6791       , p_debug_on             IN            BOOLEAN
6792       , x_inserted_record      OUT NOCOPY    BOOLEAN
6793       , x_allocated_quantity   OUT NOCOPY    NUMBER
6794       , x_remaining_quantity   OUT NOCOPY    NUMBER
6795       ) IS
6796         l_api_name                 VARCHAR2(30) := 'validate_N_insert';
6797         l_att                      NUMBER;
6798         l_qoh                      NUMBER;
6799         l_allocation_quantity      NUMBER;
6800         l_orig_allocation_quantity NUMBER;
6801         l_found                    BOOLEAN;
6802         l_possible_uom_qty         NUMBER;
6803         l_possible_trx_qty         NUMBER;
6804         l_serial_index             NUMBER;
6805 
6806         l_debug                   NUMBER;
6807 
6808       BEGIN
6809         IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
6810            g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6811         END IF;
6812         l_debug := g_debug;
6813 
6814         x_return_status             := fnd_api.g_ret_sts_success;
6815         l_allocation_quantity       := p_needed_quantity;
6816 
6817         IF l_debug = 1 THEN
6818            log_procedure(l_api_name, 'start', 'Start Validate_N_Insert');
6819            log_statement(l_api_name, 'needed_quantity', 'needed quantity: ' || p_needed_quantity);
6820            log_statement(l_api_name, 'rec_id', 'p_record_id: ' || p_record_id);
6821         END IF;
6822 
6823          IF l_allocation_quantity > g_locs(p_record_id).quantity THEN
6824           l_allocation_quantity  := g_locs(p_record_id).quantity;
6825           log_statement(l_api_name, 'record_quantity', 'record quantity: ' || l_allocation_quantity);
6826         END IF;
6827 
6828        GET_AVAIL_QTY_FOR_XFER(
6829                 p_organization_id             => p_organization_id
6830              ,  p_inventory_item_id           => p_inventory_item_id
6831              ,  p_revision                 => g_locs(p_record_id).revision
6832              ,  p_lot_number                  => g_locs(p_record_id).lot_number
6833              ,  p_subinventory_code          => g_locs(p_record_id).subinventory_code
6834              ,  p_locator_id                   => g_locs(p_record_id).locator_id
6835              ,  p_lpn_id                     => g_locs(p_record_id).lpn_id
6836              ,  x_qoh                         => l_qoh
6837              ,  x_att                          => l_att
6838              ,  x_return_status         => x_return_status
6839              ,  x_msg_count             => x_msg_count
6840                  ,  x_msg_data              => x_msg_data   );
6841 
6842 
6843         IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6844               IF l_debug = 1 THEN
6845                  log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
6846               END IF;
6847               RAISE fnd_api.g_exc_unexpected_error;
6848             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6849               IF l_debug = 1 THEN
6850                  log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
6851               END IF;
6852               RAISE fnd_api.g_exc_error;
6853         END IF;
6854 
6855         IF l_debug = 1 THEN
6856           log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
6857         END IF;
6858         --update record quantity
6859         IF l_att < g_locs(p_record_id).quantity THEN
6860           g_locs(p_record_id).quantity  := l_att;
6861         END IF;
6862 
6863         --update possible allocate quantity
6864         IF l_att < l_allocation_quantity THEN
6865           l_allocation_quantity  := l_att;
6866           IF l_debug = 1 THEN
6867              log_statement(l_api_name, 'tAvailable_qty', 'ATT < possible quantity.  New possible qty: ' || g_locs(p_record_id).quantity);
6868           END IF;
6869         END IF;
6870 
6871         --if no available quantity, return
6872         IF l_allocation_quantity <= 0 THEN
6873           --if reading from table, go to next record
6874           IF l_debug = 1 THEN
6875              log_event(l_api_name, 'zero_tree_qty', 'Available quantity ' || 'returned from quantity tree is zero');
6876           END IF;
6877 
6878           IF p_debug_on THEN
6879             g_trace_recs(p_record_id).att_qty       := l_att;
6880             g_trace_recs(p_record_id).att_qty_flag  := 'N';
6881           END IF;
6882 
6883           x_allocated_quantity  := 0;
6884           x_remaining_quantity  := 0;
6885           x_inserted_record     := FALSE;
6886           RETURN;
6887         END IF;
6888 
6889         IF p_debug_on THEN
6890           g_trace_recs(p_record_id).att_qty       := l_att;
6891           g_trace_recs(p_record_id).att_qty_flag  := 'Y';
6892         END IF;
6893 
6894         --check to see if serial number has already been used
6895         IF g_locs(p_record_id).serial_number IS NOT NULL THEN
6896           IF l_debug = 1 THEN
6897              log_statement(l_api_name, 'search_sn', 'Calling Search Serial Numbers');
6898           END IF;
6899 
6900           inv_detail_util_pvt.search_serial_numbers(
6901             p_organization_id            => p_organization_id
6902           , p_inventory_item_id          => p_inventory_item_id
6903           , p_serial_number              => g_locs(p_record_id).serial_number
6904           , x_found                      => l_found
6905           , x_return_status              => x_return_status
6906           , x_msg_count                  => x_msg_count
6907           , x_msg_data                   => x_msg_data
6908           );
6909 
6910           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6911             IF l_debug = 1 THEN
6912                log_statement(l_api_name, 'uerr_search_sn', 'Unexpected error in search_serial_numbers');
6913             END IF;
6914             RAISE fnd_api.g_exc_unexpected_error;
6915           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6916             IF l_debug = 1 THEN
6917                log_statement(l_api_name, 'err_search_sn', 'Error in search_serial_numbers');
6918             END IF;
6919             RAISE fnd_api.g_exc_error;
6920           END IF;
6921 
6922           IF l_found THEN
6923             IF p_debug_on THEN
6924               g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
6925             END IF;
6926             IF l_debug = 1 THEN
6927                log_event(l_api_name, 'sn_used', 'Serial Number has been used');
6928             END IF;
6929             g_locs(p_record_id).quantity  := 0;
6930             x_allocated_quantity          := 0;
6931             x_remaining_quantity          := 0;
6932             x_inserted_record             := FALSE;
6933             RETURN;
6934           END IF;
6935 
6936           IF p_debug_on THEN
6937             g_trace_recs(p_record_id).serial_number_used_flag  := 'Y';
6938           END IF;
6939         END IF;
6940 
6941         --If we are factoring in Pick UOM, convert quantity into Pick UOM.
6942         --Then, find the the largest non-decimal quantity in Pick UOM.  Convert
6943         --back to primary UOM
6944         -- if Uom code is null, than use primary uom
6945         -- if pick uom = primary uom, skip conversions
6946 
6947         l_orig_allocation_quantity  := l_allocation_quantity;
6948 
6949         IF  p_use_pick_uom
6950             AND g_locs(p_record_id).uom_code IS NOT NULL
6951             AND g_locs(p_record_id).uom_code <> p_primary_uom THEN
6952 
6953           IF l_debug = 1 THEN
6954              log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
6955           END IF;
6956           --convert from primary uom to pick uom
6957           l_possible_uom_qty  := inv_convert.inv_um_convert(
6958                                    p_inventory_item_id
6959                                  , NULL
6960                                  , l_allocation_quantity
6961                                  , p_primary_uom
6962                                  , g_locs(p_record_id).uom_code
6963                                  , NULL
6964                                  , NULL
6965                                  );
6966 
6967           --if no conversion defined or some error in conversion,
6968           --inv_um_convert returns -99999.  In this case, don't carry
6969           --out any more conversion functions.  possible quantity
6970           --remains unchanged
6971           IF (l_possible_uom_qty <> -99999) THEN
6972             --don't want to pick fractional amounts of pick uom
6973             l_possible_uom_qty     := FLOOR(l_possible_uom_qty);
6974 
6975             IF l_debug = 1 THEN
6976                log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
6977             END IF;
6978             --convert back to primary uom
6979             l_allocation_quantity  := inv_convert.inv_um_convert(
6980                                         p_inventory_item_id
6981                                       , NULL
6982                                       , l_possible_uom_qty
6983                                       , g_locs(p_record_id).uom_code
6984                                       , p_primary_uom
6985                                       , NULL
6986                                       , NULL
6987                                       );
6988             IF l_debug = 1 THEN
6989                log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: ' || l_allocation_quantity);
6990             END IF;
6991           END IF;
6992         END IF;
6993 
6994         --populate remaining quantity
6995         x_remaining_quantity        := l_orig_allocation_quantity - l_allocation_quantity;
6996         IF l_debug = 1 THEN
6997            log_statement(l_api_name, 'rem_qty', 'remaining_quantity : ' || x_remaining_quantity);
6998         END IF;
6999 
7000         IF l_allocation_quantity <= 0 THEN
7001           IF l_debug = 1 THEN
7002              log_statement(l_api_name, 'no_alloc_qty', 'Quantity remaining to allocate.  Exiting.');
7003           END IF;
7004           x_allocated_quantity  := 0;
7005           x_inserted_record     := FALSE;
7006           RETURN;
7007         END IF;
7008 
7009         --Lock Serial number, so that no other detailing process
7010         -- can use it.
7011         IF g_locs(p_record_id).serial_number IS NOT NULL THEN
7012           l_found  := inv_detail_util_pvt.lock_serial_number(p_inventory_item_id, g_locs(p_record_id).serial_number);
7013 
7014           IF l_found = FALSE THEN
7015             IF l_debug = 1 THEN
7016                log_statement(l_api_name, 'lock_sn', 'Could not lock Serial Number. Exiting.');
7017             END IF;
7018 
7019             IF p_debug_on THEN
7020               g_trace_recs(p_record_id).serial_number_used_flag  := 'N';
7021             END IF;
7022 
7023             x_remaining_quantity  := g_locs(p_record_id).quantity;
7024             x_allocated_quantity  := 0;
7025             x_inserted_record     := FALSE;
7026             RETURN;
7027           END IF;
7028 
7029           -- add serial number to pl/sql table of detailed serials
7030           inv_detail_util_pvt.add_serial_number(p_inventory_item_id, p_organization_id, g_locs(p_record_id).serial_number, l_serial_index);
7031         END IF;
7032 
7033         --If quantity remaining to allocate is greater than 0, update the
7034         --quantity tree and insert the record into WTT
7035         IF p_transaction_uom = p_primary_uom THEN
7036           l_possible_trx_qty  := l_allocation_quantity;
7037         ELSE
7038           l_possible_trx_qty  :=
7039                      inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_allocation_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
7040         END IF;
7041         IF l_debug = 1 THEN
7042            log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Trx Qty: ' || l_possible_trx_qty);
7043         END IF;
7044         -- insert temporary suggestion
7045         INSERT INTO wms_transactions_temp
7046                     (
7047                     pp_transaction_temp_id
7048                   , transaction_temp_id
7049                   , type_code
7050                   , line_type_code
7051                   , transaction_quantity
7052                   , primary_quantity
7053                   , revision
7054                   , lot_number
7055                   , lot_expiration_date
7056                   , from_subinventory_code
7057                   , from_locator_id
7058                   , rule_id
7059                   , reservation_id
7060                   , serial_number
7061                   , to_subinventory_code
7062                   , to_locator_id
7063                   , from_cost_group_id
7064                   , to_cost_group_id
7065                   , lpn_id
7066                     )
7067              VALUES (
7068                     wms_transactions_temp_s.NEXTVAL
7069                   , p_transaction_temp_id
7070                   , p_type_code
7071                   , 2 -- line type code is output
7072                   , l_possible_trx_qty
7073                   , l_allocation_quantity
7074                   , g_locs(p_record_id).revision
7075                   , g_locs(p_record_id).lot_number
7076                   , g_locs(p_record_id).lot_expiration_date
7077                   , g_locs(p_record_id).subinventory_code
7078                   , g_locs(p_record_id).locator_id
7079                   , p_rule_id
7080                   , p_reservation_id
7081                   , g_locs(p_record_id).serial_number
7082                   , p_to_subinventory_code
7083                   , p_to_locator_id
7084                   , g_locs(p_record_id).cost_group_id
7085                   , p_to_cost_group_id
7086                   , g_locs(p_record_id).lpn_id
7087                     );
7088         IF l_debug = 1 THEN
7089            log_statement(l_api_name, 'finish_insert_wtt', 'Finished inserting wtt recs.');
7090            log_statement(l_api_name, 'alloc_qty', 'Alloc qty: ' || l_allocation_quantity);
7091         END IF;
7092 
7093         IF p_debug_on THEN
7094           g_trace_recs(p_record_id).suggested_qty  := l_allocation_quantity;
7095         END IF;
7096 
7097         x_inserted_record           := TRUE;
7098         x_allocated_quantity        := l_allocation_quantity;
7099         IF l_debug = 1 THEN
7100            log_statement(l_api_name, 'alloc_qty', 'Allocated quantity: ' || x_allocated_quantity);
7101            log_procedure(l_api_name, 'end', 'End ValidNinsert');
7102         END IF;
7103 
7104       EXCEPTION
7105         WHEN fnd_api.g_exc_error THEN
7106           x_return_status  := fnd_api.g_ret_sts_error;
7107           fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7108           --
7109           IF l_debug = 1 THEN
7110              log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
7111           END IF;
7112 
7113         WHEN fnd_api.g_exc_unexpected_error THEN
7114           x_return_status  := fnd_api.g_ret_sts_unexp_error;
7115           fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7116           IF l_debug = 1 THEN
7117              log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
7118           END IF;
7119 
7120         WHEN OTHERS THEN
7121           x_return_status  := fnd_api.g_ret_sts_unexp_error;
7122 
7123           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
7124             fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
7125           END IF;
7126 
7127           fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7128           IF l_debug = 1 THEN
7129              log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
7130           END IF;
7131 
7132   END ValidNinsert;
7133 
7134   -- End of bug #4006426 ---
7135 
7136 
7137   PROCEDURE rollback_consist_allocations(
7138     x_return_status OUT NOCOPY    VARCHAR2
7139   , x_msg_count     OUT NOCOPY    NUMBER
7140   , x_msg_data      OUT NOCOPY    VARCHAR2
7141   , p_group_id      IN            NUMBER
7142   , p_tree_id       IN            NUMBER
7143   , p_type_code     IN            NUMBER
7144   , p_first_uom_rec IN            NUMBER
7145   , p_last_uom_rec  IN            NUMBER
7146   , p_prev_rec      IN            NUMBER
7147   , p_next_rec      IN            NUMBER
7148   , p_debug_on      IN            BOOLEAN
7149   ) IS
7150     l_api_name    VARCHAR2(30) := 'rollback_consist_allocations';
7151     l_current_loc NUMBER;
7152     l_next_rec    NUMBER;
7153 
7154     l_debug       NUMBER;
7155   BEGIN
7156     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
7157        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
7158      END IF;
7159     l_debug := g_debug;
7160 
7161     IF l_debug = 1 THEN
7162        log_procedure(l_api_name, 'Start', 'Start Rollback_Consist_Allocations');
7163        -- rollback the changes we've made
7164        log_statement(l_api_name, 'consist_not_enough_qty', 'Not enough quantity in this consistency group. ' || 'Rolling back suggestions');
7165        log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
7166     END IF;
7167     inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
7168 
7169     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7170       IF l_debug = 1 THEN
7171          log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
7172       END IF;
7173       RAISE fnd_api.g_exc_unexpected_error;
7174     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7175       IF l_debug = 1  THEN
7176          log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
7177       END IF;
7178       RAISE fnd_api.g_exc_error;
7179     END IF;
7180 
7181     --put pick UOM records back into the list;
7182     --we need to put this records between after the last
7183     --record that has the current order by string, since
7184     --these recs have the same order by string.  The last rec
7185     --with the same order by string is stored in l_prev_rec,
7186     --and the first rec with the next order by string is l_loc_id
7187     --We only do this is the pick uom list is populated
7188     IF l_debug = 1 THEN
7189        log_statement(l_api_name, 'p_first_uom_rec', 'first_uom_rec: ' || p_first_uom_rec);
7190        log_statement(l_api_name, 'p_next_rec', 'next_rec: ' || p_next_rec);
7191        log_statement(l_api_name, 'p_prev_rec', 'prev_rec: ' || p_prev_rec);
7192     END IF;
7193     IF p_first_uom_rec <> 0 THEN
7194       IF p_next_rec IS NULL THEN
7195         l_next_rec  := p_prev_rec;
7196 
7197         LOOP
7198           EXIT WHEN NVL(l_next_rec, 0) = 0;
7199           EXIT WHEN g_locs(l_next_rec).order_by_string <> g_locs(p_prev_rec).order_by_string;
7200           l_next_rec  := g_locs(l_next_rec).next_rec;
7201         END LOOP;
7202       ELSE
7203         l_next_rec  := p_next_rec;
7204       END IF;
7205 
7206       IF p_prev_rec = 0 THEN
7207         g_consists(p_group_id).first_rec  := p_first_uom_rec;
7208       ELSE
7209         g_locs(p_prev_rec).next_rec  := p_first_uom_rec;
7210       END IF;
7211 
7212       g_locs(p_last_uom_rec).next_rec  := l_next_rec;
7213     END IF;
7214 
7215     --loop through trace recs, updating recs for this consist
7216     -- group to change consist_string_flag from Y to N
7217     -- and to set suggested quantity back to 0
7218     IF p_debug_on THEN
7219 
7220       l_current_loc  := g_consists(p_group_id).first_rec;
7221       IF l_debug = 1 THEN
7222          log_statement(l_api_name, 'trace', 'Updating trace records');
7223          log_statement(l_api_name, 'first_loc', 'First rec to update: ' || l_current_loc);
7224       END IF ;
7225 
7226       --loop through each record in this consist group
7227       LOOP
7228         EXIT WHEN NVL(l_current_loc, 0) = 0;
7229         --update the trace records
7230         g_trace_recs(l_current_loc).consist_string_flag := 'N';
7231         g_trace_recs(l_current_loc).suggested_qty := 0;
7232         g_trace_recs(l_current_loc).secondary_suggested_qty := 0;
7233         l_current_loc := g_locs(l_current_loc).next_rec;
7234         IF l_debug = 1 THEN
7235            log_statement(l_api_name, 'current_loc', 'Current rec: ' || l_current_loc);
7236         END IF ;
7237       END LOOP;
7238     END IF;
7239 
7240     DELETE FROM wms_transactions_temp
7241           WHERE line_type_code = 2
7242             AND type_code = p_type_code;
7243     IF l_debug = 1 THEN
7244        log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
7245        log_procedure(l_api_name, 'End', 'End Rollback_Consist_Allocations');
7246     END IF;
7247   EXCEPTION
7248     WHEN fnd_api.g_exc_error THEN
7249       x_return_status  := fnd_api.g_ret_sts_error;
7250       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7251       IF l_debug = 1 THEN
7252          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
7253       END IF;
7254 
7255     WHEN fnd_api.g_exc_unexpected_error THEN
7256       x_return_status  := fnd_api.g_ret_sts_unexp_error;
7257       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7258       IF l_debug = 1 THEN
7259          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
7260       END IF;
7261 
7262     WHEN OTHERS THEN
7263       x_return_status  := fnd_api.g_ret_sts_unexp_error;
7264 
7265       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
7266         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
7267       END IF;
7268 
7269       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7270       IF l_debug = 1 THEN
7271          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
7272       END IF;
7273   END rollback_consist_allocations;
7274 
7275 
7276   PROCEDURE allocate_consist_group(
7277     x_return_status        OUT NOCOPY    VARCHAR2
7278   , x_msg_count            OUT NOCOPY    NUMBER
7279   , x_msg_data             OUT NOCOPY    VARCHAR2
7280   , p_group_id             IN            NUMBER
7281   , p_needed_quantity      IN            NUMBER
7282   , p_use_pick_uom         IN            BOOLEAN
7283   , p_organization_id      IN            NUMBER
7284   , p_inventory_item_id    IN            NUMBER
7285   , p_to_subinventory_code IN            VARCHAR2
7286   , p_to_locator_id        IN            NUMBER
7287   , p_to_cost_group_id     IN            NUMBER
7288   , p_primary_uom          IN            VARCHAR2
7289   , p_transaction_uom      IN            VARCHAR2
7290   , p_transaction_temp_id  IN            NUMBER
7291   , p_type_code            IN            NUMBER
7292   , p_rule_id              IN            NUMBER
7293   , p_reservation_id       IN            NUMBER
7294   , p_tree_id              IN            NUMBER
7295   , p_debug_on             IN            BOOLEAN
7296   , p_needed_sec_quantity  IN            NUMBER
7297   , p_secondary_uom        IN            VARCHAR2
7298   , p_grade_code           IN            VARCHAR2
7299   , p_orig_needed_quantity IN            NUMBER   -- Added for 14699845 (Flexible lot allocation)
7300   , p_orig_needed_sec_qty  IN            NUMBER   -- Added for 14699845 (Flexible lot allocation)
7301   , p_simulation_mode      IN            NUMBER   -- Added for 14699845 (Flexible lot allocation)
7302   , p_lot_divisible_flag   IN            VARCHAR2
7303   , x_success              OUT NOCOPY    BOOLEAN
7304   ) IS
7305     l_api_name                 VARCHAR2(30)   := 'allocate_consist_group';
7306     l_loc_id                   NUMBER;
7307     l_current_order_by_string  VARCHAR2(1000) := NULL;
7308     l_first_rec_uom            NUMBER         := 0;
7309     l_last_rec_uom             NUMBER         := 0;
7310     l_last_rec_cur_uom         NUMBER         := 0;
7311     l_uom_loc_id               NUMBER;
7312     l_needed_quantity          NUMBER;
7313     -- Added for 14699845 (Flexible lot allocation)
7314     l_needed_quantity_wo_tol   NUMBER         := p_orig_needed_quantity;
7315     l_needed_sec_qty_wo_tol    NUMBER         := p_orig_needed_sec_qty;
7316 
7317     l_inserted_record          BOOLEAN;
7318     l_allocated_quantity       NUMBER;
7319     l_remaining_quantity       NUMBER;
7320     l_expected_quantity        NUMBER;
7321     l_sec_needed_quantity      NUMBER;                  -- new
7322     l_sec_allocated_quantity   NUMBER;                  -- new
7323     l_sec_remaining_quantity   NUMBER;                  -- new
7324     l_sec_expected_quantity    NUMBER;                  -- new
7325     l_current_loc              NUMBER;
7326     l_prev_rec                 NUMBER         := 0;
7327     l_original_needed_quantity NUMBER;
7328     l_original_needed_sec_qty  NUMBER;
7329     l_uom_index                NUMBER;
7330     l_lot_control_code         NUMBER         :=inv_cache.item_rec.lot_control_code; -- added for bug7267861
7331     l_insert                   NUMBER    := 0;  --bug# 8270806
7332     l_debug                    NUMBER;
7333   BEGIN
7334     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
7335        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
7336     END IF;
7337     l_debug := g_debug;
7338 
7339     IF l_debug = 1 THEN
7340        log_procedure(l_api_name, 'Start', 'Start Allocate_Consist_Group');
7341        log_procedure(l_api_name, 'Start', 'p_needed_sec_quantity: ' || p_needed_sec_quantity);
7342        log_procedure(l_api_name, 'Start', 'p_needed_quantity: ' || p_needed_quantity);
7343        -- Added for 14699845 (Flexible lot allocation)
7344        log_procedure(l_api_name, 'Start', 'p_orig_needed_quantity: ' || p_orig_needed_quantity);
7345        log_procedure(l_api_name, 'Start', 'p_orig_needed_sec_qty: '  || p_orig_needed_sec_qty);
7346        log_procedure(l_api_name, 'Start', 'p_simulation_mode: ' || p_simulation_mode);
7347     END IF;
7348     l_needed_quantity           := p_needed_quantity;
7349     l_sec_needed_quantity       := p_needed_sec_quantity; -- bug 10228168
7350 
7351     -- Modified for 14699845 (Flexible lot allocation)
7352     l_original_needed_quantity  := LEAST(p_needed_quantity, p_orig_needed_quantity);
7353     l_original_needed_sec_qty   := LEAST(p_needed_sec_quantity,p_orig_needed_sec_qty);
7354 
7355     l_loc_id                    := g_consists(p_group_id).first_rec;
7356     x_success                   := FALSE;
7357 
7358     --for each record in the consistency group
7359     LOOP --{
7360       EXIT WHEN l_loc_id = 0;
7361       l_insert := 0;  --bug# 8270806,reseting the value to l_insert
7362       -- Allocation from pick UOM list if this rec's order string is not
7363       -- equal to previous rec's order string and we are using pick UOM
7364       -- and the pick UOM list is not empty
7365       IF NVL(l_current_order_by_string, '@@@') <> NVL(g_locs(l_loc_id).order_by_string, '@@@')
7366          AND p_use_pick_uom
7367          AND l_first_rec_uom <> 0 THEN --{
7368         IF l_debug = 1 THEN
7369            log_statement(l_api_name, 'pick_uom', 'Allocating pick UOM records');
7370         END IF;
7371 
7372         l_uom_loc_id  := l_first_rec_uom;
7373 
7374         -- for each record in Pick UOM table
7375         LOOP --{
7376           EXIT WHEN l_uom_loc_id = 0;
7377           l_expected_quantity := g_locs(l_uom_loc_id).quantity;
7378           l_sec_expected_quantity := g_locs(l_uom_loc_id).secondary_quantity;
7379 
7380           -- validate_and_insert will allocation no more than needed quantity
7381           IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_needed_quantity_wo_tol < l_expected_quantity)
7382               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_needed_sec_qty_wo_tol < l_sec_expected_quantity)
7383           THEN
7384              l_expected_quantity := l_needed_quantity;
7385              l_sec_expected_quantity := l_sec_needed_quantity;
7386           END IF;
7387           IF l_debug = 1 THEN
7388              log_statement(l_api_name, 'exp_qty', 'Expected Qty: ' || l_expected_quantity);
7389              log_statement(l_api_name, 'sec_exp_qty', 'Secondary Expected Qty: ' || l_sec_expected_quantity);
7390              log_statement(l_api_name, 'val_insert', 'Calling Validate and Insert');
7391           END IF;
7392 
7393           -- call helper procedure to validate and insert record
7394           validate_and_insert(
7395             x_return_status              => x_return_status
7396           , x_msg_count                  => x_msg_count
7397           , x_msg_data                   => x_msg_data
7398           , p_record_id                  => l_uom_loc_id
7399           , p_needed_quantity            => l_needed_quantity
7400           , p_use_pick_uom               => FALSE
7401           , p_organization_id            => p_organization_id
7402           , p_inventory_item_id          => p_inventory_item_id
7403           , p_to_subinventory_code       => p_to_subinventory_code
7404           , p_to_locator_id              => p_to_locator_id
7405           , p_to_cost_group_id           => p_to_cost_group_id
7406           , p_primary_uom                => p_primary_uom
7407           , p_transaction_uom            => p_transaction_uom
7408           , p_transaction_temp_id        => p_transaction_temp_id
7409           , p_type_code                  => p_type_code
7410           , p_rule_id                    => p_rule_id
7411           , p_reservation_id             => p_reservation_id
7412           , p_tree_id                    => p_tree_id
7413           , p_debug_on                   => p_debug_on
7414           , p_needed_sec_quantity        => l_sec_needed_quantity
7415           , p_secondary_uom              => p_secondary_uom
7416           , p_grade_code                 => p_grade_code
7417           , x_inserted_record            => l_inserted_record
7418           , x_allocated_quantity         => l_allocated_quantity
7419           , x_remaining_quantity         => l_remaining_quantity
7420           , x_sec_allocated_quantity     => l_sec_allocated_quantity
7421           , x_sec_remaining_quantity     => l_sec_remaining_quantity
7422           , p_orig_needed_quantity       => l_needed_quantity_wo_tol  -- Added for 14699845 (Flexible lot allocation)
7423           , p_orig_needed_sec_qty        => l_needed_sec_qty_wo_tol   -- Added for 14699845 (Flexible lot allocation)
7424           , p_simulation_mode            => p_simulation_mode         -- Added for 14699845 (Flexible lot allocation)
7425           );
7426 
7427           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7428              IF l_debug = 1 THEN
7429                 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
7430              END IF;
7431              RAISE fnd_api.g_exc_unexpected_error;
7432           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7433              IF l_debug = 1 THEN
7434                 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
7435              END IF;
7436              RAISE fnd_api.g_exc_error;
7437           END IF;
7438 
7439           -- If function did not insert full quantity, decrease group qty
7440           IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_expected_quantity > l_allocated_quantity)
7441               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_expected_quantity > l_sec_allocated_quantity)
7442           THEN --{
7443              IF l_debug = 1 THEN
7444                 log_statement(l_api_name, 'did_not_alloc_full', 'Not all of the expected quantity was allocated');
7445              END IF;
7446              g_consists(p_group_id).quantity := g_consists(p_group_id).quantity - (l_expected_quantity - l_allocated_quantity);
7447              g_consists(p_group_id).secondary_quantity := g_consists(p_group_id).secondary_quantity
7448                                                            - (l_sec_expected_quantity - l_sec_allocated_quantity);
7449              IF l_debug = 1 THEN
7450                 log_statement(l_api_name, 'new_group_qty', 'New group quantity: ' || g_consists(p_group_id).quantity);
7451                 log_statement(l_api_name, 'new_group_qty', 'New group sec qty: '
7452                                            || g_consists(p_group_id).secondary_quantity);
7453              END IF;
7454              g_locs(l_uom_loc_id).quantity := l_allocated_quantity;
7455              g_locs(l_uom_loc_id).secondary_quantity := l_sec_allocated_quantity;
7456 
7457              -- If group qty is now less than needed qty, rollback and return
7458              IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
7459                      AND g_consists(p_group_id).quantity < l_original_needed_quantity)
7460                  OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
7461                      AND g_consists(p_group_id).secondary_quantity < l_original_needed_sec_qty)
7462              THEN --{
7463                 IF l_debug = 1 THEN
7464                    log_statement(l_api_name, 'rollback_consist', 'Not enough quantity in consist group. Calling '
7465                                               || 'rollback consist allocations.');
7466                 END IF;
7467 
7468                 rollback_consist_allocations(
7469                   x_return_status              => x_return_status
7470                 , x_msg_count                  => x_msg_count
7471                 , x_msg_data                   => x_msg_data
7472                 , p_group_id                   => p_group_id
7473                 , p_tree_id                    => p_tree_id
7474                 , p_type_code                  => p_type_code
7475                 , p_first_uom_rec              => l_first_rec_uom
7476                 , p_last_uom_rec               => l_last_rec_uom
7477                 , p_prev_rec                   => l_prev_rec
7478                 , p_next_rec                   => l_loc_id
7479                 , p_debug_on                   => p_debug_on
7480                 );
7481 
7482                 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7483                    IF l_debug = 1 THEN
7484                       log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
7485                    END IF;
7486                    RAISE fnd_api.g_exc_unexpected_error;
7487                 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7488                    IF l_debug = 1 THEN
7489                       log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
7490                    END IF;
7491                    RAISE fnd_api.g_exc_error;
7492                 END IF;
7493                 IF l_debug = 1 THEN
7494                    log_statement(l_api_name, 'after_rollback_consist', 'Rolled back the allocations.  Exiting');
7495                 END IF;
7496                 x_success  := FALSE;
7497                 RETURN;
7498              END IF; --}
7499           END IF; --}
7500 
7501           IF p_debug_on THEN
7502              g_trace_recs(l_uom_loc_id).consist_string_flag  := 'Y';
7503           END IF;
7504 
7505           -- Decrease remaining qty to be allocated
7506           l_needed_quantity := l_needed_quantity - l_allocated_quantity;
7507           l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
7508 
7509           -- Added for 14699845 (Flexible lot allocation)
7510           l_needed_quantity_wo_tol := l_needed_quantity_wo_tol - l_allocated_quantity;
7511           l_needed_sec_qty_wo_tol  := l_needed_sec_qty_wo_tol  - l_sec_allocated_quantity;
7512 
7513           -- if no qty left to detail, exit pick UOM loop
7514           IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND (l_needed_quantity <= 0 OR l_needed_quantity_wo_tol <= 0))
7515               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND (l_sec_needed_quantity <= 0 OR l_needed_sec_qty_wo_tol <= 0))
7516           THEN
7517              IF l_debug = 1 THEN
7518                 log_statement(l_api_name, 'no_more_qty', 'Allocated all the needed quantity.  Exiting.');
7519              END IF;
7520              x_success  := TRUE;
7521              RETURN;
7522           END IF;
7523           IF l_debug = 1 THEN
7524              log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
7525              log_statement(l_api_name, 'need_sec_qty', 'New needed sec qty: ' || l_sec_needed_quantity);
7526              -- Added for 14699845 (Flexible lot allocation)
7527              log_statement(l_api_name, 'need_qty', 'New needed quantity without tolerance: ' || l_needed_quantity_wo_tol);
7528              log_statement(l_api_name, 'need_qty', 'New needed sec qty  without tolerance: ' || l_needed_sec_qty_wo_tol);
7529           END IF;
7530           l_uom_loc_id := g_locs(l_uom_loc_id).next_rec;
7531         END LOOP; --}
7532       END IF; --}
7533 
7534       l_current_order_by_string := g_locs(l_loc_id).order_by_string;
7535       -- Call validate_and_insert on current record
7536       -- If group qty is now less than needed qty, rollback and return
7537       -- If remaining qty > 0 and use Pick UOM, add new record to pick uom table
7538       -- decrease remaining qty to be allocated
7539       -- exit when no more qty left to detail
7540       l_expected_quantity := g_locs(l_loc_id).quantity;
7541       l_sec_expected_quantity := g_locs(l_loc_id).secondary_quantity;
7542 
7543       -- validate_and_insert will allocate no more than needed quantity
7544       IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_needed_quantity_wo_tol < l_expected_quantity)
7545           OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_needed_sec_qty_wo_tol < l_sec_expected_quantity)
7546       THEN
7547          l_insert := 1;  --bug# 8270806
7548          l_expected_quantity := l_needed_quantity_wo_tol;
7549          l_sec_expected_quantity := l_needed_sec_qty_wo_tol;
7550       END IF;
7551       IF l_debug = 1 THEN
7552          log_statement(l_api_name, 'exp_qty', 'Expected Qty: ' || l_expected_quantity);
7553          log_statement(l_api_name, 'sec_exp_qty', 'Secondary Expected Qty: ' || l_sec_expected_quantity);
7554          log_statement(l_api_name, 'exp_qty', 'l_needed_quantity: ' || l_needed_quantity);
7555          log_statement(l_api_name, 'exp_qty', 'l_sec_needed_quantity: ' || l_sec_needed_quantity);
7556 
7557          -- Added for 14699845 (Flexible lot allocation)
7558          log_statement(l_api_name, 'exp_qty', 'l_needed_quantity_wo_tol: ' || l_needed_quantity_wo_tol);
7559          log_statement(l_api_name, 'exp_qty', 'l_needed_sec_qty_wo_tol: ' || l_needed_sec_qty_wo_tol);
7560 
7561          log_statement(l_api_name, 'exp_qty', 'g_locs(l_loc_id).quantity: ' || g_locs(l_loc_id).quantity);
7562          log_statement(l_api_name, 'exp_qty', 'g_locs(l_loc_id).secondary_quantity: ' || g_locs(l_loc_id).secondary_quantity);
7563          log_statement(l_api_name, 'val_insert', 'Calling Validate and Insert');
7564       END IF;
7565 
7566       -- Added the following  restriction - 5258131
7567       IF ( ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_needed_quantity_wo_tol >= l_expected_quantity)
7568               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_needed_sec_qty_wo_tol >= l_sec_expected_quantity)
7569            )
7570            AND l_insert = 0 AND p_lot_divisible_flag = 'N'
7571          )
7572          OR ((NVL(p_lot_divisible_flag, 'Y') = 'Y') OR NVL(l_lot_control_code,1) = 1) -- added for bug7261861
7573       THEN --{
7574          validate_and_insert(
7575            x_return_status              => x_return_status
7576          , x_msg_count                  => x_msg_count
7577          , x_msg_data                   => x_msg_data
7578          , p_record_id                  => l_loc_id
7579          , p_needed_quantity            => l_needed_quantity
7580          , p_use_pick_uom               => p_use_pick_uom
7581          , p_organization_id            => p_organization_id
7582          , p_inventory_item_id          => p_inventory_item_id
7583          , p_to_subinventory_code       => p_to_subinventory_code
7584          , p_to_locator_id              => p_to_locator_id
7585          , p_to_cost_group_id           => p_to_cost_group_id
7586          , p_primary_uom                => p_primary_uom
7587          , p_transaction_uom            => p_transaction_uom
7588          , p_transaction_temp_id        => p_transaction_temp_id
7589          , p_type_code                  => p_type_code
7590          , p_rule_id                    => p_rule_id
7591          , p_reservation_id             => p_reservation_id
7592          , p_tree_id                    => p_tree_id
7593          , p_debug_on                   => p_debug_on
7594          , p_needed_sec_quantity        => l_sec_needed_quantity
7595          , p_secondary_uom              => p_secondary_uom
7596          , p_grade_code                 => p_grade_code
7597          , x_inserted_record            => l_inserted_record
7598          , x_allocated_quantity         => l_allocated_quantity
7599          , x_remaining_quantity         => l_remaining_quantity
7600          , x_sec_allocated_quantity     => l_sec_allocated_quantity
7601          , x_sec_remaining_quantity     => l_sec_remaining_quantity
7602          , p_orig_needed_quantity       => l_needed_quantity_wo_tol -- Added for 14699845 (Flexible lot allocation)
7603          , p_orig_needed_sec_qty        => l_needed_sec_qty_wo_tol  -- Added for 14699845 (Flexible lot allocation)
7604          , p_simulation_mode            => p_simulation_mode        -- Added for 14699845 (Flexible lot allocation)
7605          );
7606 
7607          IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7608             IF l_debug = 1 THEN
7609                log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
7610             END IF;
7611             RAISE fnd_api.g_exc_unexpected_error;
7612          ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7613             IF l_debug = 1 THEN
7614                log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
7615             END IF;
7616             RAISE fnd_api.g_exc_error;
7617          END IF;
7618       END IF; --} End of If 5258131
7619 
7620       -- If function did not insert full quantity, decrease group qty
7621       IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_expected_quantity > l_allocated_quantity)
7622           OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_expected_quantity > l_sec_allocated_quantity)
7623       THEN --{
7624          IF l_debug = 1 THEN
7625             log_statement(l_api_name, 'did_not_alloc_full', 'Not all of the expected quantity was allocated');
7626          END IF;
7627          g_consists(p_group_id).quantity := g_consists(p_group_id).quantity - (l_expected_quantity - l_allocated_quantity);
7628          g_consists(p_group_id).secondary_quantity := g_consists(p_group_id).secondary_quantity
7629                                                        - (l_sec_expected_quantity - l_sec_allocated_quantity);
7630          IF l_debug = 1 THEN
7631             log_statement(l_api_name, 'new_group_qty', 'New group quantity: ' || g_consists(p_group_id).quantity);
7632             log_statement(l_api_name, 'new_group_sec_qty', 'New group sec quantity: ' || g_consists(p_group_id).secondary_quantity);
7633          END IF;
7634          g_locs(l_loc_id).quantity := l_allocated_quantity;
7635          g_locs(l_loc_id).secondary_quantity := l_sec_allocated_quantity;
7636 
7637          -- If group qty is now less than needed qty, rollback and return
7638          IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
7639                  AND g_consists(p_group_id).quantity < l_original_needed_quantity)
7640              OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
7641                  AND g_consists(p_group_id).secondary_quantity < l_original_needed_sec_qty)
7642          THEN --{
7643             -- out of records with cur_consist_string;
7644             -- rollback the changes we've made
7645             IF l_debug = 1 THEN
7646                log_statement(l_api_name, 'rollback_consist', 'Not enough quantity in consist group. Calling '
7647                                           || 'rollback consist allocations.');
7648             END IF;
7649             rollback_consist_allocations(
7650               x_return_status              => x_return_status
7651             , x_msg_count                  => x_msg_count
7652             , x_msg_data                   => x_msg_data
7653             , p_group_id                   => p_group_id
7654             , p_tree_id                    => p_tree_id
7655             , p_type_code                  => p_type_code
7656             , p_first_uom_rec              => l_first_rec_uom
7657             , p_last_uom_rec               => l_last_rec_uom
7658             , p_prev_rec                   => l_loc_id
7659             , p_next_rec                   => NULL
7660             , p_debug_on                   => p_debug_on
7661             );
7662 
7663             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7664                IF l_debug = 1 THEN
7665                   log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
7666                END IF;
7667                RAISE fnd_api.g_exc_unexpected_error;
7668             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7669                IF l_debug = 1 THEN
7670                   log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
7671                END IF;
7672                RAISE fnd_api.g_exc_error;
7673             END IF;
7674             IF l_debug = 1 THEN
7675                log_statement(l_api_name, 'after_rollback_consist', 'Rolled back the allocations.  Exiting');
7676             END IF;
7677             x_success  := FALSE;
7678             RETURN;
7679          END IF; --}
7680       END IF; --}
7681 
7682       IF p_debug_on THEN
7683          g_trace_recs(l_loc_id).consist_string_flag := 'Y';
7684       END IF;
7685 
7686       -- Decrease remaining qty to be allocated
7687       l_needed_quantity := l_needed_quantity - l_allocated_quantity;
7688       l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
7689 
7690       -- Added for 14699845 (Flexible lot allocation)
7691       l_needed_quantity_wo_tol := l_needed_quantity_wo_tol - l_allocated_quantity;
7692       l_needed_sec_qty_wo_tol  := l_needed_sec_qty_wo_tol  - l_sec_allocated_quantity;
7693 
7694       -- if no qty left to detail, exit loop
7695       IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND (l_needed_quantity <= 0 OR l_needed_quantity_wo_tol <= 0) )
7696           OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND (l_sec_needed_quantity <= 0 OR l_needed_sec_qty_wo_tol <= 0) )
7697       THEN
7698          x_success  := TRUE;
7699          IF l_debug = 1 THEN
7700             log_statement(l_api_name, 'no_more_qty', 'Allocated all the needed quantity.  Exiting.');
7701          END IF;
7702          RETURN;
7703       END IF;
7704       IF l_debug = 1 THEN
7705          log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
7706          log_statement(l_api_name, 'need_qty', 'New needed sec qty: ' || l_sec_needed_quantity);
7707 
7708          -- Added for 14699845 (Flexible lot allocation)
7709          log_statement(l_api_name, 'need_qty', 'New needed quantity without tolerance: ' || l_needed_quantity_wo_tol);
7710          log_statement(l_api_name, 'need_qty', 'New needed sec qty  without tolerance: ' || l_needed_sec_qty_wo_tol);
7711       END IF;
7712       -- handle pick UOM
7713       IF ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_remaining_quantity > 0)
7714             OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_remaining_quantity > 0)
7715          )
7716          AND p_use_pick_uom
7717       THEN --{
7718          IF l_debug = 1 THEN
7719             log_statement(l_api_name, 'create_pick_uom', 'Create a pick UOM record.Remaining quantity:'
7720                                        || l_remaining_quantity);
7721             log_statement(l_api_name, 'create_pick_uom', 'Remaining sec qty:' || l_sec_remaining_quantity);
7722          END IF;
7723 
7724          -- create new record if necessary
7725          IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_remaining_quantity < g_locs(l_loc_id).quantity)
7726              OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_remaining_quantity < g_locs(l_loc_id).secondary_quantity)
7727          THEN
7728             g_locs_index := g_locs_index + 1;
7729             g_locs(g_locs_index) := g_locs(l_loc_id);
7730             g_locs(g_locs_index).quantity := l_remaining_quantity;
7731             g_locs(g_locs_index).secondary_quantity := l_sec_remaining_quantity;      -- 10636620
7732             g_locs(l_loc_id).quantity := g_locs(l_loc_id).quantity - l_remaining_quantity;
7733             g_locs(l_loc_id).secondary_quantity := g_locs(l_loc_id).secondary_quantity - l_sec_remaining_quantity; -- 10636620
7734             l_uom_index := g_locs_index;
7735             l_prev_rec := l_loc_id;
7736          ELSE
7737             -- if  could not be allocated, remove record from
7738             -- current linked list
7739             IF l_prev_rec <> 0 THEN
7740                g_locs(l_prev_rec).next_rec := g_locs(l_loc_id).next_rec;
7741             ELSE
7742                g_consists(p_group_id).first_rec := g_locs(l_loc_id).next_rec;
7743             END IF;
7744 
7745             l_uom_index := l_loc_id;
7746             -- if rec is removed from link list, prev_rec does not change
7747          END IF;
7748 
7749          -- set pointers
7750          -- new record is first record in table
7751          IF l_first_rec_uom = 0 THEN
7752             l_first_rec_uom := l_uom_index;
7753             l_last_rec_cur_uom := l_uom_index;
7754             l_last_rec_uom := l_uom_index;
7755             g_locs(l_uom_index).next_rec := 0;
7756             IF l_debug = 1 THEN
7757                log_statement(l_api_name, 'first_rec', 'The saved uom record is the first record in table');
7758             END IF;
7759             -- new record is first record with that uom code
7760          ELSIF g_locs(l_first_rec_uom).uom_code <> g_locs(l_uom_index).uom_code THEN
7761             g_locs(l_uom_index).next_rec  := l_first_rec_uom;
7762             l_first_rec_uom               := l_uom_index;
7763             l_last_rec_cur_uom            := l_uom_index;
7764             IF l_debug = 1 THEN
7765                log_statement(l_api_name, 'first_rec_uom', 'The saved uom record is the first record for uom in table');
7766             END IF;
7767          -- records with this uom code already exist in table
7768          ELSE
7769             g_locs(l_uom_index).next_rec         := g_locs(l_last_rec_cur_uom).next_rec;
7770             g_locs(l_last_rec_cur_uom).next_rec  := l_uom_index;
7771             l_last_rec_cur_uom                   := l_uom_index;
7772 
7773             IF g_locs(l_uom_index).next_rec = 0 THEN
7774                l_last_rec_uom  := l_uom_index;
7775             END IF;
7776             IF l_debug = 1 THEN
7777                log_statement(l_api_name, 'not_first_rec_uom', 'The saved record is not first record for uom in table');
7778             END IF;
7779          END IF;
7780          IF l_debug = 1 THEN
7781             log_statement(l_api_name, 'saving_loc', 'Storing record in uom table');
7782          END IF;
7783 
7784          IF p_debug_on THEN
7785             -- determine if we created a new record or not
7786             IF l_uom_index = g_locs_index THEN
7787                g_trace_recs(g_locs_index)                := g_trace_recs(l_loc_id);
7788                g_trace_recs(l_loc_id).quantity           := g_trace_recs(l_loc_id).quantity - l_remaining_quantity;
7789                g_trace_recs(g_locs_index).quantity       := l_remaining_quantity;
7790                g_trace_recs(l_loc_id).pick_uom_flag      := 'P';
7791                g_trace_recs(g_locs_index).pick_uom_flag  := 'N';
7792             ELSE
7793                g_trace_recs(l_loc_id).pick_uom_flag  := 'N';
7794             END IF;
7795          END IF;
7796       --}
7797       ELSE
7798          l_prev_rec  := l_loc_id;
7799       END IF;
7800 
7801       l_loc_id                   := g_locs(l_loc_id).next_rec;
7802     END LOOP; --}
7803 
7804     IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND (l_needed_quantity <= 0 OR l_needed_quantity_wo_tol <= 0) )
7805         OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND (l_sec_needed_quantity <= 0 OR l_needed_sec_qty_wo_tol <= 0) )
7806     THEN
7807        x_success  := TRUE;
7808     ELSE --{
7809        -- some sort of error occurred in our calculations;
7810        -- we thought that there was enough material in the consistency
7811        -- group, but we've allocated all the location records, but we have
7812        -- not fulfilled all of the needed quantity;
7813        -- Rollback the changes.
7814        IF l_debug = 1 THEN
7815           log_statement(l_api_name, 'rollback_consist',    'Quantity value on consist group was wrong.  There is not enough '
7816                                      || 'quantity to allocate in this consist group.. Calling '
7817                                      || 'rollback consist allocations.');
7818        END IF;
7819        rollback_consist_allocations(
7820          x_return_status              => x_return_status
7821        , x_msg_count                  => x_msg_count
7822        , x_msg_data                   => x_msg_data
7823        , p_group_id                   => p_group_id
7824        , p_tree_id                    => p_tree_id
7825        , p_type_code                  => p_type_code
7826        , p_first_uom_rec              => 0
7827        , p_last_uom_rec               => 0
7828        , p_prev_rec                   => 0
7829        , p_next_rec                   => 0
7830        , p_debug_on                   => p_debug_on
7831        );
7832 
7833        IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7834           IF l_debug = 1 THEN
7835              log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
7836           END IF;
7837           RAISE fnd_api.g_exc_unexpected_error;
7838        ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7839           IF l_debug = 1 THEN
7840              log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
7841           END IF;
7842           RAISE fnd_api.g_exc_error;
7843        END IF;
7844 
7845        x_success  := FALSE;
7846     END IF; --}
7847     IF l_debug = 1 THEN
7848        log_procedure(l_api_name, 'end', 'End Allocate_Consist_Group');
7849     END IF;
7850   EXCEPTION
7851     WHEN fnd_api.g_exc_error THEN
7852       x_return_status  := fnd_api.g_ret_sts_error;
7853       x_success        := FALSE;
7854       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7855       IF l_debug = 1 THEN
7856          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
7857       END IF;
7858 
7859     WHEN fnd_api.g_exc_unexpected_error THEN
7860       x_return_status  := fnd_api.g_ret_sts_unexp_error;
7861       x_success        := FALSE;
7862       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7863       IF l_debug = 1 THEN
7864          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
7865       END IF;
7866     WHEN OTHERS THEN
7867       x_return_status  := fnd_api.g_ret_sts_unexp_error;
7868       x_success        := FALSE;
7869 
7870       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
7871         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
7872       END IF;
7873 
7874       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
7875       IF l_debug = 1 THEN
7876          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
7877       END IF;
7878 
7879   END allocate_consist_group;
7880 
7881 
7882   PROCEDURE insert_consist_record(
7883     x_return_status        OUT NOCOPY    VARCHAR2
7884   , x_msg_count            OUT NOCOPY    NUMBER
7885   , x_msg_data             OUT NOCOPY    VARCHAR2
7886   , p_record_id            IN            NUMBER
7887   , p_needed_quantity      IN            NUMBER
7888   , p_use_pick_uom         IN            BOOLEAN
7889   , p_organization_id      IN            NUMBER
7890   , p_inventory_item_id    IN            NUMBER
7891   , p_to_subinventory_code IN            VARCHAR2
7892   , p_to_locator_id        IN            NUMBER
7893   , p_to_cost_group_id     IN            NUMBER
7894   , p_primary_uom          IN            VARCHAR2
7895   , p_transaction_uom      IN            VARCHAR2
7896   , p_transaction_temp_id  IN            NUMBER
7897   , p_type_code            IN            NUMBER
7898   , p_rule_id              IN            NUMBER
7899   , p_reservation_id       IN            NUMBER
7900   , p_tree_id              IN            NUMBER
7901   , p_debug_on             IN            BOOLEAN
7902   , p_order_by_rank        IN            NUMBER
7903   , p_needed_sec_quantity  IN            NUMBER
7904   , p_secondary_uom        IN            VARCHAR2
7905   , p_grade_code           IN            VARCHAR2
7906   , p_orig_needed_quantity IN            NUMBER  -- Added for 14699845 (Flexible lot allocation)
7907   , p_orig_needed_sec_qty  IN            NUMBER  -- Added for 14699845 (Flexible lot allocation)
7908   , p_simulation_mode      IN            NUMBER  -- Added for 14699845 (Flexible lot allocation)
7909   , x_finished             OUT NOCOPY    BOOLEAN
7910   , x_remaining_quantity   OUT NOCOPY    NUMBER
7911   , x_remaining_sec_qty    OUT NOCOPY    NUMBER
7912   ) IS
7913     l_api_name               VARCHAR2(30) := 'insert_consist_record';
7914     l_cur_group              NUMBER;
7915     l_hash_size              NUMBER;
7916     l_possible_quantity      NUMBER;
7917     l_needed_quantity        NUMBER;
7918     l_possible_uom_qty       NUMBER;
7919     l_orig_poss_uom_qty      NUMBER;
7920     l_sec_possible_quantity  NUMBER;                 -- new
7921     l_sec_needed_quantity    NUMBER;                 -- new
7922     l_sec_possible_uom_qty   NUMBER;                 -- new
7923 
7924     l_debug             NUMBER;
7925 
7926   BEGIN
7927     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
7928        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
7929     END IF;
7930     l_debug := g_debug;
7931     IF l_debug = 1 THEN
7932        log_procedure(l_api_name, 'start', 'Start Insert Consist Record');
7933        log_procedure(l_api_name, 'start', 'p_needed_quantity: ' || p_needed_quantity);
7934        log_procedure(l_api_name, 'start', 'p_needed_sec_quantity: ' || p_needed_sec_quantity);
7935 
7936        -- Added for 14699845 (Flexible lot allocation)
7937        log_procedure(l_api_name, 'start', 'p_orig_needed_quantity: ' || p_orig_needed_quantity);
7938        log_procedure(l_api_name, 'start', 'p_orig_needed_sec_qty: '  || p_orig_needed_sec_qty);
7939        log_procedure(l_api_name, 'start', 'p_simulation_mode: ' || p_simulation_mode); -- Added for 14699845 (Flexible lot allocation)
7940 
7941        log_procedure(l_api_name, 'start', 'p_secondary_uom: ' || p_secondary_uom);
7942        log_procedure(l_api_name, 'start', 'g_locs(p_record_id).secondary_quantity: ' || g_locs(p_record_id).secondary_quantity);
7943        log_procedure(l_api_name, 'start', 'g_locs(p_record_id).quantity: ' || g_locs(p_record_id).quantity);
7944     END IF;
7945 
7946     x_finished       := FALSE;
7947     -- used in get_hash_value.  That procedure works best if
7948     -- hashsize is power of 2
7949     l_hash_size      := POWER(2, 15);
7950     -- get hash index for this consist string
7951     IF l_debug = 1 THEN
7952        log_statement(l_api_name, 'get_hash_value', 'Calling get_hash_value');
7953     END IF;
7954     l_cur_group := DBMS_UTILITY.get_hash_value(
7955                         NAME => g_locs(p_record_id).consist_string
7956                       , base => 1
7957                       , hash_size => l_hash_size
7958                       );
7959 
7960     -- Because the hash function can return the same index for different
7961     -- consist strings, we have to check to see if the group at the index
7962     -- returned above has the same consist string as the current record.
7963     -- If not, look at the next record.  Continue on until we find the
7964     -- correct consist group or determine that the group has not been defined
7965     -- yet
7966     LOOP
7967       EXIT WHEN NOT g_consists.EXISTS(l_cur_group);
7968       EXIT WHEN NVL(g_consists(l_cur_group).consist_string, '-9999') = NVL(g_locs(p_record_id).consist_string, '-9999');
7969       l_cur_group  := l_cur_group + 1;
7970     END LOOP;
7971 
7972     -- If we need to take Pick UOM into consideration, we need to determine
7973     -- how much of this record is needed
7974     IF p_use_pick_uom THEN --{
7975        IF l_debug = 1 THEN
7976           log_statement(l_api_name, 'pick_uom', 'Handle Pick UOM');
7977        END IF;
7978 
7979        IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
7980                AND p_needed_quantity < g_locs(p_record_id).quantity)
7981            OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
7982                AND p_needed_sec_quantity < g_locs(p_record_id).secondary_quantity)
7983        THEN
7984           l_possible_quantity := p_needed_quantity;
7985           l_sec_possible_quantity := p_needed_sec_quantity; -- bug 10228168
7986        ELSE
7987           l_possible_quantity := g_locs(p_record_id).quantity;
7988           l_sec_possible_quantity := g_locs(p_record_id).secondary_quantity; -- bug 10228168
7989        END IF;
7990 
7991        IF g_consists.EXISTS(l_cur_group) THEN
7992           l_needed_quantity  := p_needed_quantity - g_consists(l_cur_group).quantity;
7993           l_sec_needed_quantity  := p_needed_sec_quantity - g_consists(l_cur_group).secondary_quantity;
7994 
7995           IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_possible_quantity > l_needed_quantity)
7996               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_possible_quantity > l_sec_needed_quantity)
7997           THEN
7998              l_possible_quantity := l_needed_quantity;
7999              l_sec_possible_quantity := l_sec_needed_quantity; -- bug 10228168
8000           END IF;
8001        END IF;
8002 
8003        IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN --{
8004           IF NVL(g_locs(p_record_id).uom_code, p_secondary_uom) <> p_secondary_uom THEN --{
8005              IF g_locs(p_record_id).uom_code = p_primary_uom THEN
8006                 l_possible_uom_qty := l_possible_quantity;
8007                 l_orig_poss_uom_qty := l_possible_uom_qty;
8008                 l_possible_uom_qty := FLOOR(l_possible_uom_qty);
8009                 l_sec_possible_quantity := ROUND( (l_possible_uom_qty/l_orig_poss_uom_qty)
8010                                                   * l_sec_possible_quantity, 5);
8011                 l_possible_quantity := l_possible_uom_qty;
8012              ELSE --{
8013                 IF l_debug = 1 THEN
8014                    log_statement(l_api_name, 'start_uom_conversion', 'Converting from secondary uom to pick uom');
8015                 END IF;
8016                 -- convert from primary uom to pick uom
8017                 l_possible_uom_qty := inv_convert.inv_um_convert(
8018                                         p_inventory_item_id
8019                                       , NULL
8020                                       , l_sec_possible_quantity
8021                                       , p_secondary_uom
8022                                       , g_locs(p_record_id).uom_code
8023                                       , NULL
8024                                       , NULL
8025                                       );
8026 
8027                 -- if no conversion defined or some error in conversion,
8028                 -- inv_um_convert returns -99999.  In this case, don't carry
8029                 -- out any more conversion functions.  possible quantity
8030                 -- remains unchanged
8031                 IF (l_possible_uom_qty <> -99999) THEN
8032                    -- don't want to pick fractional amounts of pick uom
8033                    l_orig_poss_uom_qty := l_possible_uom_qty;
8034                    l_possible_uom_qty := FLOOR(l_possible_uom_qty);
8035                    IF l_debug = 1 THEN
8036                       log_statement(l_api_name, 'to_secondary_uom', 'Converting from pick uom to secondary uom');
8037                    END IF;
8038                    -- convert back to secondary uom
8039                    l_sec_possible_quantity := inv_convert.inv_um_convert(
8040                                                 p_inventory_item_id
8041                                               , NULL
8042                                               , l_possible_uom_qty
8043                                               , g_locs(p_record_id).uom_code
8044                                               , p_secondary_uom
8045                                               , NULL
8046                                               , NULL
8047                                               );
8048 
8049                    l_possible_quantity := ROUND( (l_possible_uom_qty/l_possible_uom_qty)
8050                                                  * l_possible_quantity,5);
8051                    IF l_debug = 1 THEN
8052                       log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: '
8053                                                  || l_possible_quantity);
8054                       log_statement(l_api_name, 'after_pick_uom_convert', 'Possible sec qty after conversion for pick uom: '
8055                                                  || l_sec_possible_quantity);
8056                    END IF;
8057                 END IF;
8058              END IF; --}
8059           END IF; --}
8060        --}
8061        ELSE --{
8062           IF NVL(g_locs(p_record_id).uom_code, p_primary_uom) <> p_primary_uom
8063           THEN --{
8064              IF g_locs(p_record_id).uom_code = p_secondary_uom THEN
8065                 l_possible_uom_qty := l_sec_possible_quantity;
8066                 l_orig_poss_uom_qty := l_possible_uom_qty;
8067                 l_possible_uom_qty := FLOOR(l_possible_uom_qty);
8068                 l_possible_quantity := ROUND( (l_possible_uom_qty/l_orig_poss_uom_qty)
8069                                               * l_possible_quantity, 5);
8070                 l_sec_possible_quantity := l_possible_uom_qty;
8071              ELSE --{
8072                 IF l_debug = 1 THEN
8073                    log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
8074                 END IF;
8075                 -- convert from primary uom to pick uom
8076                 l_possible_uom_qty := inv_convert.inv_um_convert(
8077                                         p_inventory_item_id
8078                                       , NULL
8079                                       , l_possible_quantity
8080                                       , p_primary_uom
8081                                       , g_locs(p_record_id).uom_code
8082                                       , NULL
8083                                       , NULL
8084                                       );
8085 
8086                 -- if no conversion defined or some error in conversion,
8087                 -- inv_um_convert returns -99999.  In this case, don't carry
8088                 -- out any more conversion functions.  possible quantity
8089                 -- remains unchanged
8090                 IF (l_possible_uom_qty <> -99999) THEN
8091                    -- don't want to pick fractional amounts of pick uom
8092                    l_orig_poss_uom_qty := l_possible_uom_qty;
8093                    l_possible_uom_qty := FLOOR(l_possible_uom_qty);
8094                    IF l_debug = 1 THEN
8095                       log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
8096                    END IF;
8097                    -- convert back to primary uom
8098                    l_possible_quantity := inv_convert.inv_um_convert(
8099                                              p_inventory_item_id
8100                                            , NULL
8101                                            , l_possible_uom_qty
8102                                            , g_locs(p_record_id).uom_code
8103                                            , p_primary_uom
8104                                            , NULL
8105                                            , NULL
8106                                            );
8107                    l_sec_possible_quantity := ROUND( (l_possible_uom_qty/l_orig_poss_uom_qty)
8108                                                      * l_sec_possible_quantity,5);
8109                    IF l_debug = 1 THEN
8110                       log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: '
8111                                                  || l_possible_quantity);
8112                       log_statement(l_api_name, 'after_pick_uom_convert', 'Possible sec qty after conversion for pick uom: '
8113                                                  || l_sec_possible_quantity);
8114                    END IF;
8115                 END IF;
8116              END IF; --}
8117           END IF; --}
8118        END IF; --}
8119        x_remaining_quantity := g_locs(p_record_id).quantity - l_possible_quantity;
8120        x_remaining_sec_qty := g_locs(p_record_id).secondary_quantity - l_sec_possible_quantity;
8121     --}
8122     ELSE
8123        -- don't update the g_loc.quantity here.  It'll get updated in Apply.
8124        x_remaining_quantity := 0;
8125        x_remaining_sec_qty := 0;
8126        l_possible_quantity := g_locs(p_record_id).quantity;
8127        l_sec_possible_quantity := g_locs(p_record_id).secondary_quantity; -- bug 10228168
8128 
8129        IF l_debug = 1 THEN
8130           log_statement(l_api_name, 'in else of p_use_pick_uom >> ', 'l_possible_quantity: '||l_possible_quantity);
8131           log_statement(l_api_name, 'in else of p_use_pick_uom >> ', 'l_sec_possible_quantity: '||l_sec_possible_quantity);
8132        END IF;
8133     END IF;
8134 
8135     IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_possible_quantity <= 0)
8136         OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_possible_quantity <= 0)
8137     THEN
8138        x_finished  := FALSE;
8139        RETURN;
8140     END IF;
8141 
8142     -- If group does exist
8143     IF g_consists.EXISTS(l_cur_group) THEN
8144        IF l_debug = 1 THEN
8145           log_statement(l_api_name, 'group_exists', 'The consist group already exists');
8146        END IF;
8147        -- set pointer values
8148        -- Bug#4361016.Addedthe below IF Block to make sure that no node has next_rec
8149        -- pointer pointing to itself because this causes infinite loop.
8150        IF (g_consists(l_cur_group).last_rec = p_record_id) THEN
8151           g_locs(g_consists(l_cur_group).last_rec).next_rec := 0;
8152        ELSE
8153           g_locs(g_consists(l_cur_group).last_rec).next_rec := p_record_id;
8154        END IF;
8155        g_consists(l_cur_group).last_rec := p_record_id;
8156        -- increase group quantity
8157        g_consists(l_cur_group).quantity := g_consists(l_cur_group).quantity + l_possible_quantity;
8158        g_consists(l_cur_group).secondary_quantity := g_consists(l_cur_group).secondary_quantity + l_sec_possible_quantity; -- bug 10228168
8159     ELSE
8160        -- If group does not exist
8161        IF l_debug =1 THEN
8162           log_statement(l_api_name, 'new_group', 'Creating a new consist group');
8163        END IF;
8164        -- create new group
8165        g_consists(l_cur_group).consist_string  := g_locs(p_record_id).consist_string;
8166        g_consists(l_cur_group).first_rec       := p_record_id;
8167        g_consists(l_cur_group).last_rec        := p_record_id;
8168        g_consists(l_cur_group).next_group      := 0;
8169        g_consists(l_cur_group).quantity        := l_possible_quantity;
8170        g_consists(l_cur_group).secondary_quantity := l_sec_possible_quantity; -- bug 10228168
8171        g_consists(l_cur_group).order_by_rank   := p_order_by_rank;
8172 
8173        IF g_first_consist_group = 0 THEN
8174           g_first_consist_group  := l_cur_group;
8175        ELSE
8176          g_consists(g_last_consist_group).next_group  := l_cur_group;
8177        END IF;
8178 
8179        g_last_consist_group                    := l_cur_group;
8180     END IF;
8181 
8182     -- If group quantity >= needed qty and the consist group in the first
8183     -- set of records by sort criteria
8184     IF ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
8185               AND g_consists(l_cur_group).quantity >= p_needed_quantity)
8186           OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
8187               AND g_consists(l_cur_group).secondary_quantity >= p_needed_sec_quantity)
8188        ) AND g_consists(l_cur_group).order_by_rank = g_first_order_by_rank
8189     THEN --{
8190        IF l_debug = 1 THEN
8191           log_statement(l_api_name, 'alloc_group', 'The consist group has enough quantity to allocation. '
8192                                      || 'Calling allocate_consist_group.');
8193           log_statement(l_api_name, 'alloc_group', 'p_needed_quantity ' || p_needed_quantity);
8194           log_statement(l_api_name, 'alloc_group', 'p_primary_uom ' || p_primary_uom);
8195           log_statement(l_api_name, 'alloc_group', 'p_needed_sec_quantity ' || p_needed_sec_quantity);
8196           log_statement(l_api_name, 'alloc_group', 'p_secondary_uom ' || p_secondary_uom);
8197        END IF;
8198 
8199        -- call allocate_consist_group
8200        allocate_consist_group(
8201          x_return_status              => x_return_status
8202        , x_msg_count                  => x_msg_count
8203        , x_msg_data                   => x_msg_data
8204        , p_group_id                   => l_cur_group
8205        , p_needed_quantity            => p_needed_quantity
8206        , p_use_pick_uom               => p_use_pick_uom
8207        , p_organization_id            => p_organization_id
8208        , p_inventory_item_id          => p_inventory_item_id
8209        , p_to_subinventory_code       => p_to_subinventory_code
8210        , p_to_locator_id              => p_to_locator_id
8211        , p_to_cost_group_id           => p_to_cost_group_id
8212        , p_primary_uom                => p_primary_uom
8213        , p_transaction_uom            => p_transaction_uom
8214        , p_transaction_temp_id        => p_transaction_temp_id
8215        , p_type_code                  => p_type_code
8216        , p_rule_id                    => p_rule_id
8217        , p_reservation_id             => p_reservation_id
8218        , p_tree_id                    => p_tree_id
8219        , p_debug_on                   => p_debug_on
8220        , p_needed_sec_quantity        => p_needed_sec_quantity -- l_sec_needed_quantity; bug 10228168
8221        , p_secondary_uom              => p_secondary_uom
8222        , p_grade_code                 => p_grade_code
8223        , p_lot_divisible_flag         => inv_cache.item_rec.lot_divisible_flag
8224        , x_success                    => x_finished
8225        , p_orig_needed_quantity       => p_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
8226        , p_orig_needed_sec_qty        => p_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
8227        , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
8228        );
8229 
8230        IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8231           IF l_debug = 1 THEN
8232              log_error(l_api_name, 'uerr_alloc_consist_group', 'Unexpected error in allocate_consist_group');
8233           END IF;
8234           RAISE fnd_api.g_exc_unexpected_error;
8235        ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8236           IF l_debug = 1 THEN
8237              log_error(l_api_name, 'err_alloc_consist_group', 'Error in allocate_consist_group');
8238           END IF;
8239           RAISE fnd_api.g_exc_error;
8240        END IF;
8241     END IF; --}
8242 
8243     x_return_status  := fnd_api.g_ret_sts_success;
8244     IF l_debug = 1 THEN
8245        log_procedure(l_api_name, 'end', 'End Insert_Consist_Record');
8246     END IF;
8247   EXCEPTION
8248     WHEN fnd_api.g_exc_error THEN
8249       x_return_status  := fnd_api.g_ret_sts_error;
8250       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
8251       IF l_debug = 1 THEN
8252          log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
8253       END IF;
8254      --
8255     WHEN fnd_api.g_exc_unexpected_error THEN
8256       x_return_status  := fnd_api.g_ret_sts_unexp_error;
8257       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
8258       IF l_debug = 1 THEN
8259          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
8260       END IF;
8261 
8262     WHEN OTHERS THEN
8263       x_return_status  := fnd_api.g_ret_sts_unexp_error;
8264 
8265       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
8266         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
8267       END IF;
8268 
8269       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
8270       IF l_debug = 1 THEN
8271          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
8272       END IF;
8273 
8274   END insert_consist_record;
8275 
8276 
8277   PROCEDURE invalidate_lpn_group(p_lpn_id IN NUMBER) IS
8278     l_api_name   VARCHAR2(30) := 'invalidate_lpn_group';
8279     l_prev_group NUMBER;
8280     l_next_group NUMBER;
8281     l_debug      NUMBER;
8282   BEGIN
8283     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
8284        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
8285     END IF;
8286     l_debug := g_debug;
8287     IF l_debug = 1 THEN
8288        log_procedure(l_api_name, 'start', 'Start Invalidate_Lpn_Group');
8289        log_statement(l_api_name, 'lpn', 'Invalidating LPN: ' || p_lpn_id);
8290     END IF;
8291     g_lpns(p_lpn_id).total_quantity  := -1;
8292     l_prev_group                     := g_lpns(p_lpn_id).prev_group;
8293     l_next_group                     := g_lpns(p_lpn_id).next_group;
8294     IF l_debug = 1 THEN
8295        log_statement(l_api_name, 'prev', 'Prev LPN: ' || l_prev_group);
8296        log_statement(l_api_name, 'next', 'Next LPN: ' || l_next_group);
8297     END IF;
8298 
8299     IF l_prev_group <> 0 THEN
8300       g_lpns(l_prev_group).next_group  := l_next_group;
8301     END IF;
8302 
8303     IF l_next_group <> 0 THEN
8304       g_lpns(l_next_group).prev_group  := l_prev_group;
8305     END IF;
8306 
8307     IF p_lpn_id = g_first_lpn_group THEN
8308       g_first_lpn_group  := l_next_group;
8309 
8310       IF g_first_lpn_group = 0 THEN
8311         g_first_order_by_rank  := NULL;
8312       ELSE
8313         g_first_order_by_rank  := g_lpns(g_first_lpn_group).order_by_rank;
8314       END IF;
8315     END IF;
8316 
8317     IF g_last_lpn_group = p_lpn_id THEN
8318       g_last_lpn_group  := l_next_group;
8319     END IF;
8320     IF l_debug = 1 THEN
8321        log_procedure(l_api_name, 'end', 'End Invalidate_Lpn_Group');
8322     END IF;
8323   END invalidate_lpn_group;
8324 
8325   --bug 2349283 - the INV_Validate function updates the locator table,
8326   --thus locking the table.  The UpdateLocCapacity function called in
8327   --Apply for putaway rules also updates the locator table, but in a
8328   -- different session.  It tries to get a lock on the table, but
8329   --can't.  So, we get a deadlock.  To resolve this, we make this
8330   -- function a autonomous transaction, and issue a commit at the end.
8331   FUNCTION doprojectcheck(
8332     x_return_status  OUT NOCOPY    VARCHAR2
8333   , p_locator_id     IN            NUMBER
8334   , p_project_id     IN            NUMBER
8335   , p_task_id        IN            NUMBER
8336   , x_new_locator_id IN OUT NOCOPY NUMBER
8337   , x_exist_locator_id        OUT NOCOPY NUMBER --Added bug3237702
8338   )
8339     RETURN BOOLEAN IS
8340     PRAGMA AUTONOMOUS_TRANSACTION;
8341     /*l_locator inv_validate.LOCATOR;
8342     l_org     inv_validate.org;
8343     l_sub     inv_validate.sub;*/
8344     success   NUMBER;
8345     retval    BOOLEAN;
8346   BEGIN
8347    x_exist_locator_id := NULL;
8348     -- If the current locator doesn't have the project and task segments
8349     -- populated, then check if another there is a logical locator for this
8350     -- one with the required
8351     -- project and task and return FALSE. If none exists then create one and
8352     -- return TRUE. If the locator has a project and task that is not equal
8353     -- to the required then return FALSE.
8354     /*SELECT *
8355       INTO l_locator
8356       FROM mtl_item_locations
8357      WHERE inventory_location_id = p_locator_id; Commented bug3237702*/
8358      -- Cache for better performance
8359     if nvl(g_locator_id,-9999) <> p_locator_id THEN
8360        SELECT *
8361        INTO g_locator
8362        FROM MTL_ITEM_LOCATIONS
8363        WHERE inventory_location_id = p_locator_id;
8364     end if;
8365    --Added bug3237702 ends
8366 
8367     --bug 2797980 - added NVL to handle case where task is NULL
8368    IF (g_locator.project_id = p_project_id AND
8369       NVL(g_locator.task_id,-1) = NVL(p_task_id,-1)) THEN
8370      x_new_locator_id := p_locator_id;
8371      RETURN TRUE;
8372   ELSE
8373         IF g_locator.project_id IS NOT NULL THEN
8374            RETURN FALSE;
8375         END IF;
8376   END IF;
8377 
8378   g_locator.inventory_location_id := null;
8379   g_locator.physical_location_id := p_locator_id;
8380   g_locator.project_id := p_project_id;
8381   g_locator.task_id := p_task_id;
8382   g_locator.segment19 := p_project_id;
8383   g_locator.segment20 := p_task_id;
8384 
8385   -- Cache for better performance
8386   retval := inv_cache.set_org_rec(g_locator.organization_id);
8387 /*
8388   select *
8389   into l_org
8390   from mtl_parameters
8391   where organization_id = l_locator.organization_id;
8392 */
8393   retval := inv_cache.set_tosub_rec(g_locator.organization_id, g_locator.subinventory_code);
8394 /*  select *
8395   into l_sub
8396   from mtl_secondary_inventories
8397   where secondary_inventory_name = l_locator.subinventory_code
8398   and organization_id = l_locator.organization_id;
8399 */
8400   success := INV_Validate.ValidateLocator(
8401                  p_locator => g_locator,
8402                  p_org => inv_cache.org_rec,
8403                  p_sub => inv_cache.tosub_rec,
8404                  p_validation_mode => INV_Validate.EXISTS_OR_CREATE,
8405                  p_value_or_id => 'I');
8406 
8407   COMMIT;
8408 
8409   x_new_locator_id := g_locator.inventory_location_id;
8410   if( success = INV_Validate.T and FND_FLEX_KEYVAL.new_combination) then
8411      return TRUE;
8412   END IF;
8413 
8414   x_exist_locator_id := g_locator.inventory_location_id;
8415   -- Locator with project segments already exists
8416   return FALSE;
8417 END DoProjectCheck;
8418 
8419   --
8420   -- API name    : Apply
8421   -- Type        : Private
8422   -- Function    : Applies a wms rule to the given transaction
8423   --               input parameters and creates recommendations
8424   -- Pre-reqs    : Record in WMS_STRATEGY_MAT_TXN_TMP_V uniquely
8425   --               identified by parameters p_transaction_temp_id and
8426   --               p_type_code ( base table for the view is
8427   --               MTL_MATERIAL_TRANSACTIONS_TEMP );
8428   --               At least one transaction detail record in
8429   --               WMS_TRX_DETAILS_TMP_V identified by line type code = 1
8430   --               and parameters p_transaction_temp_id and p_type_code
8431   --               ( base tables are MTL_MATERIAL_TRANSACTIONS_TEMP and
8432   --               WMS_TRANSACTIONS_TEMP, respectively );
8433   --               Rule record has to exist in WMS_RULES_B uniquely
8434   --               identified by parameter p_rule_id;
8435   --     Package WMS_RULE_(RULEID) must exist;
8436   --               If picking, quantity tree has to exist, created through
8437   --               INV_Quantity_Tree_PVT.Create_Tree and uniquely identified
8438   --               by parameter p_tree_id
8439   -- Parameters  :
8440   --   p_api_version          Standard Input Parameter
8441   --   p_init_msg_list        Standard Input Parameter
8442   --   p_commit               Standard Input Parameter
8443   --   p_validation_level     Standard Input Parameter
8444   --   p_rule_id              Identifier of the rule to apply
8445   --   p_type_code            Type code of the rule
8446   --   p_partial_success_allowed_flag
8447   --            'Y' or 'N'
8448   --   p_transaction_temp_id  Identifier for the record in view
8449   --            wms_strategy_mat_txn_tmp_v that represents
8450   --            the request for detailing
8451   --   p_organization_id      Organization identifier
8452   --   p_inventory_item_id    Inventory item identifier
8453   --   p_transaction_uom      Transaction UOM code
8454   --   p_primary_uom          Primary UOM code
8455   --   p_tree_id              Identifier for the quantity tree
8456   --
8457   -- Output Parameters
8458   --   x_return_status        Standard Output Parameter
8459   --   x_msg_count            Standard Output Parameter
8460   --   x_msg_data             Standard Output Parameter
8461   --   x_finished             whether the rule has found enough quantity to
8462   --                          find a location that completely satisfy
8463   --                          the requested quantity (value is 'Y' or 'N')
8464   --
8465   -- Version
8466   --   Currently version is 1.0
8467   --
8468   -- Notes       : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
8469   --               This API must be called internally by
8470   --               WMS_Strategy_PVT.Apply only !
8471   --APPLY
8472   PROCEDURE apply(
8473     p_api_version                  IN            NUMBER
8474   , p_init_msg_list                IN            VARCHAR2
8475   , p_commit                       IN            VARCHAR2
8476   , p_validation_level             IN            NUMBER
8477   , x_return_status                OUT NOCOPY    VARCHAR2
8478   , x_msg_count                    OUT NOCOPY    NUMBER
8479   , x_msg_data                     OUT NOCOPY    VARCHAR2
8480   , p_rule_id                      IN            NUMBER
8481   , p_type_code                    IN            NUMBER
8482   , p_partial_success_allowed_flag IN            VARCHAR2
8483   , p_transaction_temp_id          IN            NUMBER
8484   , p_organization_id              IN            NUMBER
8485   , p_inventory_item_id            IN            NUMBER
8486   , p_transaction_uom              IN            VARCHAR2
8487   , p_primary_uom                  IN            VARCHAR2
8488   , p_secondary_uom                IN            VARCHAR2                 -- new
8489   , p_grade_code                   IN            VARCHAR2                 -- new
8490   , p_transaction_type_id          IN            NUMBER
8491   , p_tree_id                      IN            NUMBER
8492   , x_finished                     OUT NOCOPY    VARCHAR2
8493   , p_detail_serial                IN            BOOLEAN
8494   , p_from_serial                  IN            VARCHAR2
8495   , p_to_serial                    IN            VARCHAR2
8496   , p_detail_any_serial            IN            NUMBER
8497   , p_unit_volume                  IN            NUMBER
8498   , p_volume_uom_code              IN            VARCHAR2
8499   , p_unit_weight                  IN            NUMBER
8500   , p_weight_uom_code              IN            VARCHAR2
8501   , p_base_uom_code                IN            VARCHAR2
8502   , p_lpn_id                       IN            NUMBER
8503   , p_unit_number                  IN            VARCHAR2
8504   , p_simulation_mode              IN            NUMBER
8505   , p_project_id                   IN            NUMBER
8506   , p_task_id                      IN            NUMBER
8507   , p_wave_simulation_mode         IN   VARCHAR2 DEFAULT 'N'
8508   ) IS
8509     -- API standard variables
8510     l_api_version   CONSTANT NUMBER                                              := 1.0;
8511     l_api_name      CONSTANT VARCHAR2(30)                                        := 'Apply';
8512     -- variables needed for dynamic SQL
8513     l_cursor                 INTEGER;
8514     l_rows                   INTEGER;
8515     -- rule dynamic SQL input variables
8516     l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE;
8517     l_revision               wms_transactions_temp.revision%TYPE;
8518     l_lot_number             wms_transactions_temp.lot_number%TYPE;
8519     l_lot_expiration_date    wms_transactions_temp.lot_expiration_date%TYPE;
8520     l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
8521     l_to_subinventory_code   wms_transactions_temp.to_subinventory_code%TYPE;
8522     l_subinventory_code      wms_transactions_temp.to_subinventory_code%TYPE;
8523     l_from_locator_id        wms_transactions_temp.from_locator_id%TYPE;
8524     l_to_locator_id          wms_transactions_temp.to_locator_id%TYPE;
8525     l_locator_id             wms_transactions_temp.to_locator_id%TYPE;
8526     l_from_cost_group_id     wms_transactions_temp.from_cost_group_id%TYPE;
8527     l_to_cost_group_id       wms_transactions_temp.to_cost_group_id%TYPE;
8528     l_cost_group_id          wms_transactions_temp.to_cost_group_id%TYPE;
8529     l_lpn_id                 wms_transactions_temp.lpn_id%TYPE;
8530     l_initial_pri_quantity   wms_transactions_temp.primary_quantity%TYPE;
8531     l_initial_sec_quantity   wms_transactions_temp.secondary_quantity%TYPE;
8532     -- rule dynamic SQL output variables
8533     l_orevision              wms_transactions_temp.revision%TYPE;
8534     l_olot_number            wms_transactions_temp.lot_number%TYPE;
8535     l_olot_expiration_date   wms_transactions_temp.lot_expiration_date%TYPE;
8536     l_osubinventory_code     wms_transactions_temp.from_subinventory_code%TYPE;
8537     l_olocator_id            wms_transactions_temp.from_locator_id%TYPE;
8538     l_olocator_id_prev       wms_transactions_temp.from_locator_id%TYPE;
8539     l_olocator_id_new        wms_transactions_temp.from_locator_id%TYPE;
8540     l_ocost_group_id         wms_transactions_temp.from_cost_group_id%TYPE;
8541     l_olpn_id                wms_transactions_temp.lpn_id%TYPE;
8542     l_possible_quantity      wms_transactions_temp.primary_quantity%TYPE;
8543     l_possible_trx_qty       wms_transactions_temp.transaction_quantity%TYPE;
8544     l_sec_possible_quantity  wms_transactions_temp.secondary_quantity%TYPE;
8545     l_reservation_id         wms_transactions_temp.reservation_id%TYPE;
8546     -- variables needed for qty tree
8547     l_qoh                    NUMBER;
8548     l_rqoh                   NUMBER;
8549     l_qr                     NUMBER;
8550     l_qs                     NUMBER;
8551     l_att                    NUMBER;
8552     l_atr                    NUMBER;
8553     l_sqoh                   NUMBER;
8554     l_srqoh                  NUMBER;
8555     l_sqr                    NUMBER;
8556     l_sqs                    NUMBER;
8557     l_satt                   NUMBER;
8558     l_satr                   NUMBER;
8559     --
8560     l_rule_func_sql          LONG;
8561     l_rule_result            NUMBER;
8562     l_dummy                  NUMBER;
8563     l_pack_exists            NUMBER;
8564     l_serial_control_code    NUMBER;
8565     l_is_serial_control      NUMBER;
8566     l_package_name           VARCHAR2(128);
8567     l_msg_data               VARCHAR2(240);
8568     l_msg_count              NUMBER;
8569     l_rule_id                NUMBER;
8570     l_unit_number            VARCHAR2(30);
8571     --variables related to pick by UOM
8572     l_uom_code               VARCHAR2(3);
8573     l_order_by_string        VARCHAR2(1000);
8574     l_consist_string         VARCHAR2(1000);
8575     l_cur_order_by_string    VARCHAR2(1000)                                      := '-9999999';
8576     l_default_pick_rule      NUMBER;
8577     l_default_put_rule       NUMBER;
8578     l_allowed                VARCHAR2(1);
8579     l_loc_avail_units        NUMBER;
8580     l_capacity_updated       BOOLEAN;
8581     l_consider_staging_capacity   BOOLEAN; --Added bug3237702
8582     l_return_status          VARCHAR2(1);
8583     l_consist_exists         BOOLEAN;
8584     l_comingle               VARCHAR2(1);
8585     l_serial_number          VARCHAR2(30);
8586     l_detail_serial          NUMBER;
8587     l_found                  BOOLEAN;
8588     l_first_serial           NUMBER;
8589     l_locs_index             NUMBER; --index to v_locs table
8590     l_debug_on               BOOLEAN;
8591     l_uom_index              NUMBER;
8592     l_lpn_controlled_flag    NUMBER;
8593     l_check_cg               BOOLEAN;
8594     l_restrict_subs_code     NUMBER;
8595     l_restrict_locs_code     NUMBER;
8596     l_quantity_function      NUMBER;
8597     v_current_row            t_location_rec;
8598     --added to support allocation mode
8599     l_cur_lpn_group          NUMBER;
8600     l_cur_lpn_rec            NUMBER;
8601     l_inserted_record        BOOLEAN;
8602     l_needed_quantity        NUMBER;
8603     l_expected_quantity      NUMBER;
8604     l_allocated_quantity     NUMBER;
8605     l_remaining_quantity     NUMBER;
8606     l_allocation_mode        NUMBER;
8607     l_sec_needed_quantity    NUMBER;                          -- new
8608     l_sec_expected_quantity  NUMBER;                          -- new
8609     l_sec_allocated_quantity NUMBER;                          -- new
8610     l_sec_remaining_quantity NUMBER;                          -- new
8611     l_grade_code             VARCHAR2(150);                   -- new
8612     l_cur_uom_rec            NUMBER;
8613     l_first_uom_rec          NUMBER;
8614     l_last_uom_rec           NUMBER;
8615     l_finished               BOOLEAN;
8616     l_cur_consist_group      NUMBER;
8617     l_use_pick_uom           BOOLEAN;
8618     l_order_by_rank          NUMBER                                              := 0;
8619     l_cur_rec                NUMBER;
8620     l_prev_rec               NUMBER;
8621     l_next_rec               NUMBER;
8622     l_hash_size              NUMBER;
8623     l_sub_rsv_type         NUMBER;
8624 
8625     --added to support pjm
8626     l_project_id             NUMBER;
8627     l_oproject_id            NUMBER;
8628     l_task_id                NUMBER;
8629     l_otask_id               NUMBER;
8630     l_input_lpn_id           NUMBER;
8631     -- Initilization of Ref cursors for Pick and putaway rules
8632     -- Added to pass into DoProjectCheck new parameter used in other apply procedure  Bug3237702
8633     l_dummy_loc              NUMBER;
8634     v_pick_cursor            wms_rule_pvt.cv_pick_type;
8635     v_put_cursor             wms_rule_pvt.cv_put_type;
8636     l_debug                  NUMBER;   -- 1 for debug is on , 0 for debug is off
8637     l_progress               VARCHAR2(10);  -- local variable to track program progress,
8638                                             -- especially useful when exception occurs
8639     l_rule_counter           INTEGER;
8640 
8641     ---- Mat Status Check Variables
8642     l_serial_trx_allowed        VARCHAR2(1);
8643     l_sub_loc_lot_trx_allowed   VARCHAR2(1);
8644     l_serial_status_id          NUMBER;
8645 
8646     ---
8647 
8648     l_serial_status   INV_CACHE.ITEM_REC.serial_status_enabled%TYPE;
8649     l_lot_status      INV_CACHE.ITEM_REC.lot_status_enabled%TYPE;
8650 
8651     ---- End Mat Status Var
8652 
8653     l_lot_divisible_flag       VARCHAR2(1);
8654 
8655     l_rule_override_flag       VARCHAR2(1);
8656     l_lot_control_code         NUMBER;
8657     l_revision_control_code    NUMBER;
8658     l_grade_control_flag       VARCHAR2(1);
8659     l_reservation_is_detailed  VARCHAR2(1);
8660     l_sl_rsv_is_detailed       VARCHAR2(1);
8661 
8662     l_return_value             BOOLEAN; -- [ Added ]
8663    ---
8664     l_allocate_serial_flag     VARCHAR2(1);
8665     l_custom_select_serials    INV_DETAIL_UTIL_PVT.g_serial_row_table_rec;
8666     l_custom_serial_index      NUMBER;
8667 
8668     -- Lot Indivisible Var
8669     l_max_tolerance            NUMBER;
8670     l_max_sec_tolerance        NUMBER;
8671     l_min_tolerance            NUMBER;
8672     l_min_sec_tolerance        NUMBER;
8673 
8674     -- LPN Status Project
8675     l_onhand_status_trx_allowed VARCHAR2(1);
8676     l_default_status_id        NUMBER ;
8677     -- LPN Status Project
8678     l_default_inv_pick_rule  NUMBER;      --added for bug8310188
8679     l_wms_enabled_flag       VARCHAR2(1); --added for bug8310188
8680     l_source_type_id         NUMBER; --12687878
8681     l_source_header_id       NUMBER; --12687878
8682     l_source_line_id         NUMBER; --12687878
8683     l_orig_needed_quantity   NUMBER := 0; -- Added for 14699845 (Flexible lot allocation)
8684     l_orig_needed_sec_qty    NUMBER := 0; -- Added for 14699845 (Flexible lot allocation)
8685 
8686     --cursor used to determine if suggestions should be minimized
8687     -- for this rule.  This flag affects how the Pick UOM functionality
8688     -- works.
8689     CURSOR c_allocation_mode IS
8690       SELECT allocation_mode_id
8691            , qty_function_parameter_id
8692         FROM wms_rules_b
8693        WHERE rule_id = l_rule_id;
8694 
8695     --cursor used to determine if rule has any consistency requirements
8696     CURSOR l_consist IS
8697       SELECT consistency_id
8698         FROM wms_rule_consistencies
8699        WHERE rule_id = l_rule_id;
8700 
8701     --cursor to get the total quantity for the LPN
8702     CURSOR c_lpn_quantity IS
8703       SELECT SUM(primary_transaction_quantity)
8704            , NVL(SUM(secondary_transaction_quantity),0)
8705         FROM mtl_onhand_quantities_detail
8706        WHERE lpn_id = v_current_row.lpn_id;
8707 
8708     --Bug 5251221, cursor to get the serials which are allocated for the current rule
8709     CURSOR l_get_serial IS
8710        SELECT serial_number FROM wms_transactions_temp
8711        WHERE rule_id = l_rule_id;
8712 
8713 
8714   BEGIN
8715     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
8716        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
8717     END IF;
8718     l_debug := g_debug;
8719     l_progress := 10;
8720 
8721     -- debugging portion
8722     -- can be commented ut for final code
8723     IF (NVL(inv_cache.is_pickrelease, FALSE) OR p_wave_simulation_mode = 'Y') THEN
8724        IF (l_debug = 1) THEN
8725           log_event(l_api_name, 'Check if Pick Release', 'True');
8726        END IF;
8727        l_consider_staging_capacity := FALSE;
8728     ELSE
8729        IF (l_debug = 1) THEN
8730           log_event(l_api_name, 'Check if Pick Release', 'False');
8731        END IF;
8732        l_consider_staging_capacity := TRUE;
8733     END IF;
8734 
8735     IF l_debug = 1 THEN
8736        log_procedure(l_api_name, 'start', 'Start wms_rule_pvt.Apply');
8737        log_event(l_api_name, 'Apply ', 'org_id '||p_organization_id);
8738        log_event(l_api_name, 'Apply ', 'item_id '||p_inventory_item_id);
8739     END IF;
8740     -- end of debugging section
8741     --
8742     -- Standard start of API savepoint
8743     SAVEPOINT applyrulesp;
8744 
8745     -- Standard call to check for call compatibility
8746     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
8747        RAISE fnd_api.g_exc_unexpected_error;
8748     END IF;
8749 
8750     -- Initialize message list if p_init_msg_list is set to TRUE
8751     IF fnd_api.to_boolean(p_init_msg_list) THEN
8752        fnd_msg_pub.initialize;
8753     END IF;
8754 
8755     -- LPN Status Project
8756     IF (inv_cache.set_org_rec(p_organization_id)) THEN
8757        l_default_status_id :=  NVL(inv_cache.org_rec.default_status_id,-1);
8758        IF l_debug = 1 THEN
8759           log_statement(l_api_name, 'Value of l_default_status_id: ', l_default_status_id);
8760        END IF;
8761     END IF;
8762     -- LPN Status Project
8763 
8764     --
8765     -- Initialize API return status to success
8766     x_return_status  := fnd_api.g_ret_sts_success;
8767     --
8768     -- Initialize functional return status to completed
8769     x_finished       := fnd_api.g_true;
8770 
8771     --
8772     -- Validate input parameters and pre-requisites, if validation level
8773     -- requires this
8774     IF p_validation_level <> fnd_api.g_valid_level_none THEN
8775        IF p_type_code IS NULL
8776           OR p_type_code = fnd_api.g_miss_num THEN
8777           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
8778              fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
8779              fnd_msg_pub.ADD;
8780 
8781              IF l_debug = 1 THEN
8782                 log_error_msg(l_api_name, 'type_code_missing');
8783              END IF;
8784 
8785           END IF;
8786 
8787           RAISE fnd_api.g_exc_error;
8788        END IF;
8789 
8790        /* get the org defaults */
8791        IF l_debug = 1 THEN
8792           log_statement(l_api_name,'no_rule','Getting default rule at org level');
8793        END IF;
8794        -- 8809951 start, removed cursors and using INV CACHE
8795        IF (INV_CACHE.set_org_rec(p_organization_id) ) THEN
8796           l_default_pick_rule     := inv_cache.org_rec.default_wms_picking_rule_id;
8797           l_default_put_rule      := inv_cache.org_rec.default_put_away_rule_id;
8798           l_rule_override_flag    := inv_cache.org_rec.rules_override_lot_reservation;
8799           l_default_inv_pick_rule := inv_cache.org_rec.default_picking_rule_id;
8800           l_wms_enabled_flag      := inv_cache.org_rec.wms_enabled_flag;
8801        END If;
8802 
8803        -- 8809951 end
8804        -- changed by jcearley on 11/22/99, b/c a null rule_id is now allowed
8805        -- if rule_id is null, use default rule (0 for put away, 1 for pick)
8806        IF p_rule_id IS NULL
8807           OR p_rule_id = fnd_api.g_miss_num THEN
8808           -- query org parameters to get user's default rule
8809           -- if default rule not defined, use default seeded rule
8810           IF p_type_code = 1 THEN --put away
8811              l_rule_id  := l_default_put_rule;
8812              IF l_rule_id IS NULL THEN
8813                 IF l_debug = 1 THEN
8814                    log_statement(l_api_name, 'no_org_rule_put',
8815                                              'Did not find org default put away rule');
8816                 END IF;
8817                 l_rule_id  := 10;
8818              END IF;
8819           ELSE -- pick
8820              -- start adding code for bug8310188
8821              IF l_wms_enabled_flag ='Y' THEN
8822                 l_rule_id  := l_default_pick_rule;
8823              ELSE
8824                 l_rule_id  := l_default_inv_pick_rule;
8825              END IF ;
8826              -- end adding code for bug8310188
8827              IF l_rule_id IS NULL THEN
8828                 IF l_debug = 1 THEN
8829                    log_statement(l_api_name, 'no_org_rule_put',
8830                                              'Did not find org default put away rule');
8831                 END IF;
8832                 l_rule_id  := 2;
8833              END IF;
8834           END IF;
8835           IF l_debug = 1 THEN
8836              log_statement(l_api_name, 'default_rule',
8837                                        'Rule being used: ' || l_rule_id);
8838           END IF;
8839        ELSE
8840           l_rule_id  := p_rule_id;
8841        END IF;
8842 
8843        IF p_partial_success_allowed_flag IS NULL
8844           OR p_partial_success_allowed_flag = fnd_api.g_miss_char THEN
8845           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
8846              fnd_message.set_name('WMS', 'WMS_PARTIAL_SUCC_FLAG_MISS');
8847              IF l_debug = 1 THEN
8848                 log_error_msg(l_api_name, 'partial_succ_flag_missing');
8849              END IF;
8850              fnd_msg_pub.ADD;
8851           END IF;
8852           RAISE fnd_api.g_exc_error;
8853        END IF;
8854 
8855        IF p_transaction_temp_id IS NULL
8856           OR p_transaction_temp_id = fnd_api.g_miss_num THEN
8857           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
8858              fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
8859              fnd_msg_pub.ADD;
8860              IF l_debug = 1 THEN
8861                 log_error_msg(l_api_name, 'trx_req_line_id_missing');
8862              END IF;
8863           END IF;
8864           RAISE fnd_api.g_exc_error;
8865        END IF;
8866 
8867        IF p_organization_id IS NULL
8868           OR p_organization_id = fnd_api.g_miss_num THEN
8869           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
8870              fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
8871              fnd_msg_pub.ADD;
8872              IF l_debug = 1 THEN
8873                 log_error_msg(l_api_name, 'org_id_missing');
8874              END IF;
8875           END IF;
8876 
8877           RAISE fnd_api.g_exc_error;
8878        END IF;
8879 
8880        IF p_inventory_item_id IS NULL
8881           OR p_inventory_item_id = fnd_api.g_miss_num THEN
8882           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
8883              fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
8884              fnd_msg_pub.ADD;
8885              IF l_debug = 1 THEN
8886                 log_error_msg(l_api_name, 'item_id_missing');
8887              END IF;
8888           END IF;
8889 
8890           RAISE fnd_api.g_exc_error;
8891        END IF;
8892 
8893        IF p_type_code = 2
8894           AND (p_tree_id IS NULL
8895                OR p_tree_id = fnd_api.g_miss_num
8896               )
8897        THEN
8898           IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
8899              fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
8900              fnd_msg_pub.ADD;
8901              IF l_debug = 1 THEN
8902                 log_error_msg(l_api_name, 'qty_tree_id_missing');
8903              END IF;
8904           END IF;
8905           RAISE fnd_api.g_exc_error;
8906        END IF;
8907     END IF;
8908 
8909     -- inv_pp_debug.send_message_to_pipe('finished validations and qty tree init');
8910     --
8911     -- backup qty tree
8912     IF p_type_code = 2 THEN
8913        IF l_debug = 1 THEN
8914           log_statement(l_api_name, 'PICK','PICK');
8915           log_statement(l_api_name, 'backup_tree',
8916                        'Calling inv_quantity_tree_pvt.backup_tree');
8917        END IF;
8918        inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
8919        IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8920           IF l_debug = 1 THEN
8921              log_statement(l_api_name, 'backup_tree_unexp_err',
8922                                        'Unexpected error from inv_quantity_tree_pvt.backup_tree');
8923           END IF;
8924           RAISE fnd_api.g_exc_unexpected_error;
8925        ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8926           IF l_debug = 1 THEN
8927              log_statement(l_api_name, 'backup_tree_err',
8928                                        'Error from inv_quantity_tree_pvt.backup_tree');
8929           END IF;
8930           RAISE fnd_api.g_exc_error;
8931        END IF;
8932        -- does the rule have any consistency restrictions?
8933        OPEN l_consist;
8934        FETCH l_consist INTO l_dummy;
8935        IF l_consist%NOTFOUND THEN
8936           l_consist_exists := FALSE;
8937           IF l_debug = 1 THEN
8938              log_statement(l_api_name, 'consist_exist_false',
8939                                        'Consistencies do not exist');
8940           END IF;
8941        ELSE
8942           l_consist_exists := TRUE;
8943           IF l_debug = 1 THEN
8944              log_statement(l_api_name, 'consist_exist_true', 'Cosistencies exist');
8945           END IF;
8946        END IF;
8947        CLOSE l_consist;
8948     END IF;
8949 
8950     -- Get allocation mode
8951     OPEN c_allocation_mode;
8952     FETCH c_allocation_mode INTO l_allocation_mode, l_quantity_function;
8953     IF c_allocation_mode%NOTFOUND
8954        OR l_allocation_mode IS NULL THEN
8955        -- by default, make allocation mode 3
8956        l_allocation_mode  := 3;
8957     END IF;
8958     CLOSE c_allocation_mode;
8959 
8960 
8961     IF l_allocation_mode IN (3, 4, 5) THEN --value = 5 added for R12.1 replenishment project
8962        l_use_pick_uom  := TRUE;
8963     ELSE
8964        l_use_pick_uom  := FALSE;
8965     END IF;
8966 
8967     -- make sure, everything is clean
8968     freeglobals;
8969     wms_parameter_pvt.clearcache;
8970 
8971     g_trace_recs.DELETE;
8972     l_debug_on := isruledebugon(p_simulation_mode);
8973 
8974     l_return_value := INV_CACHE.set_item_rec(
8975                           p_organization_id,
8976                           p_inventory_item_id);
8977     IF NOT l_return_value THEN
8978        IF l_debug = 1 THEN
8979           log_statement(l_api_name, '-', 'Error setting from sub cache');
8980        END IF;
8981        RAISE fnd_api.g_exc_unexpected_error;
8982     END IF;
8983 
8984     l_serial_control_code   := NVL(inv_cache.item_rec.serial_number_control_code,1);
8985     l_restrict_subs_code    := NVL(inv_cache.item_rec.restrict_subinventories_code, 2);
8986     l_restrict_locs_code    := NVL(inv_cache.item_rec.restrict_locators_code, 2);
8987     l_lot_divisible_flag    := inv_cache.item_rec.lot_divisible_flag;
8988     l_lot_control_code      := inv_cache.item_rec.lot_control_code;
8989     l_revision_control_code := inv_cache.item_rec.revision_qty_control_code;
8990     l_grade_control_flag    := inv_cache.item_rec.grade_control_flag;
8991 
8992     -- Only detail serial numbers if they are prespecified or entered
8993     -- at inventory receipt for this item.
8994     IF p_type_code = 2 THEN -- pick
8995        IF l_serial_control_code IN (2, 5) THEN
8996           l_is_serial_control  := 1;
8997        ELSE
8998           l_is_serial_control  := 0;
8999        END IF;
9000     ELSE
9001        l_is_serial_control  := 0;
9002     END IF;
9003 
9004     IF p_detail_serial = TRUE THEN
9005        l_detail_serial  := 1;
9006     ELSE
9007        l_detail_serial  := 0;
9008     END IF;
9009 
9010     -- Logic to improve the performance for Material Status Checks
9011     -- Getting Values from  INV CACHE  and setting the l_detail_serial flag based on the following algoritham
9012     -- Based on the l_detail_falg, Serial_material status would be checked inside the Rule packages or
9013     -- Rules Engine API.
9014     -- ** Serial Mat.Status Check inside Rule Sql(R) / Engine (E)
9015     /*------------------------------------------------------------------------------------------------
9016      Serial   Serial   Serial      MSN          Group By         Serial Mat.Status     l_detail_serial
9017      Allowed  Status   Rule Objs   to be used   LOT/SUb/Loc  Required    Check in RuleSql
9018      -------------------------------------------------------------------------------------------------
9019      Y          Y       Y           Y             N            Y        Engine            1
9020      Y          Y       N           Y             N            Y          Engine            1
9021      Y          N       Y           Y             N            N        -            2
9022      Y          N       N           Y             N            N        -            2
9023      --------------------------------------------------------------------------------------------------
9024      N          Y       Y           Y             Y            Y        Rule            3
9025      N          Y       N           Y             Y            Y          Rule            3
9026      N          N       Y           Y             Y            N        -            4
9027      N          N       N           N(MOQD)       N            N        -            0
9028     --------------------------------------------------------------------------------------------------*/
9029     IF l_is_serial_control  = 1 THEN
9030        l_serial_status := INV_CACHE.ITEM_REC.serial_status_enabled;
9031        l_lot_status    := INV_CACHE.ITEM_REC.lot_status_enabled;
9032 
9033        IF l_detail_serial = 1 THEN
9034           IF NVL(l_serial_status, 'N')  = 'Y' THEN
9035              l_detail_serial := 1;
9036           ELSE
9037              l_detail_serial := 2;
9038           END IF;
9039        ELSE
9040           IF NVL(l_serial_status, 'N')  = 'Y' THEN
9041              l_detail_serial := 3;
9042           ELSE
9043              l_detail_serial := 0;
9044           END IF;
9045        END IF;
9046 
9047        -- Checking, if any Serial object based attributes used by any Picking rules
9048        IF l_detail_serial =  0 THEN
9049           IF IsSerialObjectUsed( p_organization_id ) THEN
9050              l_detail_serial := 4;
9051           END IF;
9052        END IF;
9053     END IF;
9054 
9055     -- [ If the org level flag is set to use Custom logic for Serial numbers,
9056     -- the MSNT is used but grouped by sub/loc
9057     If p_type_code = 2  THEN
9058        l_allocate_serial_flag := inv_cache.org_rec.allocate_serial_flag;
9059     END IF;
9060 
9061     IF l_allocate_serial_flag = 'C' THEN
9062        l_detail_serial := 4;
9063     END IF;
9064 
9065     IF l_debug = 1 THEN
9066        log_statement(l_api_name, 'l_detail_serial', l_detail_serial);
9067        log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
9068        log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
9069     END IF;
9070 
9071     -- get the name of the rule package
9072     getpackagename(l_rule_id, l_package_name);
9073 
9074     -- Initialize the pointer to the first trx detail input line
9075     wms_re_common_pvt.initinputpointer;
9076 
9077     IF l_debug = 1 THEN
9078        log_statement(l_api_name, 'start_input_loop',
9079                     'Starting loop through input lines');
9080     END IF;
9081     -- Loop through all the trx detail input lines
9082     WHILE TRUE LOOP --{
9083       l_max_tolerance := 0;
9084       l_max_sec_tolerance := 0;
9085       -- Get the next trx detail input line
9086       wms_re_common_pvt.getnextinputline(
9087         l_pp_transaction_temp_id
9088       , l_revision
9089       , l_lot_number
9090       , l_lot_expiration_date
9091       , l_from_subinventory_code
9092       , l_from_locator_id
9093       , l_from_cost_group_id
9094       , l_to_subinventory_code
9095       , l_to_locator_id
9096       , l_to_cost_group_id
9097       , l_needed_quantity
9098       , l_sec_needed_quantity
9099       , l_grade_code
9100       , l_reservation_id
9101       , l_serial_number -- [ new code ]
9102       , l_lpn_id
9103       );
9104       EXIT WHEN l_pp_transaction_temp_id IS NULL;
9105       -- [ roll up the rem_tol_qty for Lot inadvisable items  ,   for picking
9106       --   This logic is not implemented . To be implemented in feature  ]
9107 
9108       -- Added for 14699845 (Flexible lot allocation)
9109       l_orig_needed_quantity := l_needed_quantity;
9110       l_orig_needed_sec_qty  := l_sec_needed_quantity;
9111 
9112       IF l_debug = 1 THEN
9113          log_statement(l_api_name, 'input_rec', 'Got next input line');
9114          log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
9115          log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
9116          log_statement(l_api_name, 'input_serial', 'serial number:' || l_serial_number);
9117          log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
9118          log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
9119          log_statement(l_api_name, 'input_cg', 'cg:'   || l_from_cost_group_id);
9120          log_statement(l_api_name, 'input_tsub', 'tsub:' || l_to_subinventory_code);
9121          log_statement(l_api_name, 'input_tloc', 'tloc:' || l_to_locator_id);
9122          log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
9123          log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
9124          log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
9125          log_statement(l_api_name, 'input_sec_qty', 'sec_qty:' || l_sec_needed_quantity);
9126          log_statement(l_api_name, 'input_qty', 'WMS_Engine_PVT.g_move_order_type:' || WMS_Engine_PVT.g_move_order_type);
9127          log_statement(l_api_name, 'input_qty', 'WMS_Engine_PVT.g_wip_entity_type:' || WMS_Engine_PVT.g_wip_entity_type);
9128          -- Added for 14699845 (Flexible lot allocation)
9129          log_statement(l_api_name, 'input_qty', 'l_orig_needed_quantity: ' || l_orig_needed_quantity);
9130          log_statement(l_api_name, 'input_qty', 'l_orig_needed_sec_qty:  ' || l_orig_needed_sec_qty);
9131       END IF;
9132 
9133       -- [ compute line level tolerances for lot indivisible item for non-reserved lines
9134       --   and the l_needed qty is adjusted to max allowed qty based on the max tol Qty
9135       --   If the tol qty is zero, then the l_needed qty remains unchanged. ]
9136       IF l_lot_divisible_flag = 'N'
9137          AND l_lot_control_code <> 1
9138          AND p_type_code = 2
9139                  AND WMS_Engine_PVT.g_move_order_type = 3
9140          -- and l_reservation_id is null -- Commented code to account for manual reservations
9141       THEN
9142          l_max_tolerance := NVL(g_max_tolerance,0); -- Added NVL for Bug 13612884
9143          l_orig_needed_quantity := l_needed_quantity;  -- Added for 14699845 (Flexible lot allocation)
9144          l_needed_quantity := l_needed_quantity + l_max_tolerance;
9145          IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
9146             l_max_sec_tolerance := NVL(g_max_sec_tolerance,0);
9147             l_orig_needed_sec_qty := l_sec_needed_quantity;  -- Added for 14699845 (Flexible lot allocation)
9148             l_sec_needed_quantity := l_sec_needed_quantity + l_max_sec_tolerance;
9149          END IF;
9150       ELSIF p_type_code = 2
9151             AND (WMS_Engine_PVT.g_move_order_type IN (2,3) --Added mover order type 2 for Over Allocation to be honored for replenishment type move orders bug#9656966
9152                  OR (WMS_Engine_PVT.g_move_order_type IN (5,8) AND WMS_Engine_PVT.g_wip_entity_type IN (9,10)) ) THEN  --BUG14517947
9153          IF g_max_tolerance < 0 THEN
9154             l_max_tolerance   := NVL(g_max_tolerance,0); -- Added NVL for Bug 13612884
9155             l_needed_quantity := l_needed_quantity + l_max_tolerance;
9156          ELSIF l_allocation_mode IN (1, 5) THEN
9157             l_max_tolerance   := NVL(g_max_tolerance,0); -- Added NVL for Bug 13612884
9158             l_needed_quantity := l_needed_quantity + l_max_tolerance;
9159          ELSE
9160             l_max_tolerance := 0;
9161          END IF;
9162 
9163          IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
9164             IF g_max_sec_tolerance < 0 THEN
9165                l_max_sec_tolerance := NVL(g_max_sec_tolerance,0);
9166                l_sec_needed_quantity := l_sec_needed_quantity + l_max_sec_tolerance;
9167             ELSIF l_allocation_mode IN (1, 5) THEN
9168                l_max_sec_tolerance := NVL(g_max_sec_tolerance,0);
9169                l_sec_needed_quantity := l_sec_needed_quantity + l_max_sec_tolerance;
9170             ELSE
9171                l_max_sec_tolerance := 0;
9172             END IF;
9173          END IF;
9174       ELSE
9175          l_max_tolerance := 0;
9176          IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
9177             l_max_sec_tolerance := 0;
9178          END IF;
9179       END IF;
9180 
9181       IF l_debug = 1 THEN
9182          log_statement(l_api_name, 'New Needed Qty with tolerance ', 'qty:' || l_needed_quantity);
9183          log_statement(l_api_name, 'New Needed Sec qty with tolerance ', 'sec qty:' || l_sec_needed_quantity);
9184          -- Added for 14699845 (Flexible lot allocation)
9185          log_statement(l_api_name, 'Original Needed Qty without tolerance ', 'qty:' || l_orig_needed_quantity);
9186          log_statement(l_api_name, 'Original Needed Sec Qty without tolerance ', 'sec qty:' || l_orig_needed_sec_qty);
9187       END IF;
9188 
9189       IF ((p_project_id IS NOT NULL) AND (l_to_locator_id IS NOT NULL) AND (p_type_code = 1)) THEN
9190          -- bug 2400549 - for WIP backflush transfer putaway,
9191          -- always use the locator specified on the move order line, even
9192          -- if that locator is from common stock (not project)
9193          -- Bug 2666620: BackFlush MO Type Removed. It is now 5. Moreover Txn Action ID is 2 which is
9194          -- already handled.
9195          IF NOT (wms_engine_pvt.g_move_order_type = 5 AND wms_engine_pvt.g_transaction_action_id = 2) THEN
9196             IF l_debug = 1 THEN
9197                log_statement(l_api_name, 'do_project1', 'Calling do project check');
9198             END IF;
9199             IF doprojectcheck(l_return_status, l_to_locator_id, p_project_id, p_task_id, l_to_locator_id, l_dummy_loc) THEN
9200                IF l_debug = 1 THEN
9201                   log_statement(l_api_name, 'do_project1_success', 'Do Project Check passed');
9202                END IF;
9203                NULL;
9204             END IF;
9205          END IF;
9206       END IF;
9207 
9208       -- Save the initial input qty for later usage
9209       l_initial_pri_quantity := l_needed_quantity;
9210       IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
9211          l_initial_sec_quantity := l_sec_needed_quantity;
9212       END IF;
9213 
9214       l_input_lpn_id := l_lpn_id;
9215 
9216       IF p_type_code = 2 THEN
9217          -- check for null values.  NULL produces error in stored procedure,
9218          -- so we treat -9999 as NULL;
9219          -- since revision is varchar(3), use -99
9220          -- we only want to overwrite revision and lot for pick rules, since
9221          -- we use these values in putaway.
9222          IF (l_revision IS NULL) THEN
9223             l_revision  := '-99';
9224          END IF;
9225          IF (l_lot_number IS NULL) THEN
9226             l_lot_number  := '-9999';
9227          END IF;
9228       END IF;
9229 
9230       IF (p_type_code = 2) THEN -- pick
9231          l_subinventory_code := l_from_subinventory_code;
9232          l_locator_id        := l_from_locator_id;
9233          l_cost_group_id     := l_from_cost_group_id;
9234       ELSE --put away
9235          l_subinventory_code := l_to_subinventory_code;
9236          l_locator_id        := l_to_locator_id;
9237          l_cost_group_id     := l_to_cost_group_id;
9238       END IF;
9239 
9240       IF (l_subinventory_code IS NULL) THEN
9241          l_subinventory_code  := '-9999';
9242       END IF;
9243 
9244       IF (l_locator_id IS NULL) THEN
9245          l_locator_id  := -9999;
9246       END IF;
9247 
9248       IF (l_cost_group_id IS NULL) THEN
9249          l_cost_group_id  := -9999;
9250       END IF;
9251 
9252       IF (l_lpn_id IS NULL) THEN
9253          l_lpn_id  := -9999;
9254       END IF;
9255 
9256       IF (p_project_id IS NULL) THEN
9257          l_project_id  := -9999;
9258       ELSE
9259          l_project_id  := p_project_id;
9260       END IF;
9261 
9262       IF (p_task_id IS NULL) THEN
9263          l_task_id  := -9999;
9264       ELSE
9265          l_task_id  := p_task_id;
9266       END IF;
9267 
9268       IF (p_unit_number IS NULL) THEN
9269          l_unit_number  := '-9999';
9270       ELSE
9271          l_unit_number  := p_unit_number;
9272       END IF;
9273 
9274       IF l_debug = 1 THEN
9275          log_statement(l_api_name, 'Set value for l_sl_rsv_is_detailed', 'if serial number is reserved');
9276          log_statement(l_api_name, 'l_serial_number',  l_serial_number);
9277          log_statement(l_api_name, 'l_rule_id',  l_rule_id);
9278          log_statement(l_api_name, 'l_reservation_id',  l_reservation_id);
9279       END IF;
9280       -- [ new code to check the serial number reservation ]
9281 
9282       l_sl_rsv_is_detailed := 'N' ;
9283       IF l_serial_number IS NOT NULL
9284          AND l_serial_number <> fnd_api.g_miss_char
9285          AND l_serial_number <> '-999' /*NVL(l_serial_number, '-999') <> '-999'*/
9286          AND (  NVL(l_rule_id, 777)  = -999 OR NVL(l_reservation_id , 999) <> 999 ) THEN -- bug#10392328
9287          l_sl_rsv_is_detailed := 'Y';
9288       END IF;
9289 
9290       /* LG. Check the txn dtl lines with the control flags, then check the override rule flag
9291        * from the mtl_parameters, allocate directly if res is fully detailed.
9292        */
9293       -- [
9294       --  If the Serial Number is reserved, Rules are not called and following code is called
9295       -- ]
9296       IF ( l_rule_override_flag = 'Y' OR  l_sl_rsv_is_detailed = 'Y' )  AND p_type_code = 2 THEN --{
9297          IF l_debug = 1 THEN
9298             log_statement(l_api_name,'detailed', 'Rule Override flag is set ');
9299          END IF;
9300          -- Validate the txn detail
9301          l_reservation_is_detailed := 'Y';
9302 
9303          IF l_debug = 1 THEN
9304             log_statement(l_api_name,'detailed', 'Subinventory should be there '|| l_subinventory_code);
9305          END IF;
9306 
9307          IF NVL(l_subinventory_code, '-9999') = '-9999' THEN
9308             l_reservation_is_detailed := 'N';
9309          END IF;
9310 
9311          IF (wms_engine_pvt.g_org_loc_control IN (2, 3)             -- org level
9312              OR wms_engine_pvt.g_sub_loc_control IN (2, 3)          -- sub level
9313              OR (wms_engine_pvt.g_sub_loc_control = 5               -- item level
9314                  AND wms_engine_pvt.g_item_loc_control IN (2, 3)
9315                 )
9316             )
9317          THEN
9318             IF l_debug = 1 THEN
9319                log_statement(l_api_name,'detailed', 'Locator should be there '|| l_locator_id);
9320             END IF;
9321             IF NVL(l_locator_id,-9999) = -9999 THEN
9322                l_reservation_is_detailed := 'N';
9323             END IF;
9324          END IF;
9325 
9326          IF l_lot_control_code <> 1 THEN -- lot controlled
9327             IF l_debug = 1 THEN
9328                log_statement(l_api_name,'detailed', 'Lot should be there'|| l_lot_number);
9329             END IF;
9330             IF NVL(l_lot_number,'-9999') = '-9999' THEN
9331                l_reservation_is_detailed := 'N';
9332             END IF;
9333          END IF;
9334 
9335          IF l_revision_control_code <> 1 THEN   -- revision controlled
9336             IF l_debug = 1 THEN
9337                log_statement(l_api_name,'detailed', 'Revision should be there'|| l_Revision);
9338             END IF;
9339             IF NVL(l_revision,'-99') = '-99' THEN
9340                l_reservation_is_detailed := 'N';
9341             END IF;
9342          END IF;
9343 
9344          IF ( l_reservation_is_detailed = 'Y' OR  l_sl_rsv_is_detailed = 'Y' ) THEN --{
9345             IF l_debug = 1 THEN
9346                log_statement(l_api_name,'detailed', 'Reservation is fully detailed, validate and insert');
9347             END IF;
9348 
9349             -- [Checking the material status for serial /lots
9350             --  OPM Convergence project missed the mat-status check
9351             -- Logic : if the lot or serial number's material status is not allowed for transactions
9352             --         even though there is detailed reservations exist in the system, rule engine will
9353             --         ignore the record
9354             --         The mat-status is applicable for serial reserved items too ]
9355 
9356             l_sub_loc_lot_trx_allowed := 'Y';
9357             l_serial_trx_allowed      := 'Y';
9358             l_serial_status_id        := 0;
9359             IF ((l_serial_number  IS NOT NULL)  AND  (NVL(l_serial_status, 'N')  = 'Y'))  THEN
9360                SELECT status_id
9361                  INTO l_serial_status_id
9362                  FROM mtl_serial_numbers
9363                 WHERE inventory_item_id        = p_inventory_item_id
9364                   AND current_organization_id  = p_organization_id
9365                   AND serial_number            = l_serial_number;
9366 
9367                l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
9368                                            p_transaction_type_id
9369                                           ,p_organization_id
9370                                           ,p_inventory_item_id
9371                                           ,l_serial_status_id) ;
9372             END IF;
9373 
9374             -- Bug 4756156
9375             -- IF  ((l_lot_number IS NOT NULL)  AND (nvl(l_lot_status, 'Y') = 'Y'))  THEN
9376 
9377             -- start 10085345
9378             IF l_lpn_id = -9999 THEN
9379                l_lpn_id := NULL;
9380             END IF;
9381 
9382                                 -- start bug 13601536
9383                 IF (l_lot_number =  '-9999' ) THEN
9384                   l_lot_number  := NULL;
9385                 END IF;
9386 
9387                 IF l_locator_id  = -9999 THEN
9388                   l_locator_id := NULL;
9389                 END IF;
9390                                 -- end bug 13601536
9391 
9392             l_onhand_status_trx_allowed := 'Y';
9393 
9394             IF l_default_status_id = -1 THEN
9395                IF l_debug = 1 THEN
9396                   log_statement(l_api_name, 'before calling trx_allowed: ', l_sub_loc_lot_trx_allowed);
9397                END IF;
9398 
9399                l_onhand_status_trx_allowed := 'N';
9400                l_sub_loc_lot_trx_allowed :=   inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
9401                                                   p_transaction_type_id
9402                                                  ,p_organization_id
9403                                                  ,p_inventory_item_id
9404                                                  ,l_subinventory_code
9405                                                  ,l_locator_id
9406                                                  ,l_lot_number);
9407 
9408                IF l_debug = 1 THEN
9409                   log_statement(l_api_name, 'detailed - l_sub_loc_lot_trx_allowed ', l_sub_loc_lot_trx_allowed);
9410                END IF;
9411             ELSE --  IF l_default_status_id = -1 THEN
9412                l_sub_loc_lot_trx_allowed:='N';
9413                IF (inv_cache.item_rec.serial_number_control_code in (1,6)) THEN
9414                   l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
9415                                                      p_transaction_type_id
9416                                                     ,p_organization_id
9417                                                     ,p_inventory_item_id
9418                                                     ,l_subinventory_code
9419                                                     ,l_locator_id
9420                                                     ,l_lot_number
9421                                                     ,l_lpn_id);
9422                END IF;
9423                IF l_debug = 1 THEN
9424                   log_statement(l_api_name, 'detailed - l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
9425                END IF;
9426             END IF;
9427             -- end 10085345
9428 
9429             IF ( l_serial_trx_allowed <> 'Y' OR (l_sub_loc_lot_trx_allowed <> 'Y'  AND l_onhand_status_trx_allowed <> 'Y')) THEN --BUG# 9784319
9430                --   skip the input record and go to next rec , because mat status is not allowed
9431                IF l_debug = 1 THEN
9432                   log_statement(l_api_name, 'Mat Status Check failed', 'Skipping the input rec');
9433                END IF;
9434                GOTO nextINputrecord;
9435             END IF;
9436             -- End of mat status check ]
9437 
9438             -- [ Allocating this line based on reservation without calling rules
9439             --   Make sure all the following values are either NULL or have some
9440             --   real values but not the defaulted values  eg '-99' or '-9999' etc..
9441             --   The  default values '-99', '-9999' may cause issues with Qty tree
9442             --   May have to default the value for Project, Task , unit
9443             --   This only applicable for line based on detailed reservation
9444             -- ]
9445 
9446             IF l_revision = '-99' THEN
9447                l_revision := NULL;
9448             END IF;
9449 
9450             IF l_subinventory_code = '-9999' THEN
9451                l_subinventory_code := NULL;
9452             END IF;
9453 
9454             IF l_locator_id  = -9999 THEN
9455                l_locator_id := NULL;
9456             END IF;
9457 
9458             IF l_cost_group_id  = -9999 THEN
9459                l_cost_group_id := NULL;
9460             END IF;
9461 
9462             IF l_lpn_id = -9999 THEN
9463                l_lpn_id := NULL;
9464             END IF;
9465 
9466             IF (l_lot_number =  '-9999' ) THEN
9467                l_lot_number  := NULL;
9468             END IF;
9469 
9470             g_locs(1).revision               := l_revision;
9471             g_locs(1).lot_number             := l_lot_number;
9472             g_locs(1).subinventory_code      := l_subinventory_code;
9473             g_locs(1).locator_id             := l_locator_id;
9474             g_locs(1).quantity               := l_needed_quantity;
9475             g_locs(1).secondary_quantity     := l_sec_needed_quantity;
9476             g_locs(1).serial_number          := l_serial_number; -- [ new code ]
9477             g_locs(1).lpn_id                 := l_lpn_id; --8722417
9478 
9479 
9480             validate_and_insert(
9481               x_return_status              => x_return_status
9482             , x_msg_count                  => x_msg_count
9483             , x_msg_data                   => x_msg_data
9484             , p_record_id                  => 1
9485             , p_needed_quantity            => l_needed_quantity
9486             , p_use_pick_uom               => FALSE
9487             , p_organization_id            => p_organization_id
9488             , p_inventory_item_id          => p_inventory_item_id
9489             , p_to_subinventory_code       => l_to_subinventory_code
9490             , p_to_locator_id              => l_to_locator_id
9491             , p_to_cost_group_id           => l_to_cost_group_id
9492             , p_primary_uom                => p_primary_uom
9493             , p_transaction_uom            => p_transaction_uom
9494             , p_transaction_temp_id        => p_transaction_temp_id
9495             , p_type_code                  => p_type_code
9496             , p_rule_id                    => l_rule_id
9497             , p_reservation_id             => l_reservation_id
9498             , p_tree_id                    => p_tree_id
9499             , p_debug_on                   => l_debug_on
9500             , p_needed_sec_quantity        => l_sec_needed_quantity
9501             , p_secondary_uom              => p_secondary_uom
9502             , p_grade_code                 => p_grade_code
9503             , x_inserted_record            => l_inserted_record
9504             , x_allocated_quantity         => l_allocated_quantity
9505             , x_remaining_quantity         => l_remaining_quantity
9506             , x_sec_allocated_quantity     => l_sec_allocated_quantity
9507             , x_sec_remaining_quantity     => l_sec_remaining_quantity
9508             , p_orig_needed_quantity       => l_needed_quantity      -- Added for 14699845 (Flexible lot allocation)
9509             , p_orig_needed_sec_qty        => l_sec_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
9510             , p_simulation_mode            => p_simulation_mode      -- Added for 14699845 (Flexible lot allocation)
9511             );
9512             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9513                IF l_debug = 1 THEN
9514                   log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9515                END IF;
9516                RAISE fnd_api.g_exc_unexpected_error;
9517             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9518                IF l_debug = 1 THEN
9519                   log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9520                END IF;
9521                RAISE fnd_api.g_exc_error;
9522             END IF;
9523             /* done with this res go to the next */
9524             GOTO nextINputrecord;
9525          END IF; --}
9526       END IF; --}
9527 
9528       IF l_debug = 1 THEN
9529          IF p_type_code = 1 THEN
9530             log_statement(l_api_name, 'Input Rec :Calling rule with following value of type -', 'Putaway');
9531          ELSE
9532             log_statement(l_api_name, 'Input Rec :Calling rule with following value of type -', 'Picking');
9533          END IF;
9534          log_statement(l_api_name, 'Input Rec :l_rule_id',         l_rule_id);
9535          log_statement(l_api_name, 'Input Rec :p_organization_id',     p_organization_id);
9536          log_statement(l_api_name, 'Input Rec :p_inventory_item_id',      p_inventory_item_id);
9537          log_statement(l_api_name, 'Input Rec :p_transaction_type_id',      p_transaction_type_id);
9538          log_statement(l_api_name, 'Input Rec :l_revision',          l_revision);
9539          log_statement(l_api_name, 'Input Rec :l_lot_number',          l_lot_number);
9540          log_statement(l_api_name, 'Input Rec :l_subinventory_code',      l_subinventory_code);
9541          log_statement(l_api_name, 'Input Rec :l_locator_id',          l_locator_id);
9542          log_statement(l_api_name, 'Input Rec :l_cost_group_id',      l_cost_group_id);
9543          log_statement(l_api_name, 'Input Rec :l_pp_transaction_temp_id',l_pp_transaction_temp_id);
9544          log_statement(l_api_name, 'Input Rec :l_is_serial_control',     l_is_serial_control);
9545          log_statement(l_api_name, 'Input Rec :l_detail_serial',      l_detail_serial);
9546          log_statement(l_api_name, 'Input Rec :p_detail_any_serial',      p_detail_any_serial);
9547          log_statement(l_api_name, 'Input Rec :p_from_serial',         p_from_serial);
9548          log_statement(l_api_name, 'Input Rec :p_to_serial',         p_to_serial);
9549          log_statement(l_api_name, 'Input Rec :l_unit_number',          l_unit_number);
9550          log_statement(l_api_name, 'Input Rec :l_lpn_id',          l_lpn_id);
9551          log_statement(l_api_name, 'Input Rec :l_project_id',          l_project_id);
9552          log_statement(l_api_name, 'Input Rec :l_task_id',          l_task_id);
9553          log_statement(l_api_name, 'Input Rec :l_rule_result ',        l_rule_result);
9554          log_statement(l_api_name, 'Input Rec :l_restrict_subs_code ',      l_restrict_subs_code);
9555          log_statement(l_api_name, 'Input Rec :l_restrict_locs_code ',    l_restrict_locs_code);
9556       END IF;
9557 
9558       FOR l_rule_counter IN 1..2  LOOP --{
9559          IF p_type_code = 2 THEN
9560            --pick_open_curs
9561            pick_open_rule(
9562               v_pick_cursor
9563             , l_rule_id
9564             , p_organization_id
9565             , p_inventory_item_id
9566             , p_transaction_type_id
9567             , l_revision
9568             , l_lot_number
9569             , l_subinventory_code
9570             , l_locator_id
9571             , l_cost_group_id
9572             , l_pp_transaction_temp_id
9573             , l_is_serial_control
9574             , l_detail_serial
9575             , p_detail_any_serial
9576             , p_from_serial
9577             , p_to_serial
9578             , l_unit_number
9579             , l_lpn_id
9580             , l_project_id
9581             , l_task_id
9582             , l_rule_result
9583             );
9584          ELSIF  p_type_code = 1  then
9585             put_open_rule(
9586               v_put_cursor
9587             , l_rule_id
9588             , p_organization_id
9589             , p_inventory_item_id
9590             , p_transaction_type_id
9591             , l_subinventory_code
9592             , l_locator_id
9593             , l_pp_transaction_temp_id
9594             , l_restrict_subs_code
9595             , l_restrict_locs_code
9596             , l_project_id
9597             , l_task_id
9598             , l_rule_result
9599             );
9600          END IF;
9601 
9602          IF l_rule_result  = 1 THEN
9603             IF l_debug = 1 THEN
9604                log_statement(l_api_name, 'Open Cursor package called ' , l_rule_counter);
9605                log_statement(l_api_name, 'rule_id ' , l_rule_id);
9606             END IF;
9607             EXIT;
9608          END IF;
9609 
9610          IF (l_rule_result = 0) and l_rule_counter = 2 THEN --error
9611             IF l_debug = 1 THEN
9612                log_statement(l_api_name, 'open_curs_err', 'Error calling open_curs');
9613                log_error_msg(l_api_name, 'rule_package_missing');
9614                log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
9615             END IF;
9616             fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
9617             fnd_message.set_token('RULEID', l_rule_id);
9618             fnd_msg_pub.ADD;
9619             RAISE fnd_api.g_exc_unexpected_error;
9620          END IF;
9621       END LOOP; --}
9622 
9623       IF (p_type_code = 2) THEN -- pick
9624          g_locs_index           := 0;
9625          g_locs.DELETE;
9626          g_consists.DELETE;
9627          g_lpns.DELETE;
9628          g_first_order_by_rank  := NULL;
9629          g_first_consist_group  := 0;
9630          g_last_consist_group   := 0;
9631          l_order_by_rank        := 0;
9632       END IF;
9633 
9634       -- If type code = 2 and allocation mode = 1
9635       -- ENTIRE LPN
9636       IF p_type_code = 2 AND l_allocation_mode = 1 THEN --{
9637          l_cur_lpn_group    := 0;
9638          g_first_lpn_group  := 0;
9639          g_last_lpn_group   := 0;
9640          l_cur_lpn_rec      := 0;
9641 
9642          l_allocate_serial_flag := inv_cache.org_rec.allocate_serial_flag;
9643 
9644          IF l_debug = 1 THEN
9645             log_statement(l_api_name, 'alloc_lpns', 'Allocating Entire LPNs');
9646             log_statement(l_api_name, 'allocate_serial_flag', 'allocate_serial_flag = '||l_allocate_serial_flag);
9647          END IF;
9648 
9649          -- for each record from rules cursor
9650          LOOP --{
9651             -- Get record from rules cursor
9652             IF l_debug = 1 THEN
9653                log_statement(l_api_name, 'fetch_cursor', 'Getting rec from rule with FetchCursor');
9654             END IF;
9655             --  Added for Mat Stat check
9656             LOOP --{
9657                IF l_debug = 1 THEN
9658                   log_statement(l_api_name, 'fetch_cursor', 'inside Mat Stat check LOOP');
9659                END IF;
9660                -- For custom serial
9661                IF ( l_allocate_serial_flag = 'C' )
9662                   AND (NVL(l_custom_serial_index,-1) < NVL(l_custom_select_serials.serial_number.LAST,-1))
9663                THEN
9664                   -- next record should be next serial from custom API
9665                   l_custom_serial_index := l_custom_serial_index + 1;
9666                   v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
9667                   v_current_row.quantity := 1;
9668                ELSE
9669                   --{ Mat Stat checking
9670                   fetchcursor(
9671                     x_return_status
9672                   , x_msg_count
9673                   , x_msg_data
9674                   , v_pick_cursor
9675                   , l_rule_id
9676                   , v_current_row.revision
9677                   , v_current_row.lot_number
9678                   , v_current_row.lot_expiration_date
9679                   , v_current_row.subinventory_code
9680                   , v_current_row.locator_id
9681                   , v_current_row.cost_group_id
9682                   , v_current_row.uom_code
9683                   , v_current_row.lpn_id
9684                   , v_current_row.serial_number
9685                   , v_current_row.quantity
9686                   , v_current_row.secondary_quantity               -- new
9687                   , v_current_row.grade_code                       -- new
9688                   , v_current_row.consist_string
9689                   , v_current_row.order_by_string
9690                   , l_rows
9691                   );
9692 
9693                   EXIT WHEN NVL(l_rows, 0) = 0;  -- Added to exit , if the rule is not returning any rows
9694 
9695                   IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9696                      IF l_debug = 1 THEN
9697                         log_error(l_api_name, 'uerr_fetch_cursor', 'Unexpected error in FetchCursor');
9698                      END IF;
9699                      RAISE fnd_api.g_exc_unexpected_error;
9700                   ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9701                      IF l_debug = 1 THEN
9702                         log_error(l_api_name, 'fetch_cursor ', 'Error in FetchCursor');
9703                      END IF;
9704                      RAISE fnd_api.g_exc_error;
9705                   END IF;
9706 
9707                   -- Start 1 of bug 13026723 change
9708                   IF inv_cache.set_mtt_rec(p_transaction_type_id) THEN
9709                      IF ( v_current_row.lpn_id IS NOT NULL AND inv_cache.mtt_rec.transaction_source_type_id = 4
9710                         AND inv_cache.mtt_rec.transaction_action_id= 2
9711                         AND IS_LPN_CYC_RESERVED (p_organization_id,v_current_row.lpn_id) )
9712                      THEN
9713                         IF l_debug = 1 THEN
9714                            log_error(l_api_name, 'lpn cycle count reserved check ', 'This LPN has Cycle count reservation. Hence skipping it.');
9715                         END IF;
9716 
9717                         GOTO nextoutputrecord;
9718                      END IF;
9719                   END IF;
9720                   -- End 1 of bug 13026723 change
9721 
9722                   IF l_debug = 1 THEN
9723                      log_statement(l_api_name, 'Serial Status - l_detail_serial ', l_detail_serial);
9724                      log_statement(l_api_name, 'fetch_cursor - l_rows ', l_rows);
9725                      log_statement(l_api_name, 'fetch_cursor - v_current_row.lot_number ', v_current_row.lot_number);
9726                      log_statement(l_api_name, 'fetch_cursor - v_current_row.serial_number ', v_current_row.serial_number);
9727                   END IF;
9728 
9729                   IF ( l_allocate_serial_flag = 'C' AND l_is_serial_control = 1) THEN --{
9730                      -- Moved this piece of code inside the IF condition for bug#14574893 -- 12687878
9731                      IF p_transaction_type_id in (52,53) THEN --sales orders, internal orders
9732                         BEGIN
9733                            SELECT source_header_type_id, source_header_id, source_line_id
9734                            INTO l_source_type_id, l_source_header_id, l_source_line_id
9735                            FROM wsh_delivery_details
9736                            WHERE move_order_line_id = p_transaction_temp_id
9737                            AND rownum = 1;
9738                         EXCEPTION
9739                            WHEN NO_DATA_FOUND THEN
9740                               l_source_type_id := null;
9741                               l_source_header_id := null;
9742                               l_source_line_id := null;
9743                         END;
9744                      END IF;
9745 
9746                      IF l_debug = 1 THEN
9747                         log_statement(l_api_name, 'value of - l_source_type_id ',l_source_type_id);
9748                         log_statement(l_api_name, 'value of - l_source_header_id ',l_source_header_id);
9749                         log_statement(l_api_name, 'value of - l_source_line_id ',l_source_line_id);
9750                      END IF;
9751 
9752                      INV_DETAIL_SERIAL_PUB.Get_User_Serial_Numbers (
9753                          x_return_status           => x_return_status
9754                        , x_msg_count               => x_msg_count
9755                        , x_msg_data                => x_msg_data
9756                        , p_organization_id         => p_organization_id
9757                        , p_inventory_item_id       => p_inventory_item_id
9758                        , p_revision                => v_current_row.revision
9759                        , p_lot_number              => v_current_row.lot_number
9760                        , p_subinventory_code       => v_current_row.subinventory_code
9761                        , p_locator_id              => v_current_row.locator_id
9762                        , p_required_sl_qty         => v_current_row.quantity
9763                        , p_from_range              => p_from_serial
9764                        , p_to_range                => p_to_serial
9765                        , p_unit_number             => l_unit_number
9766                        , p_cost_group_id           => l_cost_group_id
9767                        , p_transaction_type_id     => p_transaction_type_id -- 12687878
9768                        , p_demand_source_type_id   => l_source_type_id      -- p_demand_source_type_id   -- 12687878
9769                        , p_demand_source_header_id => l_source_header_id    -- p_demand_source_header_id -- 12687878
9770                        , p_demand_source_line_id   => l_source_line_id      -- p_demand_source_line_id   -- 12687878
9771                        , x_serial_numbers          => l_custom_select_serials );
9772 
9773                      IF ( x_return_status = fnd_api.g_ret_sts_unexp_error ) THEN
9774                         IF ( l_debug = 1 ) THEN
9775                            log_error(l_api_name, 'uerr_Get_User_Serial_Numbers', 'Unexpected error in Get_User_Serial_Numbers');
9776                         END IF;
9777                         RAISE fnd_api.g_exc_unexpected_error;
9778                      ELSIF ( x_return_status = fnd_api.g_ret_sts_error ) THEN
9779                         IF ( l_debug = 1 ) THEN
9780                            log_error(l_api_name, 'Get_User_Serial_Numbers', 'Error in Get_User_Serial_Numbers');
9781                         END IF;
9782                         RAISE fnd_api.g_exc_error;
9783                      END IF;
9784 
9785                      l_custom_serial_index := l_custom_select_serials.serial_number.FIRST;
9786                      v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
9787                      v_current_row.quantity := 1;
9788                   END IF; --}
9789                END IF; --} custom serial
9790 
9791                l_sub_loc_lot_trx_allowed     := 'Y';
9792                l_serial_trx_allowed        := 'Y';
9793                l_serial_status_id          := 0;
9794 
9795                IF v_current_row.serial_number IS NOT NULL  THEN
9796                   IF l_detail_serial = 1 THEN
9797                      SELECT status_id
9798                        INTO l_serial_status_id
9799                        FROM mtl_serial_numbers
9800                       WHERE inventory_item_id       = p_inventory_item_id
9801                         AND current_organization_id = p_organization_id
9802                         AND serial_number           = v_current_row.serial_number;
9803 
9804                      l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
9805                                                  p_transaction_type_id
9806                                                 ,p_organization_id
9807                                                 ,p_inventory_item_id
9808                                                 ,l_serial_status_id) ;
9809                   END IF;
9810 
9811                   IF l_debug = 1 THEN
9812                      log_statement(l_api_name, 'Serial Status - p_transaction_type_id ', p_transaction_type_id);
9813                      log_statement(l_api_name, 'Serial Status - p_organization_id ', p_organization_id);
9814                      log_statement(l_api_name, 'Serial Status -p_transaction_type_id ', p_organization_id);
9815                      log_statement(l_api_name, 'Serial Status - p_inventory_item_id ', p_inventory_item_id);
9816                      log_statement(l_api_name, 'Serial Status - serial_number ', v_current_row.serial_number);
9817                      log_statement(l_api_name, 'Serial Status - l_serial_status_id ', l_serial_status_id);
9818                      log_statement(l_api_name, 'Serial Status - l_serial_trx_allowed ', l_serial_trx_allowed);
9819                   END IF;
9820                END IF;
9821 
9822                -- LPN Status Project
9823                l_onhand_status_trx_allowed := 'Y';
9824 
9825                IF l_default_status_id = -1 THEN
9826                   IF l_debug = 1 THEN
9827                      log_statement(l_api_name, 'before calling trx_allowed: ', l_sub_loc_lot_trx_allowed);
9828                   END IF;
9829 
9830                   l_onhand_status_trx_allowed := 'N';
9831                   l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
9832                                                    p_transaction_type_id
9833                                                   ,p_organization_id
9834                                                   ,p_inventory_item_id
9835                                                   ,v_current_row.subinventory_code
9836                                                   ,v_current_row.locator_id
9837                                                   ,v_current_row.lot_number);
9838 
9839                   IF l_debug = 1 THEN
9840                      log_statement(l_api_name, 'fetch_cursor - l_sub_loc_lot_trx_allowed ', l_sub_loc_lot_trx_allowed);
9841                   END IF;
9842                ELSE -- IF l_default_status_id = -1 THEN
9843                   l_sub_loc_lot_trx_allowed:='N';
9844                   IF (inv_cache.item_rec.serial_number_control_code in (1,6)) THEN
9845                      l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
9846                                                         p_transaction_type_id
9847                                                        ,p_organization_id
9848                                                        ,p_inventory_item_id
9849                                                        ,v_current_row.subinventory_code
9850                                                        ,v_current_row.locator_id
9851                                                        ,v_current_row.lot_number
9852                                                        ,v_current_row.lpn_id);
9853                   END IF;
9854                   IF l_debug = 1 THEN
9855                      log_statement(l_api_name, 'fetch_cursor - l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
9856                   END IF;
9857                END IF;
9858 
9859                EXIT WHEN (l_serial_trx_allowed = 'Y'
9860                           AND (l_sub_loc_lot_trx_allowed = 'Y' OR l_onhand_status_trx_allowed='Y'));
9861                -- >> Else fetch next record from the rule cursor --
9862             END LOOP; --}
9863             -- End of Mat Stat Check --
9864             -- LPN Status Project
9865 
9866             -- initialize pointer to next rec
9867             v_current_row.next_rec := 0;
9868             -- if no more records
9869             IF l_rows = 0 THEN --{
9870                IF l_debug = 1 THEN
9871                   log_statement(l_api_name, 'no_more_rec', 'No more records from rule');
9872                END IF;
9873                IF l_consist_exists THEN --{
9874                   -- loop through consist groups, looking for groups where quantity = needed quantity
9875                   l_cur_consist_group  := g_first_consist_group;
9876                   IF l_debug = 1 THEN
9877                      log_statement(l_api_name, 'first_consist_group', 'First Consist Group in list: ' || l_cur_consist_group);
9878                   END IF;
9879                   LOOP --{
9880                      IF g_over_allocation = 'N'
9881                         OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
9882                         OR  WMS_Engine_PVT.g_move_order_type <> 3
9883                      THEN
9884                         EXIT WHEN (  ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P')
9885                                         AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance)
9886                                      )
9887                                   OR ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S')
9888                                         AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance)
9889                                      )
9890                                   );
9891                      ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3
9892                      THEN
9893                         IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
9894                            IF l_max_sec_tolerance >= 0 THEN
9895                               EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
9896                                         OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
9897                            ELSE
9898                               EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
9899                            END IF;
9900                         ELSE
9901                            IF l_max_tolerance >= 0 THEN
9902                               EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9903                                         OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9904                            ELSE
9905                               EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9906                            END IF;
9907                         END IF;
9908                      END IF;
9909 
9910                      EXIT WHEN l_cur_consist_group = 0;
9911 
9912                      IF (  ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
9913                              AND (g_consists(l_cur_consist_group).quantity
9914                                   BETWEEN (l_needed_quantity - l_max_tolerance) AND l_needed_quantity)
9915                            )
9916                         OR ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
9917                              AND (g_consists(l_cur_consist_group).secondary_quantity
9918                                   BETWEEN (l_sec_needed_quantity - l_max_sec_tolerance) AND l_sec_needed_quantity)
9919                            )
9920                         )
9921                      THEN --{
9922                         -- for each LPN in lpn array
9923                         l_cur_lpn_group := g_consists(l_cur_consist_group).first_rec;
9924                         IF l_debug = 1 THEN
9925                            log_statement(l_api_name, 'first_lpn', 'First LPN in list: ' || l_cur_lpn_group);
9926                         END IF;
9927                         LOOP --{ loop through lpn in consist group
9928                            EXIT WHEN l_cur_lpn_group = 0;
9929                            -- if lpn quantity is less than or equal to the needed quantity
9930                            -- and the LPN has been entirely allocated, use it
9931                            IF l_debug = 1 THEN
9932                               log_statement(l_api_name, 'alloc_stored_lpn', 'Allocating LPN. id: ' || l_cur_lpn_group);
9933                            END IF;
9934                            -- for each record in LPN
9935                            l_cur_lpn_rec := g_lpns(l_cur_lpn_group).first_rec;
9936                            LOOP --{
9937                               EXIT WHEN l_cur_lpn_rec = 0;
9938                               g_trace_recs(l_cur_lpn_rec).entire_lpn_flag  := 'Y';
9939                               -- call validate and insert
9940                               l_expected_quantity := g_locs(l_cur_lpn_rec).quantity;
9941                               IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
9942                                  l_sec_expected_quantity := g_locs(l_cur_lpn_rec).secondary_quantity;
9943                               END IF;
9944 
9945                               validate_and_insert(
9946                                 x_return_status              => x_return_status
9947                               , x_msg_count                  => x_msg_count
9948                               , x_msg_data                   => x_msg_data
9949                               , p_record_id                  => l_cur_lpn_rec
9950                               , p_needed_quantity            => l_needed_quantity
9951                               , p_use_pick_uom               => FALSE
9952                               , p_organization_id            => p_organization_id
9953                               , p_inventory_item_id          => p_inventory_item_id
9954                               , p_to_subinventory_code       => l_to_subinventory_code
9955                               , p_to_locator_id              => l_to_locator_id
9956                               , p_to_cost_group_id           => l_to_cost_group_id
9957                               , p_primary_uom                => p_primary_uom
9958                               , p_transaction_uom            => p_transaction_uom
9959                               , p_transaction_temp_id        => p_transaction_temp_id
9960                               , p_type_code                  => p_type_code
9961                               , p_rule_id                    => l_rule_id
9962                               , p_reservation_id             => l_reservation_id
9963                               , p_tree_id                    => p_tree_id
9964                               , p_debug_on                   => l_debug_on
9965                               , p_needed_sec_quantity        => l_sec_needed_quantity
9966                               , p_secondary_uom              => p_secondary_uom
9967                               , p_grade_code                 => p_grade_code
9968                               , x_inserted_record            => l_inserted_record
9969                               , x_allocated_quantity         => l_allocated_quantity
9970                               , x_remaining_quantity         => l_remaining_quantity
9971                               , x_sec_allocated_quantity     => l_sec_allocated_quantity
9972                               , x_sec_remaining_quantity     => l_sec_remaining_quantity
9973                               , p_orig_needed_quantity       => l_needed_quantity     -- Added for 14699845 (Flexible lot allocation)
9974                               , p_orig_needed_sec_qty        => l_sec_needed_quantity -- Added for 14699845 (Flexible lot allocation)
9975                               , p_simulation_mode            => p_simulation_mode     -- Added for 14699845 (Flexible lot allocation)
9976                               );
9977 
9978                               IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9979                                  IF l_debug = 1 THEN
9980                                     log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9981                                  END IF;
9982                                  RAISE fnd_api.g_exc_unexpected_error;
9983                               ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9984                                  IF l_debug = 1 THEN
9985                                     log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9986                                  END IF;
9987                                  RAISE fnd_api.g_exc_error;
9988                               END IF;
9989 
9990                               -- if returns false
9991                               IF l_inserted_record = FALSE
9992                                  OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_allocated_quantity < l_expected_quantity)
9993                                  OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_allocated_quantity < l_sec_expected_quantity)
9994                               THEN
9995                                  IF l_debug = 1 THEN
9996                                     log_statement(l_api_name, 'insert_failed', 'Record failed to allocation.  Rolling back and '
9997                                                                || 'invalidating LPN');
9998                                     -- rollback quantity tree
9999                                     log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
10000                                  END IF;
10001                                  inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
10002                                  IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10003                                     IF l_debug = 1 THEN
10004                                        log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
10005                                     END IF;
10006                                     RAISE fnd_api.g_exc_unexpected_error;
10007                                  ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10008                                     IF l_debug = 1 THEN
10009                                        log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
10010                                     END IF;
10011                                     RAISE fnd_api.g_exc_error;
10012                                  END IF;
10013 
10014                                  -- delete allocations
10015                                  DELETE FROM wms_transactions_temp
10016                                   WHERE line_type_code = 2
10017                                     AND type_code = p_type_code;
10018 
10019                                  IF l_debug_on THEN
10020                                     l_cur_rec  := g_lpns(l_cur_lpn_group).first_rec;
10021                                     LOOP
10022                                        g_trace_recs(l_cur_rec).entire_lpn_flag  := 'N';
10023                                        g_trace_recs(l_cur_rec).suggested_qty    := 0;
10024                                        IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'THEN
10025                                           g_trace_recs(l_cur_rec).secondary_qty := 0;
10026                                        END IF;
10027                                        EXIT WHEN l_cur_rec = l_cur_lpn_rec;
10028                                        l_cur_rec := g_locs(l_cur_rec).next_rec;
10029                                     END LOOP;
10030                                  END IF;
10031 
10032                                  IF l_debug = 1 THEN
10033                                     log_statement(l_api_name, 'finish_delete_sugs',
10034                                                               'Finished deleting suggestions and restored quantity tree');
10035                                  END IF;
10036                                  -- Exit loop for each rec in this LPN
10037                                  EXIT;
10038                               END IF; -- didn't allocate as much as expected
10039 
10040                               IF l_debug_on THEN
10041                                  g_trace_recs(l_cur_lpn_rec).consist_string_flag  := 'Y';
10042                               END IF;
10043                               -- decrease quantity needed
10044                               IF l_debug = 1 THEN
10045                                  log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
10046                                  log_statement(l_api_name, 'need_qty', 'New sec needed quantity: ' || l_sec_needed_quantity);
10047                                  -- Added for 14699845 (Flexible lot allocation)
10048                                  log_statement(l_api_name, 'need_qty', 'orig needed quantity: ' || l_orig_needed_quantity);
10049                                  log_statement(l_api_name, 'need_qty', 'orig needed sec qty : ' || l_orig_needed_sec_qty);
10050                               END IF;
10051                               l_cur_lpn_rec := g_locs(l_cur_lpn_rec).next_rec;
10052                               EXIT WHEN l_cur_lpn_rec = 0;
10053                               -- end loop through lpn recs
10054                            END LOOP; --} loop through recs w/in LPN
10055 
10056                            -- if no more quantity needed, exit LPN loop
10057                            l_needed_quantity  := l_needed_quantity - g_lpns(l_cur_lpn_group).quantity;
10058                            l_sec_needed_quantity  := l_sec_needed_quantity - g_lpns(l_cur_lpn_group).secondary_quantity;
10059 
10060                            -- Added for 14699845 (Flexible lot allocation)
10061                            l_orig_needed_quantity := l_orig_needed_quantity - g_lpns(l_cur_lpn_group).quantity;
10062                            l_orig_needed_sec_qty  := l_orig_needed_sec_qty - g_lpns(l_cur_lpn_group).secondary_quantity;
10063 
10064                            IF l_debug = 1 THEN
10065                               log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
10066                               log_statement(l_api_name, 'need_qty', 'New sec needed quantity: ' || l_sec_needed_quantity);
10067 
10068                               -- Added for 14699845 (Flexible lot allocation)
10069                               log_statement(l_api_name, 'need_qty', 'New orig needed quantity: ' || l_orig_needed_quantity);
10070                               log_statement(l_api_name, 'need_qty', 'New orig needed sec qty:  ' || l_orig_needed_sec_qty);
10071                            END IF;
10072 
10073                            IF g_over_allocation = 'N'
10074                               OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
10075                               OR WMS_Engine_PVT.g_move_order_type <> 3
10076                            THEN
10077                               EXIT WHEN (  ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P')
10078                                               AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance)
10079                                            )
10080                                         OR ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S')
10081                                               AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance)
10082                                            )
10083                                         );
10084                            ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
10085                               IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10086                                  IF l_max_sec_tolerance >= 0 THEN
10087                                     EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
10088                                                OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10089                                  ELSE
10090                                     EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10091                                  END IF;
10092                               ELSE
10093                                  IF l_max_tolerance >= 0 THEN
10094                                     EXIT WHEN (l_needed_quantity <= l_max_tolerance)
10095                                                OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10096                                  ELSE
10097                                     EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10098                                  END IF;
10099                               END IF;
10100                            END IF;
10101 
10102                            l_cur_lpn_group    := g_lpns(l_cur_lpn_group).next_consist_lpn_id;
10103                            EXIT WHEN l_cur_lpn_group = 0;
10104 
10105                            IF l_debug = 1 THEN
10106                               log_statement(l_api_name, 'next_lpn', 'Next LPN in list: ' || l_cur_lpn_group);
10107                            END IF;
10108 
10109                         END LOOP; --} lpns in consist group
10110 
10111                         -- if no more quantity needed, exit LPN loop
10112                         IF g_over_allocation = 'N'
10113                            OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
10114                            OR WMS_Engine_PVT.g_move_order_type <> 3
10115                         THEN
10116                            EXIT WHEN (  ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10117                                            AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance)
10118                                         )
10119                                      OR ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10120                                            AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance)
10121                                         )
10122                                      );
10123                         ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
10124                            IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10125                               IF l_max_sec_tolerance >= 0 THEN
10126                                  EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
10127                                            OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10128                               ELSE
10129                                  EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10130                               END IF;
10131                            ELSE
10132                               IF l_max_tolerance >= 0 THEN
10133                                  EXIT WHEN (l_needed_quantity <= l_max_tolerance)
10134                                            OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10135                               ELSE
10136                                  EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10137                               END IF;
10138                            END IF;
10139                         END IF;
10140                      END IF; --} enough quantity to allocate
10141 
10142                      -- end loop through consist groups
10143                      l_cur_consist_group  := g_consists(l_cur_consist_group).next_group;
10144 
10145                      IF l_debug = 1 THEN
10146                         log_statement(l_api_name, 'next_consist_group', 'Next Consist Group in list: ' || l_cur_consist_group);
10147                      END IF;
10148                   END LOOP; --}  loop through consist groups
10149 
10150                   -- exit outermost loop
10151                   IF l_debug = 1 THEN
10152                      log_statement(l_api_name, 'lpn_alloc_finished', 'Finished checking all LPNS.  Exit LPN allocation.');
10153                   END IF;
10154 
10155                   EXIT; -- outermost loop
10156                --}
10157                ELSE --{ no consists
10158                   -- for each LPN in lpn array
10159                   l_cur_lpn_group  := g_first_lpn_group;
10160 
10161                   IF l_debug = 1 THEN
10162                      log_statement(l_api_name, 'first_lpn', 'First LPN in list: ' || g_first_lpn_group);
10163                   END IF;
10164 
10165                   LOOP --{
10166                      IF g_over_allocation = 'N'
10167                         OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
10168                         OR WMS_Engine_PVT.g_move_order_type <> 3
10169                      THEN
10170                         EXIT WHEN (  ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10171                                         AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance)
10172                                      )
10173                                   OR ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10174                                         AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance)
10175                                      )
10176                                   );
10177                      ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
10178                         IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10179                            IF l_max_sec_tolerance >= 0 THEN
10180                               EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
10181                                          OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10182                            ELSE
10183                               EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10184                            END IF;
10185                         ELSE
10186                            IF l_max_tolerance >= 0 THEN
10187                               EXIT WHEN (l_needed_quantity <= l_max_tolerance)
10188                                          OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10189                            ELSE
10190                               EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10191                            END IF;
10192                         END IF;
10193                      END IF;
10194                      EXIT WHEN l_cur_lpn_group = 0;
10195 
10196                      -- if lpn quantity is less than or equal to the needed quantity
10197                      -- and the LPN has been entirely allocated, use it
10198                      IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10199                          AND g_lpns(l_cur_lpn_group).quantity <= l_needed_quantity
10200                          AND g_lpns(l_cur_lpn_group).total_quantity <> -1
10201                          AND g_lpns(l_cur_lpn_group).quantity = g_lpns(l_cur_lpn_group).total_quantity
10202                         )
10203                         OR
10204                         (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10205                          AND g_lpns(l_cur_lpn_group).secondary_quantity <= l_sec_needed_quantity
10206                          AND g_lpns(l_cur_lpn_group).secondary_total_quantity <> -1
10207                          AND g_lpns(l_cur_lpn_group).secondary_quantity = g_lpns(l_cur_lpn_group).secondary_total_quantity
10208                         )
10209                      THEN --{
10210                         IF l_debug = 1 THEN
10211                            log_statement(l_api_name, 'alloc_stored_lpn', 'Allocating LPN. id: ' || l_cur_lpn_group);
10212                         END IF;
10213 
10214                         -- for each record in LPN
10215                         l_cur_lpn_rec  := g_lpns(l_cur_lpn_group).first_rec;
10216 
10217                         LOOP --{
10218                            EXIT WHEN l_cur_lpn_rec = 0;
10219                            g_trace_recs(l_cur_lpn_rec).entire_lpn_flag := 'Y';
10220                            -- call validate and insert
10221                            l_expected_quantity := g_locs(l_cur_lpn_rec).quantity;
10222                            IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10223                               l_sec_expected_quantity := g_locs(l_cur_lpn_rec).secondary_quantity;
10224                            END IF;
10225 
10226                            validate_and_insert(
10227                              x_return_status              => x_return_status
10228                            , x_msg_count                  => x_msg_count
10229                            , x_msg_data                   => x_msg_data
10230                            , p_record_id                  => l_cur_lpn_rec
10231                            , p_needed_quantity            => l_needed_quantity
10232                            , p_use_pick_uom               => FALSE
10233                            , p_organization_id            => p_organization_id
10234                            , p_inventory_item_id          => p_inventory_item_id
10235                            , p_to_subinventory_code       => l_to_subinventory_code
10236                            , p_to_locator_id              => l_to_locator_id
10237                            , p_to_cost_group_id           => l_to_cost_group_id
10238                            , p_primary_uom                => p_primary_uom
10239                            , p_transaction_uom            => p_transaction_uom
10240                            , p_transaction_temp_id        => p_transaction_temp_id
10241                            , p_type_code                  => p_type_code
10242                            , p_rule_id                    => l_rule_id
10243                            , p_reservation_id             => l_reservation_id
10244                            , p_tree_id                    => p_tree_id
10245                            , p_debug_on                   => l_debug_on
10246                            , p_needed_sec_quantity        => l_sec_needed_quantity
10247                            , p_secondary_uom              => p_secondary_uom
10248                            , p_grade_code                 => p_grade_code
10249                            , x_inserted_record            => l_inserted_record
10250                            , x_allocated_quantity         => l_allocated_quantity
10251                            , x_remaining_quantity         => l_remaining_quantity
10252                            , x_sec_allocated_quantity     => l_sec_allocated_quantity
10253                            , x_sec_remaining_quantity     => l_sec_remaining_quantity
10254                            , p_orig_needed_quantity       => l_needed_quantity      -- Added for 14699845 (Flexible lot allocation)
10255                            , p_orig_needed_sec_qty        => l_sec_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
10256                            , p_simulation_mode            => p_simulation_mode      -- Added for 14699845 (Flexible lot allocation)
10257                            );
10258 
10259                            IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10260                               IF l_debug = 1 THEN
10261                                  log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
10262                               END IF;
10263                               RAISE fnd_api.g_exc_unexpected_error;
10264                            ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10265                               IF l_debug = 1 THEN
10266                                  log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
10267                               END IF;
10268                               RAISE fnd_api.g_exc_error;
10269                            END IF;
10270 
10271                            -- if returns false
10272                            IF l_inserted_record = FALSE
10273                               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_allocated_quantity < l_expected_quantity)
10274                               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_allocated_quantity < l_sec_expected_quantity)
10275                            THEN --{
10276                               IF l_debug = 1 THEN
10277                                  log_statement(l_api_name, 'insert_failed', 'Record failed to allocation.  Rolling back and '
10278                                                             || 'invalidating LPN');
10279                                  -- rollback quantity tree
10280                                  log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
10281                               END IF;
10282 
10283                               inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
10284 
10285                               IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10286                                  IF l_debug = 1 THEN
10287                                     log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
10288                                  END IF;
10289                                  RAISE fnd_api.g_exc_unexpected_error;
10290                               ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10291                                  IF l_debug = 1 THEN
10292                                     log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
10293                                  END IF;
10294                                  RAISE fnd_api.g_exc_error;
10295                               END IF;
10296 
10297                               -- set lpn quantity to -1
10298                               -- no need to call invalidate, since we'll never see this
10299                               -- LPN record again
10300 
10301                               -- delete allocations
10302                               DELETE FROM wms_transactions_temp
10303                                WHERE line_type_code = 2
10304                                  AND type_code = p_type_code;
10305 
10306                               IF l_debug_on THEN
10307                                  l_cur_rec  := g_lpns(l_cur_lpn_group).first_rec;
10308                                  LOOP
10309                                     g_trace_recs(l_cur_rec).entire_lpn_flag  := 'N';
10310                                     g_trace_recs(l_cur_rec).suggested_qty    := 0;
10311                                     IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10312                                        g_trace_recs(l_cur_rec).secondary_qty := 0;
10313                                     END IF;
10314                                     EXIT WHEN l_cur_rec = l_cur_lpn_rec;
10315                                     l_cur_rec                                := g_locs(l_cur_rec).next_rec;
10316                                  END LOOP;
10317                               END IF;
10318 
10319                               IF l_debug = 1 THEN
10320                                  log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
10321                               END IF;
10322 
10323                               -- Exit loop for each rec in this LPN
10324                               EXIT;
10325                            END IF; --} didn't allocate as much as expected
10326 
10327                            -- decrease quantity needed
10328                            l_needed_quantity     := l_needed_quantity - l_allocated_quantity;
10329                            l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
10330 
10331                            -- Added for 14699845 (Flexible lot allocation)
10332                            l_orig_needed_quantity := l_orig_needed_quantity - l_allocated_quantity;
10333                            l_orig_needed_sec_qty  := l_orig_needed_sec_qty  - l_sec_allocated_quantity;
10334 
10335                            IF l_debug = 1 THEN
10336                               log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
10337                               log_statement(l_api_name, 'need_qty', 'New sec needed quantity: ' || l_sec_needed_quantity);
10338 
10339                               -- Added for 14699845 (Flexible lot allocation)
10340                               log_statement(l_api_name, 'need_qty', 'New orig needed quantity: ' || l_orig_needed_quantity);
10341                               log_statement(l_api_name, 'need_qty', 'New orig needed sec qty:  ' || l_orig_needed_sec_qty);
10342                            END IF;
10343 
10344                            IF g_over_allocation = 'N'
10345                               OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
10346                               OR WMS_Engine_PVT.g_move_order_type <> 3
10347                            THEN
10348                               EXIT WHEN (  ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10349                                               AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance)
10350                                            )
10351                                         OR ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10352                                               AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance)
10353                                            )
10354                                         );
10355                            ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3
10356                            THEN
10357                               IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10358                                  IF l_max_sec_tolerance >= 0 THEN
10359                                     EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
10360                                                OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10361                                  ELSE
10362                                     EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10363                                  END IF;
10364                               ELSE
10365                                  IF l_max_tolerance >= 0 THEN
10366                                     EXIT WHEN (l_needed_quantity <= l_max_tolerance)
10367                                                OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10368                                  ELSE
10369                                     EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10370                                  END IF;
10371                               END IF;
10372                            END IF;
10373                            l_cur_lpn_rec := g_locs(l_cur_lpn_rec).next_rec;
10374 
10375                            -- end loop through lpn recs
10376                         END LOOP; --} loop through recs w/in LPN
10377 
10378                         -- if no more quantity needed, exit LPN loop
10379                         -- EXIT WHEN l_needed_quantity <= 0;
10380                         IF g_over_allocation = 'N'
10381                            OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
10382                            OR WMS_Engine_PVT.g_move_order_type <> 3
10383                         THEN
10384                            EXIT WHEN (  ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10385                                            AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance)
10386                                         )
10387                                      OR ( NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10388                                            AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance)
10389                                         )
10390                                      );
10391                         ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3
10392                         THEN
10393                            IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10394                               IF l_max_sec_tolerance >= 0 THEN
10395                                  EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
10396                                             OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10397                               ELSE
10398                                  EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
10399                               END IF;
10400                            ELSE
10401                               IF l_max_tolerance >= 0 THEN
10402                                  EXIT WHEN (l_needed_quantity <= l_max_tolerance)
10403                                             OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10404                               ELSE
10405                                  EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
10406                               END IF;
10407                            END IF;
10408                         END IF;
10409                      END IF; --} needed qty > lpn.quantity
10410 
10411                      l_cur_lpn_group  := g_lpns(l_cur_lpn_group).next_group;
10412 
10413                      IF l_debug = 1 THEN
10414                         log_statement(l_api_name, 'next_lpn', 'Next LPN in list: ' || l_cur_lpn_group);
10415                      END IF;
10416 
10417                      -- end loop through lpn groups
10418                   END LOOP; --}
10419 
10420                   -- exit outermost loop
10421                   IF l_debug = 1 THEN
10422                      log_statement(l_api_name, 'lpn_alloc_finished', 'Finished checking all LPNS.  Exit LPN allocation.');
10423                   END IF;
10424 
10425                   EXIT;
10426                END IF; --} consists exist
10427             END IF; --} if no more records
10428 
10429             -- add record to table
10430             g_locs_index := g_locs_index + 1;
10431 
10432             IF l_debug = 1 THEN
10433                log_statement(l_api_name, 'loc_index', 'loc index: ' || g_locs_index);
10434             END IF;
10435 
10436             g_locs(g_locs_index) := v_current_row;
10437 
10438             -- initialize trace records
10439             IF l_debug_on THEN
10440                log_statement(l_api_name, 'init_trace', 'Init trace record');
10441                g_trace_recs(g_locs_index).revision                 := v_current_row.revision;
10442                g_trace_recs(g_locs_index).lot_number               := v_current_row.lot_number;
10443                g_trace_recs(g_locs_index).lot_expiration_date      := v_current_row.lot_expiration_date;
10444                g_trace_recs(g_locs_index).subinventory_code        := v_current_row.subinventory_code;
10445                g_trace_recs(g_locs_index).locator_id               := v_current_row.locator_id;
10446                g_trace_recs(g_locs_index).cost_group_id            := v_current_row.cost_group_id;
10447                g_trace_recs(g_locs_index).lpn_id                   := v_current_row.lpn_id;
10448                g_trace_recs(g_locs_index).uom_code                 := v_current_row.uom_code;
10449                g_trace_recs(g_locs_index).quantity                 := v_current_row.quantity;
10450                g_trace_recs(g_locs_index).secondary_qty            := v_current_row.secondary_quantity;
10451                g_trace_recs(g_locs_index).grade_code               := v_current_row.grade_code;
10452                g_trace_recs(g_locs_index).secondary_uom_code       := v_current_row.secondary_uom_code;
10453                g_trace_recs(g_locs_index).serial_number            := v_current_row.serial_number;
10454                -- set LPN flag to no
10455                g_trace_recs(g_locs_index).consist_string_flag      := 'V';
10456                g_trace_recs(g_locs_index).partial_pick_flag        := 'Y';
10457                g_trace_recs(g_locs_index).order_string_flag        := 'V';
10458                g_trace_recs(g_locs_index).pick_uom_flag            := 'V';
10459                g_trace_recs(g_locs_index).serial_number_used_flag  := 'V';
10460                g_trace_recs(g_locs_index).entire_lpn_flag          := 'N';
10461                -- write to log file
10462                log_statement(l_api_name, 'rev', 'revision: ' || v_current_row.revision);
10463                log_statement(l_api_name, 'lot', 'lot: ' || v_current_row.lot_number);
10464                log_statement(l_api_name, 'sub', 'sub:' || v_current_row.subinventory_code);
10465                log_statement(l_api_name, 'loc', 'loc: ' || v_current_row.locator_id);
10466                log_statement(l_api_name, 'cg', 'cg: ' || v_current_row.cost_group_id);
10467                log_statement(l_api_name, 'lpn', 'lpn: ' || v_current_row.lpn_id);
10468                log_statement(l_api_name, 'sn', 'sn: ' || v_current_row.serial_number);
10469                log_statement(l_api_name, 'qty', 'quantity: ' || v_current_row.quantity);
10470                log_statement(l_api_name, 'sqty', 'secondary_quantity: ' || v_current_row.secondary_quantity);
10471                log_statement(l_api_name, 'uom', 'uom_code: ' || v_current_row.uom_code);
10472                log_statement(l_api_name, 'suom', 'secondary_uom_code: ' || v_current_row.secondary_uom_code);
10473                log_statement(l_api_name, 'ord', 'order:' || v_current_row.order_by_string);
10474                log_statement(l_api_name, 'con', 'consist:' || v_current_row.consist_string);
10475             END IF;
10476 
10477             -- if lpn already exists
10478             IF g_lpns.EXISTS(v_current_row.lpn_id) THEN --{
10479                IF l_debug = 1 THEN
10480                   log_statement(l_api_name, 'lpn_exists', 'This LPN group already exists');
10481                END IF;
10482                -- if lpn consist string is different than rec's consist string,
10483                -- this LPN will never be allocated entirely. Remove LPN from list.
10484                IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND g_lpns(v_current_row.lpn_id).total_quantity < 0)
10485                   OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND g_lpns(v_current_row.lpn_id).secondary_total_quantity < 0)
10486                THEN
10487                   IF l_debug = 1 THEN
10488                      log_statement(l_api_name, 'invalid_lpn', 'This LPN is invalid');
10489                   END IF;
10490                   GOTO nextoutputrecord;
10491                ELSIF l_consist_exists
10492                      AND g_lpns(v_current_row.lpn_id).consist_string <> v_current_row.consist_string
10493                THEN
10494                   IF l_debug = 1 THEN
10495                      log_statement(l_api_name, 'no_consist', 'This record has a '
10496                                                 || 'different consist string than its LPN.  Invalidating LPN');
10497                   END IF;
10498 
10499                   invalidate_lpn_group(v_current_row.lpn_id);
10500 
10501                   IF l_debug_on THEN
10502                      g_trace_recs(g_locs_index).consist_string_flag := 'N';
10503                      l_cur_rec := g_lpns(v_current_row.lpn_id).first_rec;
10504 
10505                      LOOP
10506                         EXIT WHEN l_cur_rec = 0;
10507                         g_trace_recs(l_cur_rec).consist_string_flag  := 'N';
10508                         l_cur_rec := g_locs(l_cur_rec).next_rec;
10509                      END LOOP;
10510                   END IF;
10511 
10512                   GOTO nextoutputrecord;
10513                   -- bug 2356370 - need to recheck the LPN total quantity to make
10514                   -- sure it doesn't exceed the needed quantity.
10515                ELSIF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10516                       AND g_lpns(v_current_row.lpn_id).total_quantity > l_needed_quantity)
10517                   OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10518                       AND g_lpns(v_current_row.lpn_id).secondary_total_quantity > l_sec_needed_quantity)
10519                THEN
10520                   IF l_debug = 1 THEN
10521                      log_statement(l_api_name, 'bad_tot_qty2', 'The total quantity for'
10522                                                 || ' this LPN exceeds the needed quantity.  Invalidating LPN.');
10523                   END IF;
10524 
10525                   invalidate_lpn_group(v_current_row.lpn_id);
10526                   -- goto next output record
10527                   GOTO nextoutputrecord;
10528                END IF;
10529 
10530                -- increase LPN quantity
10531                g_lpns(v_current_row.lpn_id).quantity := g_lpns(v_current_row.lpn_id).quantity
10532                                                           + v_current_row.quantity;
10533                g_lpns(v_current_row.lpn_id).secondary_quantity := g_lpns(v_current_row.lpn_id).secondary_quantity
10534                                                                     + v_current_row.secondary_quantity;
10535                -- set pointers
10536                g_locs(g_lpns(v_current_row.lpn_id).last_rec).next_rec := g_locs_index;
10537                g_lpns(v_current_row.lpn_id).last_rec := g_locs_index;
10538             --}
10539             ELSE
10540                --{ else lpn does not already exist
10541                IF l_debug = 1 THEN
10542                   log_statement(l_api_name, 'new_lpn', 'Creating a new LPN group');
10543                END IF;
10544 
10545                g_lpns(v_current_row.lpn_id).lpn_id                := v_current_row.lpn_id;
10546                g_lpns(v_current_row.lpn_id).first_rec             := g_locs_index;
10547                g_lpns(v_current_row.lpn_id).last_rec              := g_locs_index;
10548                g_lpns(v_current_row.lpn_id).quantity              := v_current_row.quantity;
10549                g_lpns(v_current_row.lpn_id).secondary_quantity    := v_current_row.secondary_quantity;
10550                g_lpns(v_current_row.lpn_id).grade_code            := v_current_row.grade_code;
10551                g_lpns(v_current_row.lpn_id).prev_group            := 0;
10552                g_lpns(v_current_row.lpn_id).next_group            := 0;
10553                g_lpns(v_current_row.lpn_id).prev_consist_lpn_id   := 0;
10554                g_lpns(v_current_row.lpn_id).next_consist_lpn_id   := 0;
10555                g_lpns(v_current_row.lpn_id).parent_consist_group  := 0;
10556                g_lpns(v_current_row.lpn_id).consist_string        := v_current_row.consist_string;
10557 
10558                -- query total quantity for LPN
10559                OPEN c_lpn_quantity;
10560                FETCH c_lpn_quantity INTO g_lpns(v_current_row.lpn_id).total_quantity
10561                                        , g_lpns(v_current_row.lpn_id).secondary_total_quantity;
10562                IF l_debug = 1 THEN
10563                   log_statement(l_api_name, 'tot_qty', 'Total quantity for this LPN: ' || g_lpns(v_current_row.lpn_id).total_quantity);
10564                   log_statement(l_api_name, 'tot_qty', 'Total sec quantity for this LPN: '
10565                                              || g_lpns(v_current_row.lpn_id).secondary_total_quantity);
10566                END IF;
10567 
10568                IF c_lpn_quantity%NOTFOUND
10569                   OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10570                       AND (g_lpns(v_current_row.lpn_id).total_quantity IS NULL
10571                            OR g_lpns(v_current_row.lpn_id).total_quantity <= 0
10572                            OR g_lpns(v_current_row.lpn_id).total_quantity > l_needed_quantity))
10573                   OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10574                       AND (g_lpns(v_current_row.lpn_id).secondary_total_quantity IS NULL
10575                            OR g_lpns(v_current_row.lpn_id).secondary_total_quantity <= 0
10576                            OR g_lpns(v_current_row.lpn_id).secondary_total_quantity > l_sec_needed_quantity))
10577                THEN
10578                   CLOSE c_lpn_quantity;
10579 
10580                   IF l_debug = 1 THEN
10581                      log_statement(l_api_name, 'bad_tot_qty', 'The total quantity for'
10582                                                 || ' this LPN keeps it from being allocated.  Invalidating LPN.');
10583                   END IF;
10584 
10585                   invalidate_lpn_group(v_current_row.lpn_id);
10586                   -- goto next output record
10587                   GOTO nextoutputrecord;
10588                END IF;
10589 
10590                CLOSE c_lpn_quantity;
10591 
10592                IF NVL(l_cur_order_by_string, '@@@') <> NVL(v_current_row.order_by_string, '@@@')
10593                THEN
10594                   l_order_by_rank       := l_order_by_rank + 1;
10595                   l_cur_order_by_string := v_current_row.order_by_string;
10596 
10597                   IF g_first_order_by_rank IS NULL THEN
10598                      g_first_order_by_rank := l_order_by_rank;
10599                   END IF;
10600                END IF;
10601 
10602                g_lpns(v_current_row.lpn_id).order_by_rank := l_order_by_rank;
10603                -- initialize record in LPN array
10604                g_lpns(v_current_row.lpn_id).prev_group := g_last_lpn_group;
10605 
10606                IF g_first_lpn_group = 0 THEN
10607                   g_first_lpn_group := v_current_row.lpn_id;
10608                ELSE
10609                   g_lpns(g_last_lpn_group).next_group := v_current_row.lpn_id;
10610                END IF;
10611 
10612                g_last_lpn_group := v_current_row.lpn_id;
10613             END IF; --} if lpn already exists
10614 
10615             -- validate from/to sub/loc
10616             -- if fail, invalidate LPN and goto next output record
10617             -- first check to make sure picking from dest sub is not allowed;
10618             -- then, based on type code, compare src sub to dest sub;
10619             -- next, check to see if sub and item are locator controlled;
10620             -- if loc control, go to next record only if src loc = dest loc;
10621             -- if not loc control, go to next records (since subs are equal);
10622             -- all of the global variables are set in
10623             -- wms_engine_pvt.create_suggestions
10624             IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
10625                 AND v_current_row.subinventory_code = l_to_subinventory_code)
10626             THEN
10627                IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
10628                    OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
10629                    OR (wms_engine_pvt.g_sub_loc_control = 5
10630                        AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
10631                       )
10632                   ) THEN
10633                   IF (v_current_row.locator_id = l_to_locator_id) THEN
10634                      IF l_debug = 1 THEN
10635                         log_event(l_api_name, 'sub_loc_same', 'Cannot use this '
10636                                                || 'location since source subinventory and locator are'
10637                                                || ' same as destination subinventory and locator');
10638                      END IF;
10639 
10640                      IF l_debug_on THEN
10641                         g_trace_recs(g_locs_index).same_subinv_loc_flag := 'N';
10642                      END IF;
10643 
10644                      invalidate_lpn_group(v_current_row.lpn_id);
10645                      GOTO nextoutputrecord;
10646                   END IF;
10647                ELSE
10648                   IF l_debug = 1 THEN
10649                      log_event(l_api_name, 'sub_same', 'Cannot use this '
10650                                             || 'location since source subinventory is '
10651                                             || 'same as destination subinventory');
10652                   END IF;
10653 
10654                   IF l_debug_on THEN
10655                      g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'N';
10656                   END IF;
10657 
10658                   invalidate_lpn_group(v_current_row.lpn_id);
10659                   GOTO nextoutputrecord;
10660                END IF;
10661             END IF;
10662 
10663             IF l_debug_on THEN
10664                g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'Y';
10665             END IF;
10666 
10667             -- query quantity tree
10668             -- If att < rec quantity, invalidate LPN and goto next output record
10669 
10670             IF l_debug = 1 THEN
10671                log_statement(l_api_name, 'query tree', 'Calling Query Tree');
10672             END if;
10673             -- BUG 3609380
10674             -- Allocation was being treated as a subinventory transfer, and hence not honoring
10675             -- reservations alredy made on any level higher than SUB. Changes to treat as Issue
10676             -- by removing l_to_subinevntory_code.
10677             inv_quantity_tree_pvt.query_tree(
10678                 p_api_version_number         => g_qty_tree_api_version
10679               , p_init_msg_lst               => fnd_api.g_false -- p_init_msg_lst
10680               , x_return_status              => x_return_status
10681               , x_msg_count                  => x_msg_count
10682               , x_msg_data                   => x_msg_data
10683               , p_tree_id                    => p_tree_id
10684               , p_revision                   => v_current_row.revision
10685               , p_lot_number                 => v_current_row.lot_number
10686               , p_subinventory_code          => v_current_row.subinventory_code
10687               , p_locator_id                 => v_current_row.locator_id
10688               , x_qoh                        => l_qoh
10689               , x_sqoh                       => l_sqoh
10690               , x_rqoh                       => l_rqoh
10691               , x_srqoh                      => l_srqoh
10692               , x_qr                         => l_qr
10693               , x_sqr                        => l_sqr
10694               , x_qs                         => l_qs
10695               , x_sqs                        => l_sqs
10696               , x_att                        => l_att
10697               , x_satt                       => l_satt
10698               , x_atr                        => l_atr
10699               , x_satr                       => l_satr
10700               , p_transfer_subinventory_code => chk_for_passing_xfer_sub(p_transaction_temp_id
10701                                                                         ,l_to_subinventory_code) -- Bug# 4099907
10702               , p_cost_group_id              => v_current_row.cost_group_id
10703               , p_lpn_id                     => v_current_row.lpn_id
10704               );
10705 
10706             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10707                IF l_debug = 1 THEN
10708                   log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
10709                END IF;
10710                RAISE fnd_api.g_exc_unexpected_error;
10711             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10712                IF l_debug = 1 THEN
10713                   log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
10714                END if;
10715                RAISE fnd_api.g_exc_error;
10716             END IF;
10717 
10718             IF l_debug = 1 THEN
10719                log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
10720                log_statement(l_api_name, 'sec_att_qty', 'Available sec quantity = ' || l_satt);
10721             END IF;
10722 
10723             -- If not all of the record is available, then we can't allocate
10724             -- the entire LPN
10725             IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_att < v_current_row.quantity)
10726                 OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_satt < v_current_row.secondary_quantity)
10727             THEN
10728                IF l_debug = 1 THEN
10729                   log_statement(l_api_name, 'not_enough_att', 'Not all the material is available for this rec. Skipping this LPN');
10730                END IF;
10731                IF l_debug_on THEN
10732                   g_trace_recs(g_locs_index).att_qty           := l_att;
10733                   g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
10734                   g_trace_recs(g_locs_index).att_qty_flag      := 'N';
10735                END IF;
10736                invalidate_lpn_group(v_current_row.lpn_id);
10737                GOTO nextoutputrecord;
10738             END IF;
10739 
10740             IF l_debug_on THEN
10741                g_trace_recs(g_locs_index).att_qty           := l_att;
10742                g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
10743                g_trace_recs(g_locs_index).att_qty_flag      := 'Y';
10744             END IF;
10745 
10746             -- If LPN is not in first order by group OR
10747             -- goto next output record
10748             IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10749                    AND g_lpns(v_current_row.lpn_id).quantity < g_lpns(v_current_row.lpn_id).total_quantity)
10750                OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10751                    AND g_lpns(v_current_row.lpn_id).secondary_quantity < g_lpns(v_current_row.lpn_id).secondary_total_quantity)
10752                )
10753             THEN
10754                IF l_debug = 1 THEN
10755                   log_statement(l_api_name, 'not_enough_lpn_qty',
10756                                             'Not enough quantity allocated for this LPN. Getting next record');
10757                END IF;
10758                -- Bug #5345736
10759                -- invalidate_lpn_group(v_current_row.lpn_id); --bug 6831349
10760                GOTO nextoutputrecord;
10761             END IF;
10762 
10763             IF l_consist_exists THEN --{
10764                -- find consist group
10765                -- used in get_hash_value.  That procedure works best if
10766                -- hashsize is power of 2
10767                l_hash_size := POWER(2, 15);
10768                -- get hash index for this consist string
10769                IF l_debug = 1 THEN
10770                   log_statement(l_api_name, 'get_hash_value', 'Calling get_hash_value for consist string');
10771                END IF;
10772                l_cur_consist_group := DBMS_UTILITY.get_hash_value(
10773                                            NAME => g_lpns(v_current_row.lpn_id).consist_string
10774                                          , base => 1
10775                                          , hash_size => l_hash_size
10776                                          );
10777                -- Because the hash function can return the same index for different
10778                -- consist strings, we have to check to see if the group at the index
10779                -- returned above has the same consist string as the current record.
10780                -- If not, look at the next record.  Continue on until we find the
10781                -- correct consist group or determine that the group has not been
10782                -- defined yet
10783                LOOP
10784                   EXIT WHEN NOT g_consists.EXISTS(l_cur_consist_group);
10785                   EXIT WHEN g_consists(l_cur_consist_group).consist_string = g_lpns(v_current_row.lpn_id).consist_string;
10786                   l_cur_consist_group  := l_cur_consist_group + 1;
10787                END LOOP;
10788 
10789                -- see if consist group already exists
10790                -- If group does exist
10791                IF g_consists.EXISTS(l_cur_consist_group) THEN
10792                   IF l_debug = 1 THEN
10793                      log_statement(l_api_name, 'group_exists', 'The consist group already exists');
10794                   END IF;
10795 
10796                   -- if lpn quantity would exceed needed quantity, invalidate lpn
10797                   IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10798                          AND (g_consists(l_cur_consist_group).quantity
10799                                 + g_lpns(v_current_row.lpn_id).quantity) > l_needed_quantity)
10800                      OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10801                          AND (g_consists(l_cur_consist_group).secondary_quantity
10802                                 + g_lpns(v_current_row.lpn_id).secondary_quantity) > l_sec_needed_quantity)
10803                      )
10804                   THEN
10805                      IF l_debug = 1 THEN
10806                         log_statement(l_api_name, 'too_much_qty', 'LPN quantity would exceed quantity needed.');
10807                      END IF;
10808 
10809                      invalidate_lpn_group(v_current_row.lpn_id);
10810                      GOTO nextoutputrecord;
10811                   END IF;
10812 
10813                   -- set pointer values
10814                   g_lpns(v_current_row.lpn_id).prev_consist_lpn_id := g_consists(l_cur_consist_group).last_rec;
10815                   g_lpns(g_consists(l_cur_consist_group).last_rec).next_consist_lpn_id := v_current_row.lpn_id;
10816                   g_consists(l_cur_consist_group).last_rec := v_current_row.lpn_id;
10817                   -- increase group quantity
10818                   g_consists(l_cur_consist_group).quantity := g_consists(l_cur_consist_group).quantity
10819                                                                 + g_lpns(v_current_row.lpn_id).quantity;
10820                   IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
10821                      g_consists(l_cur_consist_group).secondary_quantity := g_consists(l_cur_consist_group).secondary_quantity
10822                                                                              + g_lpns(v_current_row.lpn_id).secondary_quantity;
10823                   END IF;
10824                ELSE
10825                   -- If group does not exist
10826                   IF l_debug = 1 THEN
10827                      log_statement(l_api_name, 'new_group', 'Creating a new consist group');
10828                   END IF;
10829 
10830                   -- create new group
10831                   g_consists(l_cur_consist_group).consist_string     := g_lpns(v_current_row.lpn_id).consist_string;
10832                   g_consists(l_cur_consist_group).first_rec          := v_current_row.lpn_id;
10833                   g_consists(l_cur_consist_group).last_rec           := v_current_row.lpn_id;
10834                   g_consists(l_cur_consist_group).next_group         := 0;
10835                   g_consists(l_cur_consist_group).quantity           := v_current_row.quantity;
10836                   g_consists(l_cur_consist_group).secondary_quantity := v_current_row.secondary_quantity;
10837                   g_consists(l_cur_consist_group).grade_code         := v_current_row.grade_code;
10838                   g_consists(l_cur_consist_group).order_by_rank      := g_lpns(v_current_row.lpn_id).order_by_rank;
10839 
10840                   IF g_first_consist_group = 0 THEN
10841                      g_first_consist_group := l_cur_consist_group;
10842                   ELSE
10843                      g_consists(g_last_consist_group).next_group := l_cur_consist_group;
10844                   END IF;
10845                   g_last_consist_group := l_cur_consist_group;
10846                END IF;
10847 
10848                g_lpns(v_current_row.lpn_id).parent_consist_group := l_cur_consist_group;
10849 
10850                -- only allocate a consist group if the quantity = needed quantity exactly
10851                IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10852                       AND g_consists(l_cur_consist_group).quantity < (l_needed_quantity - l_max_tolerance))
10853                   OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10854                       AND g_consists(l_cur_consist_group).secondary_quantity < (l_sec_needed_quantity - l_max_sec_tolerance))
10855                   )
10856                THEN
10857                   IF l_debug = 1 THEN
10858                      log_statement(l_api_name, 'not_enough_qty', 'Not enough quantity to allocate consist group');
10859                   END IF;
10860 
10861                   GOTO nextoutputrecord;
10862                END IF;
10863 
10864                IF g_consists(l_cur_consist_group).order_by_rank <> g_first_order_by_rank
10865                THEN
10866                   IF l_debug = 1 THEN
10867                      log_statement(l_api_name, 'consist_order_by', 'Consist group is not first based on sort criteria');
10868                   END IF;
10869                   GOTO nextoutputrecord;
10870                END IF;
10871 
10872                l_lpn_id := g_consists(l_cur_consist_group).first_rec;
10873             --}
10874             ELSIF g_lpns(v_current_row.lpn_id).order_by_rank <> g_first_order_by_rank THEN
10875                -- no consists
10876                IF l_debug = 1 THEN
10877                   log_statement(l_api_name, 'not_first_order_by', 'Not first LPN based on sort criteria.  Getting next record.');
10878                END IF;
10879                GOTO nextoutputrecord;
10880             ELSE
10881                l_lpn_id  := v_current_row.lpn_id;
10882             END IF;
10883 
10884             LOOP --{ loop through LPNS
10885                -- Allocation process.  If consist exists, we loop through all
10886                -- the lpns in the consist group.  If no consistency restrictions,
10887                -- we exit the loop after allocating the first lpn
10888 
10889                IF l_debug = 1 THEN
10890                   log_statement(l_api_name, 'alloc_lpn', 'Allocation lpn: ' || l_lpn_id);
10891                END IF;
10892 
10893                -- Allocate the LPN, since the LPN is in the first order by group
10894                -- and the LPN has all possible suggestions
10895                -- For each record in LPN
10896                l_cur_lpn_rec      := g_lpns(l_lpn_id).first_rec;
10897 
10898                LOOP --{
10899                   EXIT WHEN l_cur_lpn_rec = 0;
10900 
10901                   -- Call validate and insert
10902                   IF l_debug_on THEN
10903                      g_trace_recs(l_cur_lpn_rec).consist_string_flag  := 'Y';
10904                      g_trace_recs(l_cur_lpn_rec).entire_lpn_flag      := 'Y';
10905                   END IF;
10906 
10907                   IF l_debug = 1 THEN
10908                      log_statement(l_api_name, 'val_insert', 'Calling validate_and_insert');
10909                   END IF;
10910 
10911                   validate_and_insert(
10912                     x_return_status              => x_return_status
10913                   , x_msg_count                  => x_msg_count
10914                   , x_msg_data                   => x_msg_data
10915                   , p_record_id                  => l_cur_lpn_rec
10916                   , p_needed_quantity            => l_needed_quantity
10917                   , p_use_pick_uom               => FALSE
10918                   , p_organization_id            => p_organization_id
10919                   , p_inventory_item_id          => p_inventory_item_id
10920                   , p_to_subinventory_code       => l_to_subinventory_code
10921                   , p_to_locator_id              => l_to_locator_id
10922                   , p_to_cost_group_id           => l_to_cost_group_id
10923                   , p_primary_uom                => p_primary_uom
10924                   , p_transaction_uom            => p_transaction_uom
10925                   , p_transaction_temp_id        => p_transaction_temp_id
10926                   , p_type_code                  => p_type_code
10927                   , p_rule_id                    => l_rule_id
10928                   , p_reservation_id             => l_reservation_id
10929                   , p_tree_id                    => p_tree_id
10930                   , p_debug_on                   => l_debug_on
10931                   , p_needed_sec_quantity        => l_sec_needed_quantity
10932                   , p_secondary_uom              => p_secondary_uom
10933                   , p_grade_code                 => p_grade_code
10934                   , x_inserted_record            => l_inserted_record
10935                   , x_allocated_quantity         => l_allocated_quantity
10936                   , x_remaining_quantity         => l_remaining_quantity
10937                   , x_sec_allocated_quantity     => l_sec_allocated_quantity
10938                   , x_sec_remaining_quantity     => l_sec_remaining_quantity
10939                   , p_orig_needed_quantity       => l_needed_quantity     -- Added for 14699845 (Flexible lot allocation)
10940                   , p_orig_needed_sec_qty        => l_sec_needed_quantity -- Added for 14699845 (Flexible lot allocation)
10941                   , p_simulation_mode            => p_simulation_mode     -- Added for 14699845 (Flexible lot allocation)
10942                   );
10943 
10944                   IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10945                      IF l_debug = 1 THEN
10946                         log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
10947                      END IF;
10948 
10949                      RAISE fnd_api.g_exc_unexpected_error;
10950                   ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10951                      IF l_debug = 1 THEN
10952                         log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
10953                      END IF;
10954 
10955                      RAISE fnd_api.g_exc_error;
10956                   END IF;
10957 
10958                   -- If this fails
10959                   IF l_inserted_record = FALSE
10960                      OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
10961                          AND l_allocated_quantity < g_locs(l_cur_lpn_rec).quantity)
10962                      OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
10963                          AND l_sec_allocated_quantity < g_locs(l_cur_lpn_rec).secondary_quantity)
10964                   THEN --{
10965                      IF l_debug = 1 THEN
10966                         log_statement(l_api_name, 'insert_fail', 'Record failed to insert.' || 'Invalidating LPN');
10967                      END IF;
10968 
10969                      -- invalidate LPN
10970                      IF l_consist_exists THEN
10971                         l_cur_consist_group := g_lpns(l_lpn_id).parent_consist_group;
10972                         l_prev_rec := g_lpns(l_lpn_id).prev_consist_lpn_id;
10973                         l_next_rec := g_lpns(l_lpn_id).next_consist_lpn_id;
10974                         g_consists(l_cur_consist_group).quantity := g_consists(l_cur_consist_group).quantity
10975                                                                       - g_lpns(l_lpn_id).quantity;
10976                         g_consists(l_cur_consist_group).secondary_quantity := g_consists(l_cur_consist_group).secondary_quantity
10977                                                                                 - g_lpns(l_lpn_id).secondary_quantity;
10978 
10979                         IF g_consists(l_cur_consist_group).first_rec = l_lpn_id THEN
10980                            g_consists(l_cur_consist_group).first_rec := l_next_rec;
10981                            g_consists(l_cur_consist_group).order_by_rank := g_lpns(l_next_rec).order_by_rank;
10982                         END IF;
10983 
10984                         IF g_consists(l_cur_consist_group).last_rec = l_lpn_id THEN
10985                            g_consists(l_cur_consist_group).last_rec  := l_prev_rec;
10986                         END IF;
10987 
10988                         g_lpns(l_next_rec).prev_consist_lpn_id    := l_prev_rec;
10989                         g_lpns(l_prev_rec).next_consist_lpn_id    := l_next_rec;
10990                      END IF;
10991 
10992                      invalidate_lpn_group(l_lpn_id);
10993 
10994                      -- restore quantity tree
10995                      IF l_debug = 1 THEN
10996                         log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
10997                      END IF;
10998 
10999                      inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
11000 
11001                      IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
11002                         IF l_debug = 1 THEN
11003                            log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
11004                         END IF;
11005                         RAISE fnd_api.g_exc_unexpected_error;
11006                      ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
11007                         IF l_debug = 1 THEN
11008                            log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
11009                         END IF;
11010                         RAISE fnd_api.g_exc_error;
11011                      END IF;
11012 
11013                      -- delete allocations
11014                      -- is this okay?? what if multiple input lines?
11015                      DELETE FROM wms_transactions_temp
11016                       WHERE line_type_code = 2
11017                         AND type_code = p_type_code;
11018 
11019                      IF l_debug_on THEN
11020                         l_cur_rec  := g_lpns(l_lpn_id).first_rec;
11021                         LOOP
11022                            g_trace_recs(l_cur_rec).entire_lpn_flag  := 'N';
11023                            g_trace_recs(l_cur_rec).suggested_qty := 0;
11024                            IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
11025                               g_trace_recs(l_cur_rec).secondary_qty := 0;
11026                            END IF;
11027                            EXIT WHEN l_cur_rec = l_cur_lpn_rec;
11028                            l_cur_rec := g_locs(l_cur_rec).next_rec;
11029                         END LOOP;
11030                      END IF;
11031 
11032                      IF l_debug = 1 THEN
11033                         log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
11034                      END IF;
11035 
11036                      -- With this LPN invalidated, go get next record
11037                      GOTO nextoutputrecord;
11038                   END IF; --}
11039 
11040                   l_cur_lpn_rec  := g_locs(l_cur_lpn_rec).next_rec;
11041                   -- end loop (each rec in lpn)
11042                END LOOP; --}
11043 
11044                -- decrease quantity needed
11045                l_needed_quantity := l_needed_quantity - g_lpns(l_lpn_id).quantity;
11046                l_sec_needed_quantity := l_sec_needed_quantity - g_lpns(l_lpn_id).secondary_quantity;
11047 
11048                -- Added for 14699845 (Flexible lot allocation)
11049                l_orig_needed_quantity := l_orig_needed_quantity - g_lpns(l_lpn_id).quantity;
11050                l_orig_needed_sec_qty  := l_orig_needed_sec_qty  - g_lpns(l_lpn_id).secondary_quantity;
11051 
11052                IF l_debug = 1 THEN
11053                   log_statement(l_api_name, 'need_qty', 'New Needed Quantity: ' || l_needed_quantity);
11054                   log_statement(l_api_name, 'need_qty', 'New sec Needed Quantity: ' || l_sec_needed_quantity);
11055 
11056                   -- Added for 14699845 (Flexible lot allocation)
11057                   log_statement(l_api_name, 'need_qty', 'New orig needed quantity: ' || l_orig_needed_quantity);
11058                   log_statement(l_api_name, 'need_qty', 'New orig needed sec qty:  ' || l_orig_needed_sec_qty);
11059                END IF;
11060 
11061                IF g_over_allocation = 'N'
11062                   OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
11063                   OR WMS_Engine_PVT.g_move_order_type <> 3
11064                THEN
11065                   EXIT WHEN (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
11066                                 AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance))
11067                             OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
11068                                 AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance))
11069                             );
11070                ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
11071                   IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
11072                      IF l_max_sec_tolerance >= 0 THEN
11073                         EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
11074                                    OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11075                      ELSE
11076                         EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11077                      END IF;
11078                   ELSE
11079                      IF l_max_tolerance >= 0 THEN
11080                         EXIT WHEN (l_needed_quantity <= l_max_tolerance)
11081                                    OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11082                      ELSE
11083                         EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11084                      END IF;
11085                   END IF;
11086                END IF;
11087 
11088                -- Once LPN has been allocated, remove it from the LPN list
11089                IF l_consist_exists THEN
11090                   l_lpn_id  := g_lpns(l_lpn_id).next_consist_lpn_id;
11091                   EXIT WHEN l_lpn_id = 0;
11092                ELSE
11093                   invalidate_lpn_group(l_lpn_id);
11094                   EXIT;
11095                END IF;
11096             END LOOP; --} loop through LPNS
11097 
11098             IF g_over_allocation = 'N'
11099                OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
11100                OR WMS_Engine_PVT.g_move_order_type <> 3
11101             THEN
11102                EXIT WHEN (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
11103                              AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance))
11104                          OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
11105                              AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance))
11106                          );
11107             ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
11108                IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
11109                   IF l_max_sec_tolerance >= 0 THEN
11110                      EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
11111                                 OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11112                   ELSE
11113                      EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11114                   END IF;
11115                ELSE
11116                   IF l_max_tolerance >= 0 THEN
11117                      EXIT WHEN (l_needed_quantity <= l_max_tolerance)
11118                                 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11119                   ELSE
11120                      EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11121                   END IF;
11122                END IF;
11123             END IF;
11124 
11125             <<nextoutputrecord>>
11126             NULL;
11127          -- End outermost loop
11128          END LOOP; --}
11129       --} else if type code = 2
11130       ELSIF p_type_code = 2 THEN --{
11131          -- PICK
11132          l_cur_uom_rec         := 0;
11133          l_first_uom_rec       := 0;
11134          l_last_uom_rec        := 0;
11135          l_cur_consist_group   := 0;
11136          g_first_consist_group := 0;
11137 
11138          IF l_debug = 1 THEN
11139             log_statement(l_api_name, 'start_alloc', 'Start allocation process');
11140          END IF;
11141 
11142          -- bug#9589015 start
11143          l_allocate_serial_flag := inv_cache.org_rec.allocate_serial_flag;
11144 
11145          IF l_debug = 1 THEN
11146             log_statement(l_api_name, 'allocate_serial_flag', 'allocate_serial_flag = '||l_allocate_serial_flag);
11147          END IF;
11148          -- bug#9589015 end
11149 
11150          --for each record returned from cursor
11151          LOOP --{ Get record from rules cursor
11152             IF l_debug = 1 THEN
11153                log_statement(l_api_name, 'fetch_cursor', 'Getting rec from rule with FetchCursor');
11154             END IF;
11155             -- Added the loop for Mat Stat check --
11156             LOOP --{
11157                IF l_debug = 1 THEN
11158                   log_statement(l_api_name, 'fetch_cursor', 'inside Mat Stat check LOOP');
11159                END IF;
11160                -- bug#9589015 start
11161                -- For custom serial
11162                IF ( l_allocate_serial_flag = 'C' )
11163                     AND (NVL(l_custom_serial_index,-1) < NVL(l_custom_select_serials.serial_number.LAST,-1))
11164                THEN
11165                   -- next record should be next serial from custom API
11166                   l_custom_serial_index := l_custom_serial_index + 1;
11167                   v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
11168                   v_current_row.quantity := 1;
11169                ELSE --{
11170                   -- bug#9589015 end
11171                   --  Mat Stat --
11172                   fetchcursor(
11173                     x_return_status
11174                   , x_msg_count
11175                   , x_msg_data
11176                   , v_pick_cursor
11177                   , l_rule_id
11178                   , v_current_row.revision
11179                   , v_current_row.lot_number
11180                   , v_current_row.lot_expiration_date
11181                   , v_current_row.subinventory_code
11182                   , v_current_row.locator_id
11183                   , v_current_row.cost_group_id
11184                   , v_current_row.uom_code
11185                   , v_current_row.lpn_id
11186                   , v_current_row.serial_number
11187                   , v_current_row.quantity
11188                   , v_current_row.secondary_quantity               -- new
11189                   , v_current_row.grade_code                       -- new
11190                   , v_current_row.consist_string
11191                   , v_current_row.order_by_string
11192                   , l_rows
11193                   );
11194                   EXIT WHEN  nvl(l_rows, 0)  = 0 ;  --bug#9589015
11195                   IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
11196                      IF l_debug = 1 THEN
11197                         log_error(l_api_name, 'uerr_fetch_cursor', 'Unexpected error in FetchCursor');
11198                      END IF;
11199                      RAISE fnd_api.g_exc_unexpected_error;
11200                   ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
11201                      IF l_debug = 1 THEN
11202                         log_error(l_api_name, 'err_fetch_cursor', 'Error in FetchCursor');
11203                      END IF;
11204                      RAISE fnd_api.g_exc_error;
11205                   END IF;
11206 
11207                   -- is_serial_trx_allowed is_sub_loc_lot_trx_allowed
11208                   -- bug#9589015 start
11209 
11210                   -- Start 2 of bug 13026723 change
11211                   IF inv_cache.set_mtt_rec(p_transaction_type_id) THEN
11212                      IF ( v_current_row.lpn_id IS NOT NULL AND inv_cache.mtt_rec.transaction_source_type_id = 4
11213                            AND inv_cache.mtt_rec.transaction_action_id= 2
11214                            AND IS_LPN_CYC_RESERVED (p_organization_id,v_current_row.lpn_id) )
11215                      THEN
11216                         IF l_debug = 1 THEN
11217                            log_error(l_api_name, 'lpn cycle count reserved check ',
11218                                                  'This LPN has Cycle count reservation. Hence skipping it.');
11219                         END IF;
11220                         GOTO nextoutputrecord2;
11221                      END IF;
11222                   END IF;
11223                   -- End 2 of bug 13026723 change
11224 
11225                   IF (l_allocate_serial_flag = 'C' AND l_is_serial_control = 1) THEN --{
11226                      -- Moved this piece of code inside the IF condition for bug#14574893 -- 12687878
11227                      IF p_transaction_type_id in (52,53) THEN --sales orders, internal orders
11228                         BEGIN
11229                            SELECT source_header_type_id, source_header_id, source_line_id
11230                              INTO l_source_type_id, l_source_header_id, l_source_line_id
11231                              FROM wsh_delivery_details
11232                             WHERE move_order_line_id = p_transaction_temp_id
11233                               AND rownum = 1;
11234                         EXCEPTION
11235                            WHEN NO_DATA_FOUND THEN
11236                               l_source_type_id := null;
11237                               l_source_header_id := null;
11238                               l_source_line_id := null;
11239                         END;
11240                      END IF;
11241 
11242                      IF l_debug = 1 THEN
11243                         log_statement(l_api_name, 'value of - l_source_type_id ',l_source_type_id);
11244                         log_statement(l_api_name, 'value of - l_source_header_id ',l_source_header_id);
11245                         log_statement(l_api_name, 'value of - l_source_line_id ',l_source_line_id);
11246                      END IF;
11247 
11248                      INV_DETAIL_SERIAL_PUB.Get_User_Serial_Numbers (
11249                          x_return_status           => x_return_status
11250                        , x_msg_count               => x_msg_count
11251                        , x_msg_data                => x_msg_data
11252                        , p_organization_id         => p_organization_id
11253                        , p_inventory_item_id       => p_inventory_item_id
11254                        , p_revision                => v_current_row.revision
11255                        , p_lot_number              => v_current_row.lot_number
11256                        , p_subinventory_code       => v_current_row.subinventory_code
11257                        , p_locator_id              => v_current_row.locator_id
11258                        , p_required_sl_qty         => v_current_row.quantity
11259                        , p_from_range              => p_from_serial
11260                        , p_to_range                => p_to_serial
11261                        , p_unit_number             => l_unit_number
11262                        , p_cost_group_id           => l_cost_group_id
11263                        , p_transaction_type_id     => p_transaction_type_id -- 12687878
11264                        , p_demand_source_type_id   => l_source_type_id   -- p_demand_source_type_id   -- 12687878
11265                        , p_demand_source_header_id => l_source_header_id -- p_demand_source_header_id -- 12687878
11266                        , p_demand_source_line_id   => l_source_line_id   -- p_demand_source_line_id   -- 12687878
11267                        , x_serial_numbers          => l_custom_select_serials );
11268 
11269                      IF ( x_return_status = fnd_api.g_ret_sts_unexp_error ) THEN
11270                         IF ( l_debug = 1 ) THEN
11271                            log_error(l_api_name, 'uerr_Get_User_Serial_Numbers', 'Unexpected error in Get_User_Serial_Numbers');
11272                         END IF;
11273                         RAISE fnd_api.g_exc_unexpected_error;
11274                      ELSIF ( x_return_status = fnd_api.g_ret_sts_error ) THEN
11275                         IF ( l_debug = 1 ) THEN
11276                            log_error(l_api_name, 'Get_User_Serial_Numbers', 'Error in Get_User_Serial_Numbers');
11277                         END IF;
11278                         RAISE fnd_api.g_exc_error;
11279                      END IF;
11280                      IF l_debug = 1 THEN
11281                         log_statement(l_api_name, 'Serial Status - l_custom_serial_index ', l_custom_serial_index);
11282                      END IF;
11283 
11284                      l_custom_serial_index := l_custom_select_serials.serial_number.FIRST;
11285                      v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
11286                      v_current_row.quantity := 1;
11287                   END IF; --}
11288                END IF; --} custom serial
11289 
11290                -- is_serial_trx_allowed is_sub_loc_lot_trx_allowed
11291                l_sub_loc_lot_trx_allowed := 'Y';
11292                l_serial_trx_allowed      := 'Y';
11293                l_serial_status_id        :=  0;
11294 
11295                -- bug#9589015 end
11296 
11297                IF l_debug = 1 THEN
11298                   log_statement(l_api_name, 'Serial Status - l_detail_serial ', l_detail_serial);
11299                   log_statement(l_api_name, 'fetch_cursor - l_rows ', l_rows);
11300                   log_statement(l_api_name, 'fetch_cursor - v_current_row.lot_number ', v_current_row.lot_number);
11301                   log_statement(l_api_name, 'fetch_cursor - v_current_row.serial_number ', v_current_row.serial_number);
11302                END IF;
11303 
11304                IF v_current_row.serial_number IS NOT NULL  THEN
11305                   IF l_detail_serial = 1 THEN
11306                      SELECT status_id
11307                        INTO l_serial_status_id
11308                        FROM mtl_serial_numbers
11309                       WHERE inventory_item_id       = p_inventory_item_id
11310                         AND current_organization_id = p_organization_id
11311                         AND serial_number           = v_current_row.serial_number;
11312 
11313                      l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
11314                                                  p_transaction_type_id
11315                                                 ,p_organization_id
11316                                                 ,p_inventory_item_id
11317                                                 ,l_serial_status_id) ;
11318                   END IF;
11319 
11320                   IF l_debug = 1 THEN
11321                      log_statement(l_api_name, 'Serial Status - p_transaction_type_id ', p_transaction_type_id);
11322                      log_statement(l_api_name, 'Serial Status - p_organization_id ', p_organization_id);
11323                      log_statement(l_api_name, 'Serial Status - p_inventory_item_id ', p_inventory_item_id);
11324                      log_statement(l_api_name, 'Serial Status - serial_number ', v_current_row.serial_number);
11325                      log_statement(l_api_name, 'Serial Status - l_serial_status_id ', l_serial_status_id);
11326                      log_statement(l_api_name, 'Serial Status - l_serial_trx_allowed ', l_serial_trx_allowed);
11327                   END IF;
11328                END IF;
11329 
11330                -- LPN Status Project
11331                l_onhand_status_trx_allowed := 'Y';
11332                IF l_default_status_id = -1 THEN
11333                   l_onhand_status_trx_allowed := 'N';
11334                   l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
11335                                                    p_transaction_type_id
11336                                                   ,p_organization_id
11337                                                   ,p_inventory_item_id
11338                                                   ,v_current_row.subinventory_code
11339                                                   ,v_current_row.locator_id
11340                                                   ,v_current_row.lot_number);
11341 
11342                   IF l_debug = 1 THEN
11343                      log_statement(l_api_name, 'fetch_cursor - l_sub_loc_lot_trx_allowed: ', l_sub_loc_lot_trx_allowed);
11344                   END IF;
11345                ELSE
11346                   l_sub_loc_lot_trx_allowed:='N';
11347                   IF (inv_cache.item_rec.serial_number_control_code IN (1,6)) THEN
11348                      l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
11349                                                         p_transaction_type_id
11350                                                        ,p_organization_id
11351                                                        ,p_inventory_item_id
11352                                                        ,v_current_row.subinventory_code
11353                                                        ,v_current_row.locator_id
11354                                                        ,v_current_row.lot_number
11355                                                        ,v_current_row.lpn_id);
11356                   END IF;
11357                   IF l_debug = 1 THEN
11358                      log_statement(l_api_name, 'fetch_cursor - l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
11359                   END IF;
11360                END IF;
11361 
11362                EXIT WHEN (l_serial_trx_allowed = 'Y'
11363                           AND (l_sub_loc_lot_trx_allowed = 'Y' OR l_onhand_status_trx_allowed='Y'));
11364 
11365                -- >> Else fetch next record from the rule cursor --
11366             END LOOP; --}
11367             -- End of Mat Stat Check --
11368             -- LPN Status Project
11369 
11370             v_current_row.next_rec  := 0;
11371 
11372             -- if no more records
11373             IF l_rows = 0 THEN --{
11374                IF l_debug = 1 THEN
11375                   log_statement(l_api_name, 'no_recs', 'No more records from cursor');
11376                END IF;
11377 
11378                -- (FOR R12.1 REPLENISHMENT PROJECT - 6681109) STARTS ---
11379                -- IN R12 BRANCH , the code will not do any harm as the allocation mode = 5 value
11380                -- is only available in R12 Main Line code and the logic in contained WITH value =  here
11381 
11382                -- if allocation mode = 5
11383                IF l_allocation_mode = 5 AND l_first_uom_rec <> 0
11384                   AND (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_orig_needed_quantity > 0)
11385                       OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_orig_needed_sec_qty > 0)
11386                       )
11387                THEN
11388                   -- After all location-based records (from where there was possibility of getting allocation in the
11389                   -- first round of scan) gets exhausted, it comes here for the second round of scan. At that point,
11390                   -- we know the final unallocated qty after the first round of scan and that is the qty which are
11391                   -- candidate for replenishment
11392 
11393                   IF l_debug = 1 THEN
11394                      log_statement(l_api_name, 'exit_final_unallocated_qty',
11395                                                'Can not allocate any further with pick UOM for current input RECORD '
11396                                                 || '- COMING out of the outer loop');
11397                   END IF;
11398 
11399                   EXIT; -- Can not allocate any further; so come out of the outer loop
11400 
11401                   -- (FOR R12.1 REPLENISHMENT PROJECT - 6681109) ENDS ---
11402 
11403                   -- if allocation mode IN 3,4
11404                ELSIF l_allocation_mode IN (3, 4) AND l_first_uom_rec <> 0 THEN --{
11405                   -- for each record in pick uom list
11406                   IF l_debug = 1 THEN
11407                      log_statement(l_api_name, 'pick_uom', 'Allocate pick UOM table');
11408                   END IF;
11409                   LOOP --{
11410                      l_cur_uom_rec := l_first_uom_rec;
11411                      EXIT WHEN l_cur_uom_rec = 0;
11412                      -- remove rec from list
11413                      l_first_uom_rec := g_locs(l_cur_uom_rec).next_rec;
11414                      g_locs(l_cur_uom_rec).next_rec := 0;
11415 
11416                      -- If consist restrictions
11417                      IF l_consist_exists THEN --{
11418                         IF l_debug = 1 THEN
11419                            log_statement(l_api_name, 'insert_consist', 'Calling Insert_Consist_Record');
11420                         END IF;
11421 
11422                         -- call insert consist record
11423                         insert_consist_record(
11424                           x_return_status              => x_return_status
11425                         , x_msg_count                  => x_msg_count
11426                         , x_msg_data                   => x_msg_data
11427                         , p_record_id                  => l_cur_uom_rec
11428                         , p_needed_quantity            => l_needed_quantity
11429                         , p_use_pick_uom               => FALSE
11430                         , p_organization_id            => p_organization_id
11431                         , p_inventory_item_id          => p_inventory_item_id
11432                         , p_to_subinventory_code       => l_to_subinventory_code
11433                         , p_to_locator_id              => l_to_locator_id
11434                         , p_to_cost_group_id           => l_to_cost_group_id
11435                         , p_primary_uom                => p_primary_uom
11436                         , p_transaction_uom            => p_transaction_uom
11437                         , p_transaction_temp_id        => p_transaction_temp_id
11438                         , p_type_code                  => p_type_code
11439                         , p_rule_id                    => l_rule_id
11440                         , p_reservation_id             => l_reservation_id
11441                         , p_tree_id                    => p_tree_id
11442                         , p_debug_on                   => l_debug_on
11443                         , p_order_by_rank              => l_order_by_rank
11444                         , p_needed_sec_quantity        => l_sec_needed_quantity
11445                         , p_secondary_uom              => p_secondary_uom
11446                         , p_grade_code                 => p_grade_code
11447                         , x_finished                   => l_finished
11448                         , x_remaining_quantity         => l_remaining_quantity
11449                         , x_remaining_sec_qty          => l_sec_remaining_quantity
11450                         , p_orig_needed_quantity       => l_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
11451                         , p_orig_needed_sec_qty        => l_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
11452                         , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
11453                         );
11454 
11455                         IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
11456                            IF l_debug = 1 THEN
11457                               log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
11458                            END IF;
11459                            RAISE fnd_api.g_exc_unexpected_error;
11460                         ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
11461                            IF l_debug = 1 THEN
11462                               log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
11463                            END IF;
11464                            RAISE fnd_api.g_exc_error;
11465                         END IF;
11466 
11467                         -- if allocated a consist group, exit pick uom loop
11468                         IF l_finished THEN
11469                            IF l_debug = 1 THEN
11470                               log_statement(l_api_name, 'consist_finished', 'Allocated all needed quantity with consist group');
11471                            END IF;
11472                            l_needed_quantity := 0;
11473                            l_sec_needed_quantity := 0;
11474 
11475                            -- Added for 14699845 (Flexible lot allocation)
11476                            l_orig_needed_quantity := 0;
11477                            l_orig_needed_sec_qty  := 0;
11478                            EXIT;
11479                         END IF;
11480                      --}
11481                      ELSE --{
11482                         -- else no consist restrictions
11483                         IF l_debug = 1 THEN
11484                            log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_Insert');
11485                         END IF;
11486                         -- call Validate and insert
11487                         validate_and_insert(
11488                           x_return_status              => x_return_status
11489                         , x_msg_count                  => x_msg_count
11490                         , x_msg_data                   => x_msg_data
11491                         , p_record_id                  => l_cur_uom_rec
11492                         , p_needed_quantity            => l_needed_quantity
11493                         , p_use_pick_uom               => FALSE
11494                         , p_organization_id            => p_organization_id
11495                         , p_inventory_item_id          => p_inventory_item_id
11496                         , p_to_subinventory_code       => l_to_subinventory_code
11497                         , p_to_locator_id              => l_to_locator_id
11498                         , p_to_cost_group_id           => l_to_cost_group_id
11499                         , p_primary_uom                => p_primary_uom
11500                         , p_transaction_uom            => p_transaction_uom
11501                         , p_transaction_temp_id        => p_transaction_temp_id
11502                         , p_type_code                  => p_type_code
11503                         , p_rule_id                    => l_rule_id
11504                         , p_reservation_id             => l_reservation_id
11505                         , p_tree_id                    => p_tree_id
11506                         , p_debug_on                   => l_debug_on
11507                         , p_needed_sec_quantity        => l_sec_needed_quantity
11508                         , p_secondary_uom              => p_secondary_uom
11509                         , p_grade_code                 => p_grade_code
11510                         , x_inserted_record            => l_inserted_record
11511                         , x_allocated_quantity         => l_allocated_quantity
11512                         , x_remaining_quantity         => l_remaining_quantity
11513                         , x_sec_allocated_quantity     => l_sec_allocated_quantity
11514                         , x_sec_remaining_quantity     => l_sec_remaining_quantity
11515                         , p_orig_needed_quantity       => l_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
11516                         , p_orig_needed_sec_qty        => l_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
11517                         , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
11518                         );
11519 
11520                         IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
11521                            IF l_debug = 1 THEN
11522                               log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
11523                            END IF;
11524                            RAISE fnd_api.g_exc_unexpected_error;
11525                         ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
11526                            IF l_debug = 1 THEN
11527                               log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
11528                            END IF;
11529                            RAISE fnd_api.g_exc_error;
11530                         END IF;
11531 
11532                         -- If returns true, decrease needed quantity
11533                         IF l_inserted_record THEN
11534                            l_needed_quantity := l_needed_quantity - l_allocated_quantity;
11535                            l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
11536 
11537                            -- Added for 14699845 (Flexible lot allocation)
11538                            l_orig_needed_quantity  := l_orig_needed_quantity - l_allocated_quantity;
11539                            l_orig_needed_sec_qty   := l_orig_needed_sec_qty  - l_sec_allocated_quantity;
11540 
11541                            IF l_debug = 1 THEN
11542                               log_statement(l_api_name, 'need_qty', 'New Needed quantity: ' || l_needed_quantity);
11543                               log_statement(l_api_name, 'sec need_qty', 'New Needed sec quantity: ' || l_sec_needed_quantity);
11544 
11545                               -- Added for 14699845 (Flexible lot allocation)
11546                               log_statement(l_api_name, 'need_qty', 'New orig Needed quantity: ' || l_orig_needed_quantity);
11547                               log_statement(l_api_name, 'need_qty', 'New orig Needed sec qty:  ' || l_orig_needed_sec_qty);
11548                            END IF;
11549                         END IF;
11550                      END IF; --} consist records
11551 
11552                      -- exit pick UOM loop when needed qty = 0
11553                      IF g_over_allocation = 'N'
11554                         OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
11555                         OR WMS_Engine_PVT.g_move_order_type <> 3
11556                      THEN
11557                         EXIT WHEN (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
11558                                       AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance))
11559                                   OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
11560                                       AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance))
11561                                   );
11562                      ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3
11563                      THEN
11564                         IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
11565                            IF l_max_sec_tolerance >= 0 THEN
11566                               EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
11567                                          OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11568                            ELSE
11569                               EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11570                            END IF;
11571                         ELSE
11572                            IF l_max_tolerance >= 0 THEN
11573                               EXIT WHEN (l_needed_quantity <= l_max_tolerance)
11574                                          OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11575                            ELSE
11576                               EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11577                            END IF;
11578                         END IF;
11579                      END IF;
11580                      -- end loop (pick UOM)
11581                      l_cur_uom_rec := g_locs(l_cur_uom_rec).next_rec;
11582                   END LOOP; --} pick UOM
11583 
11584                   -- if needed qty = 0, exit outer loop
11585                   IF g_over_allocation = 'N'
11586                      OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
11587                      OR WMS_Engine_PVT.g_move_order_type <> 3
11588                   THEN
11589                      EXIT WHEN (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
11590                                    AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance))
11591                                OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
11592                                    AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance))
11593                                );
11594                   ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3
11595                   THEN
11596                      IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
11597                         IF l_max_sec_tolerance >= 0 THEN
11598                            EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
11599                                       OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11600                         ELSE
11601                            EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11602                         END IF;
11603                      ELSE
11604                         IF l_max_tolerance >= 0 THEN
11605                            EXIT WHEN (l_needed_quantity <= l_max_tolerance)
11606                                       OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11607                         ELSE
11608                            EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11609                         END IF;
11610                      END IF;
11611                   END IF;
11612                END IF; --} allocation mode in 3,4
11613 
11614                -- if consist restrictions
11615                IF l_consist_exists THEN --{
11616                   IF l_debug = 1 THEN
11617                      log_statement(l_api_name, 'consist', 'Reading from consist groups');
11618                   END IF;
11619 
11620                   -- for each record in consist group
11621                   l_cur_consist_group  := g_first_consist_group;
11622 
11623                   IF l_debug = 1 THEN
11624                      log_statement(l_api_name, 'first_consist', 'First consist group:' || g_first_consist_group);
11625                   END IF;
11626 
11627                   LOOP --{
11628                      EXIT WHEN l_cur_consist_group = 0;
11629 
11630                      -- if group alloc qty > needed qty
11631                      IF ( (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
11632                            AND g_consists(l_cur_consist_group).quantity >= l_orig_needed_quantity)
11633                          OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
11634                              AND g_consists(l_cur_consist_group).secondary_quantity >= l_orig_needed_sec_qty)
11635                         )
11636                      THEN --{
11637                         IF l_debug = 1 THEN
11638                            log_statement(l_api_name, 'alloc_consist', 'Found a consist group to allocate');
11639                         END IF;
11640                         -- call allocate_consist_group
11641                         allocate_consist_group(
11642                           x_return_status              => x_return_status
11643                         , x_msg_count                  => x_msg_count
11644                         , x_msg_data                   => x_msg_data
11645                         , p_group_id                   => l_cur_consist_group
11646                         , p_needed_quantity            => l_needed_quantity
11647                         , p_use_pick_uom               => FALSE
11648                         , p_organization_id            => p_organization_id
11649                         , p_inventory_item_id          => p_inventory_item_id
11650                         , p_to_subinventory_code       => l_to_subinventory_code
11651                         , p_to_locator_id              => l_to_locator_id
11652                         , p_to_cost_group_id           => l_to_cost_group_id
11653                         , p_primary_uom                => p_primary_uom
11654                         , p_transaction_uom            => p_transaction_uom
11655                         , p_transaction_temp_id        => p_transaction_temp_id
11656                         , p_type_code                  => p_type_code
11657                         , p_rule_id                    => l_rule_id
11658                         , p_reservation_id             => l_reservation_id
11659                         , p_tree_id                    => p_tree_id
11660                         , p_debug_on                   => l_debug_on
11661                         , p_needed_sec_quantity        => l_sec_needed_quantity
11662                         , p_secondary_uom              => p_secondary_uom
11663                         , p_grade_code                 => p_grade_code
11664                         , p_lot_divisible_flag         => inv_cache.item_rec.lot_divisible_flag
11665                         , x_success                    => l_finished
11666                         , p_orig_needed_quantity       => l_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
11667                         , p_orig_needed_sec_qty        => l_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
11668                         , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
11669                         );
11670 
11671                         IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
11672                            IF l_debug = 1 THEN
11673                               log_statement(l_api_name, 'uerr_allocate_consist', 'Unexpected error in allocate_consist_group');
11674                            END IF;
11675                            RAISE fnd_api.g_exc_unexpected_error;
11676                         ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
11677                            IF l_debug = 1 THEN
11678                               log_statement(l_api_name, 'err_allocate_consist', 'Error in allocate_consist_group');
11679                            END IF;
11680                            RAISE fnd_api.g_exc_error;
11681                         END IF;
11682 
11683                         -- if finished = true
11684                         -- exit consist restrictions loop
11685                         IF l_finished THEN
11686                            IF l_debug = 1 THEN
11687                               log_statement(l_api_name, 'allocated_consist', 'Successfully allocated consistency group');
11688                            END IF;
11689                            l_needed_quantity  := 0;
11690                            l_sec_needed_quantity  := 0;
11691 
11692                            -- Added for 14699845 (Flexible lot allocation)
11693                            l_orig_needed_quantity := 0;
11694                            l_orig_needed_sec_qty  := 0;
11695                            EXIT;
11696                         END IF;
11697                      END IF; --}
11698 
11699                      -- end consist loop
11700                      l_cur_consist_group  := g_consists(l_cur_consist_group).next_group;
11701 
11702                      IF l_debug = 1 THEN
11703                         log_statement(l_api_name, 'next_consist', 'Next consist group: ' || l_cur_consist_group);
11704                      END IF;
11705                   END LOOP; --}
11706                   -- Exit outermost loop
11707                END IF; --} consist records
11708 
11709                IF l_debug = 1 THEN
11710                   log_statement(l_api_name, 'end_alloc', 'No more pick UOM or ' || 'consistecy records to Allocate.');
11711                END IF;
11712 
11713                EXIT;
11714             END IF; --} no more record
11715 
11716             IF l_debug = 1 THEN
11717                log_statement(l_api_name, 'order_string', 'Checking order string');
11718             END IF;
11719 
11720             -- if allocation mode = 3 and record has different order by string
11721             IF l_allocation_mode = 3
11722                AND l_first_uom_rec <> 0
11723                AND v_current_row.order_by_string <> l_cur_order_by_string
11724             THEN --{
11725                IF l_debug = 1 THEN
11726                   log_statement(l_api_name, 'change string', 'The order_by_string has changed.  Reading from pick UOM list');
11727                END IF;
11728 
11729                l_cur_uom_rec    := l_first_uom_rec;
11730 
11731                LOOP --{
11732                   EXIT WHEN l_cur_uom_rec = 0;
11733 
11734                   -- If consist restrictions
11735                   IF l_consist_exists THEN --{
11736                      IF l_debug = 1 THEN
11737                         log_statement(l_api_name, 'insert_consist', 'Calling insert consist record from pick UOM list');
11738                      END IF;
11739 
11740                      -- call insert consist record
11741                      insert_consist_record(
11742                        x_return_status              => x_return_status
11743                      , x_msg_count                  => x_msg_count
11744                      , x_msg_data                   => x_msg_data
11745                      , p_record_id                  => l_cur_uom_rec
11746                      , p_needed_quantity            => l_needed_quantity
11747                      , p_use_pick_uom               => FALSE
11748                      , p_organization_id            => p_organization_id
11749                      , p_inventory_item_id          => p_inventory_item_id
11750                      , p_to_subinventory_code       => l_to_subinventory_code
11751                      , p_to_locator_id              => l_to_locator_id
11752                      , p_to_cost_group_id           => l_to_cost_group_id
11753                      , p_primary_uom                => p_primary_uom
11754                      , p_transaction_uom            => p_transaction_uom
11755                      , p_transaction_temp_id        => p_transaction_temp_id
11756                      , p_type_code                  => p_type_code
11757                      , p_rule_id                    => l_rule_id
11758                      , p_reservation_id             => l_reservation_id
11759                      , p_tree_id                    => p_tree_id
11760                      , p_debug_on                   => l_debug_on
11761                      , p_order_by_rank              => l_order_by_rank
11762                      , p_needed_sec_quantity        => l_sec_needed_quantity
11763                      , p_secondary_uom              => p_secondary_uom
11764                      , p_grade_code                 => p_grade_code
11765                      , x_finished                   => l_finished
11766                      , x_remaining_quantity         => l_remaining_quantity
11767                      , x_remaining_sec_qty          => l_sec_remaining_quantity
11768                      , p_orig_needed_quantity       => l_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
11769                      , p_orig_needed_sec_qty        => l_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
11770                      , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
11771                      );
11772 
11773                      IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
11774                         IF l_debug = 1 THEN
11775                            log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
11776                         END IF;
11777                         RAISE fnd_api.g_exc_unexpected_error;
11778                      ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
11779                         IF l_debug = 1 THEN
11780                            log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
11781                         END IF;
11782                         RAISE fnd_api.g_exc_error;
11783                      END IF;
11784 
11785                      -- if allocated a consist group, exit pick uom loop
11786                      IF l_finished THEN
11787                         IF l_debug = 1 THEN
11788                            log_statement(l_api_name, 'finish_consist', 'Successfully allocated a consistency group');
11789                         END IF;
11790 
11791                         l_needed_quantity  := 0;
11792                         l_sec_needed_quantity  := 0;
11793 
11794                         -- Added for 14699845 (Flexible lot allocation)
11795                         l_orig_needed_quantity := 0;
11796                         l_orig_needed_sec_qty  := 0;
11797                         EXIT;
11798                      END IF;
11799                   --}
11800                   ELSE --{
11801                      -- else no consist restrictions
11802                      IF l_debug = 1 THEN
11803                         log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_insert for pick uom list');
11804                      END IF;
11805 
11806                      -- call Validate and insert
11807                      validate_and_insert(
11808                        x_return_status              => x_return_status
11809                      , x_msg_count                  => x_msg_count
11810                      , x_msg_data                   => x_msg_data
11811                      , p_record_id                  => l_cur_uom_rec
11812                      , p_needed_quantity            => l_needed_quantity
11813                      , p_use_pick_uom               => FALSE
11814                      , p_organization_id            => p_organization_id
11815                      , p_inventory_item_id          => p_inventory_item_id
11816                      , p_to_subinventory_code       => l_to_subinventory_code
11817                      , p_to_locator_id              => l_to_locator_id
11818                      , p_to_cost_group_id           => l_to_cost_group_id
11819                      , p_primary_uom                => p_primary_uom
11820                      , p_transaction_uom            => p_transaction_uom
11821                      , p_transaction_temp_id        => p_transaction_temp_id
11822                      , p_type_code                  => p_type_code
11823                      , p_rule_id                    => l_rule_id
11824                      , p_reservation_id             => l_reservation_id
11825                      , p_tree_id                    => p_tree_id
11826                      , p_debug_on                   => l_debug_on
11827                      , p_needed_sec_quantity        => l_sec_needed_quantity
11828                      , p_secondary_uom              => p_secondary_uom
11829                      , p_grade_code                 => p_grade_code
11830                      , x_inserted_record            => l_inserted_record
11831                      , x_allocated_quantity         => l_allocated_quantity
11832                      , x_remaining_quantity         => l_remaining_quantity
11833                      , x_sec_allocated_quantity     => l_sec_allocated_quantity
11834                      , x_sec_remaining_quantity     => l_sec_remaining_quantity
11835                      , p_orig_needed_quantity       => l_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
11836                      , p_orig_needed_sec_qty        => l_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
11837                      , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
11838                      );
11839 
11840                      IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
11841                         IF l_debug = 1 THEN
11842                            log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
11843                         END IF;
11844                         RAISE fnd_api.g_exc_unexpected_error;
11845                      ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
11846                         IF l_debug = 1 THEN
11847                            log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
11848                         END IF;
11849                         RAISE fnd_api.g_exc_error;
11850                      END IF;
11851 
11852                      -- If returns true, decrease needed quantity
11853                      IF l_inserted_record THEN
11854                         l_needed_quantity  := l_needed_quantity - l_allocated_quantity;
11855                         l_sec_needed_quantity  := l_sec_needed_quantity - l_sec_allocated_quantity;
11856 
11857                         -- Added for 14699845 (Flexible lot allocation)
11858                         l_orig_needed_quantity := l_orig_needed_quantity - l_allocated_quantity;
11859                         l_orig_needed_sec_qty  := l_orig_needed_sec_qty  - l_sec_allocated_quantity;
11860 
11861                         IF l_debug = 1 THEN
11862                            log_statement(l_api_name, 'success_validate', 'Successfully inserted record.  New needed quantity: '
11863                                                                           || l_needed_quantity);
11864                            log_statement(l_api_name, 'success_validate', 'Successfully inserted record.  New needed sec quantity: '
11865                                                                           || l_sec_needed_quantity);
11866                            -- Added for 14699845 (Flexible lot allocation)
11867                            log_statement(l_api_name, 'success_validate', 'Successfully inserted record.  New orig needed quantity: '
11868                                                                           || l_orig_needed_quantity);
11869                            log_statement(l_api_name, 'success_validate', 'Successfully inserted record.  New orig needed sec qty: '
11870                                                                           || l_orig_needed_sec_qty);
11871                         END IF;
11872                      END IF;
11873                   END IF; --} consist records
11874 
11875                   -- exit pick UOM loop when needed qty = 0
11876                   IF g_over_allocation = 'N'
11877                      OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
11878                      OR WMS_Engine_PVT.g_move_order_type <> 3
11879                   THEN
11880                      EXIT WHEN (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
11881                                    AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance))
11882                                OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
11883                                    AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance))
11884                                );
11885                   ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
11886                      IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
11887                         IF l_max_sec_tolerance >= 0 THEN
11888                            EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
11889                                       OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11890                         ELSE
11891                            EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11892                         END IF;
11893                      ELSE
11894                         IF l_max_tolerance >= 0 THEN
11895                            EXIT WHEN (l_needed_quantity <= l_max_tolerance)
11896                                       OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11897                         ELSE
11898                            EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11899                         END IF;
11900                      END IF;
11901                   END IF;
11902                   l_cur_uom_rec  := g_locs(l_cur_uom_rec).next_rec;
11903                   -- end loop (pick UOM)
11904                END LOOP; --} pick UOM
11905 
11906                IF l_debug = 1 THEN
11907                   log_statement(l_api_name, 'end_pick_uom', 'End Pick UOM loop');
11908                END IF;
11909 
11910                l_first_uom_rec  := 0;
11911                l_cur_uom_rec    := 0;
11912                l_last_uom_rec   := 0;
11913             END IF; --}
11914 
11915             IF g_over_allocation = 'N'
11916                OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
11917                OR WMS_Engine_PVT.g_move_order_type <> 3
11918             THEN
11919                EXIT WHEN (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
11920                              AND (l_needed_quantity <= 0 OR l_needed_quantity <= l_max_tolerance))
11921                          OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
11922                              AND (l_sec_needed_quantity <= 0 OR l_sec_needed_quantity <= l_max_sec_tolerance))
11923                          );
11924             ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
11925                IF NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' THEN
11926                   IF l_max_sec_tolerance >= 0 THEN
11927                      EXIT WHEN (l_sec_needed_quantity <= l_max_sec_tolerance)
11928                                 OR (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11929                   ELSE
11930                      EXIT WHEN (l_initial_sec_quantity - l_sec_needed_quantity >= WMS_RULE_PVT.g_min_sec_qty_to_alloc);
11931                   END IF;
11932                ELSE
11933                   IF l_max_tolerance >= 0 THEN
11934                      EXIT WHEN (l_needed_quantity <= l_max_tolerance)
11935                                 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11936                   ELSE
11937                      EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
11938                   END IF;
11939                END IF;
11940             END IF;
11941 
11942             IF NVL(l_cur_order_by_string, '@@@') <> NVL(v_current_row.order_by_string, '@@@') THEN
11943                IF l_debug = 1 THEN
11944                   log_statement(l_api_name, 'order_rank', 'Setting order rank');
11945                END IF;
11946 
11947                l_order_by_rank        := l_order_by_rank + 1;
11948                l_cur_order_by_string  := v_current_row.order_by_string;
11949 
11950                IF g_first_order_by_rank IS NULL THEN
11951                   log_statement(l_api_name, 'first_order', 'Setting first order rank');
11952                   g_first_order_by_rank  := l_order_by_rank;
11953                END IF;
11954             END IF;
11955 
11956             g_locs_index := g_locs_index + 1;
11957 
11958             IF l_debug = 1 THEN
11959                log_statement(l_api_name, 'loc_index', 'New loc index: ' || g_locs_index);
11960             END IF;
11961 
11962             g_locs(g_locs_index) := v_current_row;
11963 
11964             -- initialize trace records
11965             IF l_debug_on THEN
11966                IF l_debug = 1 THEN
11967                   log_statement(l_api_name, 'trace_init', 'Init Trace Record');
11968                END IF;
11969 
11970                g_trace_recs(g_locs_index).revision                 := v_current_row.revision;
11971                g_trace_recs(g_locs_index).lot_number               := v_current_row.lot_number;
11972                g_trace_recs(g_locs_index).lot_expiration_date      := v_current_row.lot_expiration_date;
11973                g_trace_recs(g_locs_index).subinventory_code        := v_current_row.subinventory_code;
11974                g_trace_recs(g_locs_index).locator_id               := v_current_row.locator_id;
11975                g_trace_recs(g_locs_index).cost_group_id            := v_current_row.cost_group_id;
11976                g_trace_recs(g_locs_index).lpn_id                   := v_current_row.lpn_id;
11977                g_trace_recs(g_locs_index).uom_code                 := v_current_row.uom_code;
11978                g_trace_recs(g_locs_index).quantity                 := v_current_row.quantity;
11979                g_trace_recs(g_locs_index).secondary_qty            := v_current_row.secondary_quantity;
11980                g_trace_recs(g_locs_index).grade_code               := v_current_row.grade_code;
11981                g_trace_recs(g_locs_index).serial_number            := v_current_row.serial_number;
11982                g_trace_recs(g_locs_index).consist_string_flag      := 'V';
11983                g_trace_recs(g_locs_index).partial_pick_flag        := 'Y';
11984                g_trace_recs(g_locs_index).order_string_flag        := 'Y';
11985                g_trace_recs(g_locs_index).pick_uom_flag            := 'V';
11986                g_trace_recs(g_locs_index).serial_number_used_flag  := 'V';
11987                g_trace_recs(g_locs_index).entire_lpn_flag          := 'V';
11988                -- write to log file
11989 
11990                IF l_debug = 1 THEN
11991                   log_statement(l_api_name, 'rev', 'revision: ' || v_current_row.revision);
11992                   log_statement(l_api_name, 'lot', 'lot: ' || v_current_row.lot_number);
11993                   log_statement(l_api_name, 'sub', 'sub:' || v_current_row.subinventory_code);
11994                   log_statement(l_api_name, 'loc', 'loc: ' || v_current_row.locator_id);
11995                   log_statement(l_api_name, 'cg', 'cg: ' || v_current_row.cost_group_id);
11996                   log_statement(l_api_name, 'lpn', 'lpn: ' || v_current_row.lpn_id);
11997                   log_statement(l_api_name, 'sn', 'sn: ' || v_current_row.serial_number);
11998                   log_statement(l_api_name, 'qty', 'quantity: ' || v_current_row.quantity);
11999                   log_statement(l_api_name, 'sqty', 'sec_quantity: ' || v_current_row.secondary_quantity);
12000                   log_statement(l_api_name, 'grade', 'grade_code: ' || v_current_row.grade_code);
12001                   log_statement(l_api_name, 'uom', 'uom_code: ' || v_current_row.uom_code);
12002                   log_statement(l_api_name, 'suom', 'sec_uom_code: ' || v_current_row.secondary_uom_code);
12003                   log_statement(l_api_name, 'ord', 'order:' || v_current_row.order_by_string);
12004                   log_statement(l_api_name, 'con', 'consist:' || v_current_row.consist_string);
12005                END IF;
12006             END IF;
12007 
12008             IF l_debug = 1 THEN
12009                log_statement(l_api_name, 'valid_sub', 'Validating sub');
12010             END IF;
12011 
12012             -- validate from/to sub/loc
12013             -- if fail, goto next output record
12014             -- first check to make sure picking from dest sub is not allowed;
12015             -- then, based on type code, compare src sub to dest sub;
12016             -- next, check to see if sub and item are locator controlled;
12017             -- if loc control, go to next record only if src loc = dest loc;
12018             -- if not loc control, go to next records (since subs are equal);
12019             -- all of the global variables are set in
12020             -- wms_engine_pvt.create_suggestions
12021             IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
12022                 AND v_current_row.subinventory_code = l_to_subinventory_code
12023                ) THEN
12024                IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
12025                    OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
12026                    OR (wms_engine_pvt.g_sub_loc_control = 5
12027                        AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
12028                       )
12029                   )
12030                THEN
12031                   IF (v_current_row.locator_id = l_to_locator_id) THEN
12032                      IF l_debug = 1 THEN
12033                         log_event(l_api_name, 'sub_loc_same', 'Cannot use this '
12034                                                || 'location since source subinventory and locator are'
12035                                                || ' same as destination subinventory and locator');
12036                      END IF;
12037 
12038                      IF l_debug_on THEN
12039                         g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'N';
12040                      END IF;
12041 
12042                      GOTO nextoutputrecord2;
12043                   END IF;
12044                ELSE
12045                   IF l_debug = 1 THEN
12046                      log_event(l_api_name, 'sub_same', 'Cannot use this '
12047                                             || 'location since source subinventory is '
12048                                             || 'same as destination subinventory');
12049                   END IF;
12050 
12051                   IF l_debug_on THEN
12052                      g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'N';
12053                   END IF;
12054 
12055                   GOTO nextoutputrecord2;
12056                END IF;
12057             END IF;
12058 
12059             IF l_debug_on THEN
12060                g_trace_recs(g_locs_index).same_subinv_loc_flag  := 'Y';
12061             END IF;
12062 
12063             -- If consistency restrictions
12064             IF l_consist_exists THEN --{
12065                IF l_debug = 1 THEN
12066                   log_statement(l_api_name, 'query_tree', 'Querying the quantity tree'
12067                                              || ' to find availability for consist record');
12068                END IF;
12069                -- BUG 3609380 :  Removing l_to_subinevntory_code.
12070                -- Validate available quantity
12071                inv_quantity_tree_pvt.query_tree(
12072                    p_api_version_number         => g_qty_tree_api_version
12073                  , p_init_msg_lst               => fnd_api.g_false -- p_init_msg_lst
12074                  , x_return_status              => x_return_status
12075                  , x_msg_count                  => x_msg_count
12076                  , x_msg_data                   => x_msg_data
12077                  , p_tree_id                    => p_tree_id
12078                  , p_revision                   => v_current_row.revision
12079                  , p_lot_number                 => v_current_row.lot_number
12080                  , p_subinventory_code          => v_current_row.subinventory_code
12081                  , p_locator_id                 => v_current_row.locator_id
12082                  , x_qoh                        => l_qoh
12083                  , x_sqoh                       => l_sqoh
12084                  , x_rqoh                       => l_rqoh
12085                  , x_srqoh                      => l_srqoh
12086                  , x_qr                         => l_qr
12087                  , x_sqr                        => l_sqr
12088                  , x_qs                         => l_qs
12089                  , x_sqs                        => l_sqs
12090                  , x_att                        => l_att
12091                  , x_satt                       => l_satt
12092                  , x_atr                        => l_atr
12093                  , x_satr                       => l_satr
12094                  , p_transfer_subinventory_code => chk_for_passing_xfer_sub(p_transaction_temp_id,l_to_subinventory_code) -- Bug# 4099907
12095                  , p_cost_group_id              => v_current_row.cost_group_id
12096                  , p_lpn_id                     => v_current_row.lpn_id
12097                  );
12098 
12099                IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12100                   IF l_debug = 1 THEN
12101                      log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
12102                   END IF;
12103                   RAISE fnd_api.g_exc_unexpected_error;
12104                ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12105                   IF l_debug = 1 THEN
12106                      log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
12107                   END IF;
12108                   RAISE fnd_api.g_exc_error;
12109                END IF;
12110 
12111                IF l_debug = 1 THEN
12112                   log_statement(l_api_name, 'att', 'ATT : ' || l_att ||'SATT is:'|| l_satt);      --9915228
12113                END IF;
12114 
12115                -- If att<=0, goto next output rec
12116                IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_att <= 0)
12117                    OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_satt <= 0)
12118                THEN
12119                   IF l_debug = 1 THEN
12120                      log_statement(l_api_name, 'no_att', 'No ATT for this record. ' || 'Getting next record');
12121                   END IF;
12122 
12123                   IF l_debug_on THEN
12124                      g_trace_recs(g_locs_index).att_qty           := l_att;
12125                      g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
12126                      g_trace_recs(g_locs_index).att_qty_flag      := 'N';
12127                   END IF;
12128 
12129                   GOTO nextoutputrecord2;
12130                END IF;
12131 
12132                IF l_debug_on THEN
12133                   g_trace_recs(g_locs_index).att_qty           := l_att;
12134                   g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
12135                   g_trace_recs(g_locs_index).att_qty_flag      := 'Y';
12136                END IF;
12137 
12138                IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_att < v_current_row.quantity)
12139                    OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_satt < v_current_row.secondary_quantity)
12140                THEN
12141                   IF l_debug = 1 THEN
12142                      log_statement(l_api_name, 'less_att', 'ATT is less than onhand ' || 'quantity. Reducing quantity');
12143                   END IF;
12144                   g_locs(g_locs_index).quantity := l_att;
12145                   g_locs(g_locs_index).secondary_quantity := l_satt; -- 9915228
12146                END IF;
12147 
12148                IF l_debug = 1 THEN
12149                   -- Insert_consist_record
12150                   log_statement(l_api_name, 'insert_consist', 'Calling Insert_Consist_Record');
12151                END IF;
12152 
12153                -- init consist flag to N.  It gets set to yes in Alloc. Consist. Group
12154                IF l_debug_on THEN
12155                   g_trace_recs(g_locs_index).consist_string_flag  := 'N';
12156                END IF;
12157 
12158                insert_consist_record(
12159                  x_return_status              => x_return_status
12160                , x_msg_count                  => x_msg_count
12161                , x_msg_data                   => x_msg_data
12162                , p_record_id                  => g_locs_index
12163                , p_needed_quantity            => l_needed_quantity
12164                , p_use_pick_uom               => l_use_pick_uom
12165                , p_organization_id            => p_organization_id
12166                , p_inventory_item_id          => p_inventory_item_id
12167                , p_to_subinventory_code       => l_to_subinventory_code
12168                , p_to_locator_id              => l_to_locator_id
12169                , p_to_cost_group_id           => l_to_cost_group_id
12170                , p_primary_uom                => p_primary_uom
12171                , p_transaction_uom            => p_transaction_uom
12172                , p_transaction_temp_id        => p_transaction_temp_id
12173                , p_type_code                  => p_type_code
12174                , p_rule_id                    => l_rule_id
12175                , p_reservation_id             => l_reservation_id
12176                , p_tree_id                    => p_tree_id
12177                , p_debug_on                   => l_debug_on
12178                , p_order_by_rank              => l_order_by_rank
12179                , p_needed_sec_quantity        => l_sec_needed_quantity
12180                , p_secondary_uom              => p_secondary_uom
12181                , p_grade_code                 => p_grade_code
12182                , x_finished                   => l_finished
12183                , x_remaining_quantity         => l_remaining_quantity
12184                , x_remaining_sec_qty          => l_sec_remaining_quantity
12185                , p_orig_needed_quantity       => l_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
12186                , p_orig_needed_sec_qty        => l_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
12187                , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
12188                );
12189 
12190                IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12191                   IF l_debug = 1 THEN
12192                      log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
12193                   END IF;
12194                   RAISE fnd_api.g_exc_unexpected_error;
12195                ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12196                   IF l_debug = 1 THEN
12197                      log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
12198                   END IF;
12199                   RAISE fnd_api.g_exc_error;
12200                END IF;
12201 
12202                -- if finished, needed qty = 0
12203                IF l_finished THEN
12204                   IF l_debug = 1 THEN
12205                      log_statement(l_api_name, 'finished', 'Successfully allocated ' || 'consistency group');
12206                   END IF;
12207                   l_needed_quantity := 0;
12208                   l_sec_needed_quantity := 0;
12209 
12210                   -- Added for 14699845 (Flexible lot allocation)
12211                   l_orig_needed_quantity := 0;
12212                   l_orig_needed_sec_qty  := 0;
12213                   EXIT;
12214                END IF;
12215             --}
12216             ELSE
12217                --{ else no consist
12218                IF l_debug = 1 THEN
12219                   log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_insert');
12220                END IF;
12221                -- call validate and insert
12222                validate_and_insert(
12223                  x_return_status              => x_return_status
12224                , x_msg_count                  => x_msg_count
12225                , x_msg_data                   => x_msg_data
12226                , p_record_id                  => g_locs_index
12227                , p_needed_quantity            => l_needed_quantity
12228                , p_use_pick_uom               => l_use_pick_uom
12229                , p_organization_id            => p_organization_id
12230                , p_inventory_item_id          => p_inventory_item_id
12231                , p_to_subinventory_code       => l_to_subinventory_code
12232                , p_to_locator_id              => l_to_locator_id
12233                , p_to_cost_group_id           => l_to_cost_group_id
12234                , p_primary_uom                => p_primary_uom
12235                , p_transaction_uom            => p_transaction_uom
12236                , p_transaction_temp_id        => p_transaction_temp_id
12237                , p_type_code                  => p_type_code
12238                , p_rule_id                    => l_rule_id
12239                , p_reservation_id             => l_reservation_id
12240                , p_tree_id                    => p_tree_id
12241                , p_debug_on                   => l_debug_on
12242                , p_needed_sec_quantity        => l_sec_needed_quantity
12243                , p_secondary_uom              => p_secondary_uom
12244                , p_grade_code                 => p_grade_code
12245                , x_inserted_record            => l_inserted_record
12246                , x_allocated_quantity         => l_allocated_quantity
12247                , x_remaining_quantity         => l_remaining_quantity
12248                , x_sec_allocated_quantity     => l_sec_allocated_quantity
12249                , x_sec_remaining_quantity     => l_sec_remaining_quantity
12250                , p_orig_needed_quantity       => l_orig_needed_quantity  -- Added for 14699845 (Flexible lot allocation)
12251                , p_orig_needed_sec_qty        => l_orig_needed_sec_qty   -- Added for 14699845 (Flexible lot allocation)
12252                , p_simulation_mode            => p_simulation_mode       -- Added for 14699845 (Flexible lot allocation)
12253                );
12254 
12255                IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12256                   IF l_debug = 1 THEN
12257                      log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
12258                   END IF;
12259                   RAISE fnd_api.g_exc_unexpected_error;
12260                ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12261                   IF l_debug = 1 THEN
12262                      log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
12263                   END IF;
12264                   RAISE fnd_api.g_exc_error;
12265                END IF;
12266 
12267                --if returns true, decrease needed qty
12268                IF l_inserted_record THEN
12269                   l_needed_quantity := l_needed_quantity - l_allocated_quantity;
12270                   l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
12271 
12272                   -- Added for 14699845 (Flexible lot allocation)
12273                   l_orig_needed_quantity := l_orig_needed_quantity - l_allocated_quantity;
12274                   l_orig_needed_sec_qty  := l_orig_needed_sec_qty  - l_sec_allocated_quantity;
12275 
12276                   IF l_debug = 1 THEN
12277                      log_statement(l_api_name, 'inserted_rec', 'Inserted record.  New needed quantity: '
12278                                                 || l_needed_quantity);
12279                      log_statement(l_api_name, 'inserted_rec', 'Inserted record.  New needed sec quantity: '
12280                                                 || l_sec_needed_quantity);
12281                      -- Added for 14699845 (Flexible lot allocation)
12282                      log_statement(l_api_name, 'inserted_rec', 'Inserted record.  New orig needed quantity: ' || l_orig_needed_quantity);
12283                      log_statement(l_api_name, 'inserted_rec', 'Inserted record.  New orig needed sec qty:  ' || l_orig_needed_sec_qty);
12284                   END IF;
12285                END IF;
12286             END IF; --} no consist restrictions
12287 
12288             -- Just comment here for R12.1 replenishment project, no code change here
12289             -- In case of allocation_mode= 5 we do not need to keep track of left out qty at locations because
12290             -- we will not be using them in the next round. We strictly pick based on the pick UOM code and we
12291             -- do not break. So we do not need to add anything in the following code.
12292 
12293 
12294             -- If remaining qty > 0 and allocation mode in 3,4
12295             IF l_allocation_mode IN (3, 4)
12296                AND (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_remaining_quantity > 0)
12297                    OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_remaining_quantity > 0)
12298                    )
12299             THEN --{
12300                IF l_debug = 1 THEN
12301                   log_statement(l_api_name, 'remain_qty', 'Remaining quantity: ' || l_remaining_quantity);
12302                   log_statement(l_api_name, 'remain_qty', 'Remaining sec quantity: ' || l_sec_remaining_quantity);
12303                   log_statement(l_api_name, 'remain_qty', 'Creating pick UOM rec');
12304                END IF;
12305                l_cur_rec := g_locs_index;
12306 
12307                IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
12308                       AND l_remaining_quantity < g_locs(g_locs_index).quantity)
12309                   OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
12310                       AND l_sec_remaining_quantity < g_locs(g_locs_index).secondary_quantity)
12311                   )
12312                THEN
12313                   -- create new location record for remaining quantity
12314                   g_locs_index                   := g_locs_index + 1;
12315                   g_locs(g_locs_index)           := g_locs(l_cur_rec);
12316                   g_locs(g_locs_index).quantity  := l_remaining_quantity;
12317                   g_locs(g_locs_index).secondary_quantity := l_sec_remaining_quantity;  -- 10636620
12318                   g_locs(l_cur_rec).quantity     := g_locs(l_cur_rec).quantity
12319                                                       - l_remaining_quantity;
12320                   g_locs(l_cur_rec).secondary_quantity := g_locs(l_cur_rec).secondary_quantity
12321                                                             - l_sec_remaining_quantity; -- 10636620
12322                   l_cur_uom_rec                  := g_locs_index;
12323                ELSE
12324                   l_cur_uom_rec  := l_cur_rec;
12325                END IF;
12326 
12327                -- new record is first record in table
12328                IF l_first_uom_rec = 0 THEN
12329                   l_first_uom_rec                 := l_cur_uom_rec;
12330                   l_last_uom_rec                  := l_cur_uom_rec;
12331                   g_locs(l_cur_uom_rec).next_rec  := 0;
12332                   IF l_debug = 1 THEN
12333                      log_statement(l_api_name, 'first_rec', 'The saved uom record is the first record in table');
12334                   END IF;
12335                   -- new record is first record with that uom code
12336                ELSIF g_locs(l_first_uom_rec).uom_code <> g_locs(l_cur_uom_rec).uom_code THEN
12337                   g_locs(l_cur_uom_rec).next_rec  := l_first_uom_rec;
12338                   l_first_uom_rec                 := l_cur_uom_rec;
12339                   l_last_uom_rec                  := l_cur_uom_rec;
12340                   IF l_debug = 1 THEN
12341                      log_statement(l_api_name, 'first_rec_uom', 'The saved uom record is the first record for uom in table');
12342                   END IF;
12343                   -- records with this uom code already exist in table
12344                ELSE
12345                   g_locs(l_cur_uom_rec).next_rec   := g_locs(l_last_uom_rec).next_rec;
12346                   g_locs(l_last_uom_rec).next_rec  := l_cur_uom_rec;
12347                   l_last_uom_rec                   := l_cur_uom_rec;
12348                   IF l_debug = 1 THEN
12349                      log_statement(l_api_name, 'not_first_rec_uom', 'The saved record is not first record for uom in table');
12350                   END IF;
12351                END IF;
12352 
12353                IF l_debug = 1 THEN
12354                   log_statement(l_api_name, 'saving_loc', 'Storing record in uom table');
12355                END IF;
12356 
12357                IF l_debug_on THEN
12358                   -- determine if we created a new record or not
12359                   IF l_cur_uom_rec = g_locs_index THEN
12360                      g_trace_recs(g_locs_index)                := g_trace_recs(l_cur_rec);
12361                      g_trace_recs(l_cur_rec).quantity          := g_trace_recs(l_cur_rec).quantity
12362                                                                     - l_remaining_quantity;
12363                      g_trace_recs(l_cur_rec).secondary_qty     := g_trace_recs(l_cur_rec).secondary_qty
12364                                                                     - l_sec_remaining_quantity;
12365                      g_trace_recs(g_locs_index).quantity       := l_remaining_quantity;
12366                      g_trace_recs(g_locs_index).secondary_qty  := l_sec_remaining_quantity;
12367                      g_trace_recs(g_locs_index).suggested_qty  := 0;
12368                      g_trace_recs(g_locs_index).secondary_suggested_qty := 0;
12369                      g_trace_recs(l_cur_rec).pick_uom_flag     := 'P';
12370                      g_trace_recs(g_locs_index).pick_uom_flag  := 'N';
12371                   ELSE
12372                      g_trace_recs(l_cur_rec).pick_uom_flag  := 'N';
12373                   END IF;
12374                END IF;
12375             --}
12376             ELSE
12377                IF l_debug_on THEN
12378                   g_trace_recs(g_locs_index).pick_uom_flag  := 'Y';
12379                END IF;
12380             END IF; -- allocation mode in 3,4
12381 
12382             -- if needed qty = 0 , exit outermost loop
12383             IF (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
12384                    AND (l_needed_quantity >= 0 AND l_needed_quantity <= l_max_tolerance))
12385                OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
12386                    AND (l_sec_needed_quantity >= 0 AND l_sec_needed_quantity <= l_max_sec_tolerance))
12387                )
12388             THEN
12389                IF l_debug = 1 THEN
12390                   log_statement(l_api_name, 'finished_alloc', 'The requested quantity has been allocated.  Exiting loop.');
12391                END IF;
12392                EXIT;
12393             END IF;
12394 
12395             <<nextoutputrecord2>>
12396             NULL;
12397             -- end outermost loop
12398          END LOOP; --}
12399       --}
12400       ELSIF (p_type_code = 1) THEN --{ put away
12401         l_capacity_updated  := FALSE;
12402         l_locs_index        := 0;
12403 
12404         --Loop through each record from the Rule cursor
12405         WHILE TRUE LOOP --{
12406           IF l_debug = 1 THEN
12407              log_event(l_api_name, 'Loop through each record  putaway from the Rule cursor ', 'Start ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
12408           END IF;
12409           --l_locs_index        := l_locs_index + 1; --bug3673962 moving this assignment as when no rows are returned by fetchputaway
12410                                                      --the index gets incremented unncessarily and fails in WMSSOGBB.pls
12411           fetchputaway(
12412             x_return_status
12413           , x_msg_count
12414           , x_msg_data
12415           , v_put_cursor
12416           , l_rule_id
12417           , l_osubinventory_code
12418           , l_olocator_id
12419           , l_oproject_id
12420           , l_otask_id
12421           , l_rows
12422           );
12423 
12424           IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12425             IF l_debug = 1 THEN
12426                log_statement(l_api_name, 'uerr_fetch_cursor',
12427                           'Unexpected error in FetchCursor');
12428             END IF;
12429             RAISE fnd_api.g_exc_unexpected_error;
12430           ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12431             IF l_debug = 1 THEN
12432                log_statement(l_api_name,'err_fetch_cursor','Error in FetchCursor');
12433             END IF;
12434             RAISE fnd_api.g_exc_error;
12435           END IF;
12436 
12437           -- Exit if no more records from rule cursor
12438           EXIT WHEN  nvl(l_rows, 0)  = 0 ;  -- [ Added to to exit , if the rule is not returning any rows
12439 
12440           l_locs_index        := l_locs_index + 1; --bug3673962
12441           log_statement(l_api_name, 'org_loc_ctl ', 'org: ' ||wms_engine_pvt.g_org_loc_control);
12442           log_statement(l_api_name, 'sub_loc_ctl ', 'org: ' ||wms_engine_pvt.g_sub_loc_control);
12443           log_statement(l_api_name, 'itm_loc_ctl ', 'org: ' ||wms_engine_pvt.g_item_loc_control);
12444           /* bug 3972784, remove locator_id if no locator control */
12445           IF (  wms_engine_pvt.g_org_loc_control in (1,4)                   -- no loc ctl org level
12446                AND ( wms_engine_pvt.g_sub_loc_control = 1                  -- no loc ctl sub level
12447                   OR (wms_engine_pvt.g_sub_loc_control = 5
12448                          AND wms_engine_pvt.g_item_loc_control = 1           -- no loc ctl item level
12449                      )
12450                    )
12451              )
12452           THEN
12453               l_olocator_id := null;
12454               log_statement(l_api_name, 'non locator controled',' Non locator controled');
12455           END IF;
12456 
12457           IF l_debug = 1 THEN
12458             log_statement(l_api_name, 'put_sub', 'Subinventory: ' || l_osubinventory_code);
12459              log_statement(l_api_name, 'put_loc', 'Locator: ' || l_olocator_id);
12460              log_statement(l_api_name, 'put_proj', 'Project: ' || l_oproject_id);
12461              log_statement(l_api_name, 'put_task', 'Task: ' || l_otask_id);
12462           END IF;
12463 
12464           IF l_debug_on THEN
12465             g_trace_recs(l_locs_index).revision             := l_revision;
12466             g_trace_recs(l_locs_index).lot_number           := l_lot_number;
12467             g_trace_recs(l_locs_index).lot_expiration_date  := l_lot_expiration_date;
12468             g_trace_recs(l_locs_index).subinventory_code    := l_osubinventory_code;
12469             g_trace_recs(l_locs_index).locator_id           := l_olocator_id;
12470             g_trace_recs(l_locs_index).cost_group_id        := l_to_cost_group_id;
12471             g_trace_recs(l_locs_index).uom_code             := NULL;
12472             g_trace_recs(l_locs_index).lpn_id               := l_input_lpn_id;
12473             g_trace_recs(l_locs_index).quantity             := NULL;
12474             g_trace_recs(l_locs_index).serial_number        := l_serial_number;
12475             --init to 0, in case of error
12476             g_trace_recs(l_locs_index).suggested_qty        := 0;
12477           END IF;
12478 
12479 
12480           --bug 2589499
12481           --if reservation exists for WIP assembly completion, put away
12482           --   to reservable sub only;
12483           --we know if sub has to be reservable based on global value set in
12484           --  create_suggestions
12485           IF wms_engine_pvt.g_reservable_putaway_sub_only THEN
12486              -- 8809951 removed curosr and using INV CACHE
12487          IF (inv_cache. set_tosub_rec(p_organization_id, l_osubinventory_code) )    THEN
12488                     l_lpn_controlled_flag  := inv_cache.tosub_rec.lpn_controlled_flag;
12489                     l_sub_rsv_type         := inv_cache.tosub_rec.reservable_type;
12490          END IF;
12491 
12492              If l_sub_rsv_type <> 1 Then
12493                IF l_debug = 1 THEN
12494                   log_statement(l_api_name, 'non_rsv_dest_sub',
12495                     'This material cannot be putaway in a non-reservable sub. ' ||
12496                     'Getting next record');
12497                END IF;
12498                --set trace flag
12499                GOTO NextOutputRecord;
12500              End If;
12501           END IF;
12502 
12503 
12504 
12505           --3/13/02 - To support PJM, check project and task if supplied.
12506           -- Case 1) Project and Task not supplied do nothing
12507           --      2) Project and Task Supplied and current record has same
12508           --     project and task continue processing.
12509           --      3) Project and Task supplied, not in current record
12510           --     then create a new entry in MTL_ITEM_LOCATIONS with
12511           --     properties of current record but with require project and task
12512           --  <This assumes that the results are ordered by Project and Task>
12513           IF p_project_id IS NOT NULL THEN
12514             IF NVL(l_oproject_id, -9999) <> p_project_id
12515                OR NVL(l_otask_id, -9999) <> nvl(p_task_id,-9999) THEN
12516               --bug 2400549 - for WIP backflush transfer putaway,
12517               --always use the locator specified on the move order line, even
12518               --if that locator is from common stock (not project)
12519               -- Bug 2666620: BackFlush MO Type Removed. It is now 5.
12520               -- Moreover Txn Action ID is 2  which is already handled.
12521              IF NOT (wms_engine_pvt.g_move_order_type = 5 AND
12522                  wms_engine_pvt.g_transaction_action_id = 2) THEN
12523                  IF l_debug = 1 THEN
12524                    log_statement(l_api_name, 'do_project2', 'Calling do project check');
12525                  END IF;
12526                 IF doprojectcheck(l_return_status,
12527                                   l_olocator_id,
12528                                   p_project_id,
12529                                   p_task_id,
12530                                   l_olocator_id_new,l_dummy_loc) THEN
12531                    IF l_debug = 1 THEN
12532                      log_statement(l_api_name, 'do_project_success', 'Do project check returned new locator');
12533                    END IF;
12534                    l_olocator_id_prev  := l_olocator_id;
12535                    l_olocator_id       := l_olocator_id_new;
12536                 ELSE
12537                   -- Current locator does not have required project/task
12538                               -- but it exists
12539                   IF l_debug = 1 THEN
12540                      log_statement(l_api_name, 'do_project_fail', 'Do project check failed. Getting next record.');
12541                   END IF;
12542                   GOTO nextoutputrecord;
12543                 END IF; --do project check
12544               END IF; -- not wip backflush
12545             END IF; -- allocated project <> needed project
12546           END IF; -- needed project <> -9999
12547 
12548                 --2/21/02 - Now check available capacity in here in the Pl/Sql
12549           --instead of calling the APIs from the rule sql.  This is to
12550           --improve performance.  If there are 10000 eligible locators, you
12551           --don't want to check capacity for all of them.  You only want to
12552           --check capacity on the one or two that you'll end up allocating
12553           IF l_debug = 1 THEN
12554              log_statement(l_api_name, 'qty_function', 'qty function code: ' || l_quantity_function);
12555           END IF;
12556        -- IF l_consider_staging_capacity THEN --Added bug3237702 -- commented for bug 6369468
12557           IF l_quantity_function = 530003 THEN
12558             l_possible_quantity  := wms_parameter_pvt.getavailableunitcapacity(
12559                                       p_organization_id            => p_organization_id
12560                                     , p_subinventory_code          => l_osubinventory_code
12561                                     , p_locator_id                 => l_olocator_id
12562                                     );
12563           ELSIF l_quantity_function = 530007 THEN
12564             l_possible_quantity  := wms_parameter_pvt.getavailablevolumecapacity(
12565                                       p_organization_id            => p_organization_id
12566                                     , p_subinventory_code          => l_osubinventory_code
12567                                     , p_locator_id                 => l_olocator_id
12568                                     , p_inventory_item_id          => p_inventory_item_id
12569                                     , p_unit_volume                => p_unit_volume
12570                                     , p_unit_volume_uom_code       => p_volume_uom_code
12571                                     , p_primary_uom                => p_primary_uom
12572                                     , p_transaction_uom            => p_transaction_uom
12573                                     , p_base_uom                   => p_base_uom_code
12574                                     );
12575           ELSIF l_quantity_function = 530011 THEN
12576             l_possible_quantity  := wms_parameter_pvt.getavailableweightcapacity(
12577                                       p_organization_id            => p_organization_id
12578                                     , p_subinventory_code          => l_osubinventory_code
12579                                     , p_locator_id                 => l_olocator_id
12580                                     , p_inventory_item_id          => p_inventory_item_id
12581                                     , p_unit_weight                => p_unit_weight
12582                                     , p_unit_weight_uom_code       => p_weight_uom_code
12583                                     , p_primary_uom                => p_primary_uom
12584                                     , p_transaction_uom            => p_transaction_uom
12585                                     , p_base_uom                   => p_base_uom_code
12586                                     );
12587           ELSIF l_quantity_function = 530015 THEN
12588             l_possible_quantity  := wms_parameter_pvt.getminimumavailablevwcapacity(
12589                                       p_organization_id            => p_organization_id
12590                                     , p_subinventory_code          => l_osubinventory_code
12591                                     , p_locator_id                 => l_olocator_id
12592                                     , p_inventory_item_id          => p_inventory_item_id
12593                                     , p_unit_volume                => p_unit_volume
12594                                     , p_unit_volume_uom_code       => p_volume_uom_code
12595                                     , p_unit_weight                => p_unit_weight
12596                                     , p_unit_weight_uom_code       => p_weight_uom_code
12597                                     , p_primary_uom                => p_primary_uom
12598                                     , p_transaction_uom            => p_transaction_uom
12599                                     , p_base_uom                   => p_base_uom_code
12600                                     );
12601           ELSIF l_quantity_function = 530019 THEN
12602             l_possible_quantity  := wms_parameter_pvt.getminimumavailableuvwcapacity(
12603                                       p_organization_id            => p_organization_id
12604                                     , p_subinventory_code          => l_osubinventory_code
12605                                     , p_locator_id                 => l_olocator_id
12606                                     , p_inventory_item_id          => p_inventory_item_id
12607                                     , p_unit_volume                => p_unit_volume
12608                                     , p_unit_volume_uom_code       => p_volume_uom_code
12609                                     , p_unit_weight                => p_unit_weight
12610                                     , p_unit_weight_uom_code       => p_weight_uom_code
12611                                     , p_primary_uom                => p_primary_uom
12612                                     , p_transaction_uom            => p_transaction_uom
12613                                     , p_base_uom                   => p_base_uom_code
12614                                     );
12615           ELSIF l_quantity_function = 530023 THEN
12616             l_possible_quantity  := wms_re_custom_pub.getavailablelocationcapacity(
12617                                       p_organization_id            => p_organization_id
12618                                     , p_subinventory_code          => l_osubinventory_code
12619                                     , p_locator_id                 => l_olocator_id
12620                                     , p_inventory_item_id          => p_inventory_item_id
12621                                     , p_transaction_quantity       => l_needed_quantity
12622                                     , p_transaction_uom            => p_transaction_uom
12623                                     );
12624           ELSE
12625             l_possible_quantity  := 0;
12626             IF l_debug = 1 THEN
12627                log_statement(l_api_name, 'bad_qtyf', 'Invalid Quantity Function');
12628             END IF;
12629           --raise error message!!!
12630           END IF;
12631       /* ELSE
12632           -- capacity should not be considered
12633           l_possible_quantity := 1e125;
12634           l_sec_possible_quantity := 1e125;
12635        END IF; */ -- commented for bug 6369468
12636 
12637        IF l_debug = 1 THEN
12638              log_statement(l_api_name, 'capacity', 'avail. capacity: ' || l_possible_quantity);
12639        END IF;
12640 
12641        --bug 2778814
12642        --For serial controlled items, we should not suggest the putaway
12643        --  of decimal quantities
12644        IF wms_engine_pvt.g_serial_number_control_code > 1 THEN
12645          l_possible_quantity := floor(l_possible_quantity);
12646          IF l_debug = 1 THEN
12647             log_statement(l_api_name, 'no_decimals',
12648                 'Cannot putaway a decimal quantity on a serial controlled item.'||
12649                 ' New available capacity: ' || l_possible_quantity);
12650          END IF;
12651        END IF;
12652 
12653           IF l_debug_on THEN
12654             g_trace_recs(l_locs_index).quantity  := l_possible_quantity;
12655           --g_trace_recs(l_locs_index).secondary_quantity  := l_sec_possible_quantity;
12656           END IF;
12657 
12658          -- [LOT_INDIV
12659      --  For lot indiv item, check if entire line qty can be dropped
12660      --  If not skip the current locator and go to next available locator
12661      --
12662      --  Default behavior is to split the qty and drop the partially
12663          --  and  go to the next locator for the remaining qty.
12664 
12665            IF l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1 AND p_type_code = 1 THEN
12666               IF l_possible_quantity < l_needed_quantity THEN
12667                  IF l_debug = 1 THEN
12668                     log_event(l_api_name, 'Required Capacity  = ', l_needed_quantity);
12669                     log_event(l_api_name, 'Available capacity =',  l_possible_quantity);
12670                     log_event(l_api_name, 'Capacity check for Lot indiv item', 'Capacity is not enough !');
12671                  END IF;
12672               GOTO nextoutputrecord;
12673               END IF;
12674            END IF;
12675           -- If no quantity for this record, get next record
12676           IF l_possible_quantity <= 0 OR l_possible_quantity IS NULL THEN
12677             IF l_debug = 1 THEN
12678                log_event(l_api_name, 'no_rec_qty_put', 'No available capacity in putaway location');
12679             END IF;
12680             --
12681             -- Patchset 'J' error_message
12682             WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_LOC_CAPACITY_FULL' ;
12683             --
12684             --
12685             GOTO nextoutputrecord;
12686           END IF;
12687 
12688           --check to see if from sub/loc = to sub/loc
12689           --this is okay if pick wave move order.
12690           --if not pick wave move order and src = dest,
12691           -- skip results
12692 
12693           --first check to make sure picking from dest sub is not allowed;
12694           --then, based on type code, compare src sub to dest sub;
12695           --next, check to see if sub and item are locator controlled;
12696           --if loc control, go to next record only if src loc = dest loc
12697           --if not loc control, go to next records (since subs are equal)
12698                 --all of the global variables are set in
12699           --wms_engine_pvt.create_suggestions
12700           IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
12701               AND l_osubinventory_code = l_from_subinventory_code
12702              ) THEN
12703             IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
12704                 OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
12705                 OR (wms_engine_pvt.g_sub_loc_control = 5
12706                     AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
12707                    )
12708                ) THEN
12709               IF (l_olocator_id = l_from_locator_id) THEN
12710 
12711                 IF l_debug = 1 THEN
12712                    log_event(
12713                      l_api_name
12714                    , 'same_sub_loc_put'
12715                    ,    'Destination '
12716                   || 'subinventory and locator for this record are the '
12717                   || 'same as the source subinventory and locator. '
12718                   || 'Using next record'
12719                   );
12720                 END IF;
12721 
12722                 IF l_debug_on THEN
12723                   g_trace_recs(l_locs_index).same_subinv_loc_flag  := 'N';
12724                 END IF;
12725 
12726                 --
12727                 -- Patchset 'J' error_message
12728                 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_SAME_SUB_LOC' ;
12729                 --
12730                 --
12731                 GOTO nextoutputrecord;
12732               END IF; -- from loc = to loc
12733             ELSE -- not loc controlled
12734               IF l_debug = 1 THEN
12735                  log_event(
12736                     l_api_name
12737                     , 'same_sub_put'
12738                     , 'Destination ' || 'subinventory for this record is the ' || 'same as the source subinventory. ' || 'Using next record'
12739                    );
12740                END IF;
12741 
12742               IF l_debug_on THEN
12743                 g_trace_recs(l_locs_index).same_subinv_loc_flag  := 'N';
12744               END IF;
12745 
12746               GOTO nextoutputrecord;
12747             END IF;
12748           END IF;
12749 
12750           IF l_debug_on THEN
12751             g_trace_recs(l_locs_index).same_subinv_loc_flag  := 'Y';
12752           END IF;
12753 
12754           --check status to see if putting away to this location is allowed
12755           -- for this transaction type
12756           -- This API checks the status for the subinventory, locator,
12757        -- Pass in NULL for lot number as this was checked during Pick (bug 12368533)
12758 
12759           IF l_debug = 1 THEN
12760              log_statement(l_api_name, 'checking_status', 'calling is_sub_loc_lot_trx_allowed to check status');
12761           END IF;
12762 
12763           --Bug Number :3457530(cheking for a transaction_type_id)
12764 
12765           IF ( p_transaction_type_id <> 64) THEN
12766           l_allowed           := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
12767                                    p_transaction_type_id        => p_transaction_type_id
12768                                  , p_organization_id            => p_organization_id
12769                                  , p_inventory_item_id          => p_inventory_item_id
12770                                  , p_subinventory_code          => l_osubinventory_code
12771                                  , p_locator_id                 => l_olocator_id
12772                                  , p_lot_number                 => NULL --l_lot_number bug 12368533
12773                                  );
12774           END IF;
12775 
12776           IF l_allowed <> 'Y' THEN
12777 
12778             IF l_debug = 1 THEN
12779                log_event(
12780                   l_api_name
12781                   , 'bad_status'
12782                   , 'This transaction type is not allowed by the status ' || 'for the subinventory, locator, or lot. Using ' || 'next record.'
12783                    );
12784              END IF;
12785 
12786             IF l_debug_on THEN
12787               g_trace_recs(l_locs_index).material_status_flag  := 'N';
12788             END IF;
12789         --
12790         -- Patchset 'J' error_message
12791         WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_MAT_STATUS_NOT_ALLOWED' ;
12792         --
12793         --
12794             GOTO nextoutputrecord;
12795           END IF;
12796 
12797           IF l_debug_on THEN
12798             g_trace_recs(l_locs_index).material_status_flag  := 'Y';
12799           END IF;
12800 
12801           /* Bug 4544717 -Converted l_possible_quantity to primary uom before comparing with
12802                          l_needed_quantity which is in primary uom if the transaction uom and
12803                          primary uom were different */
12804 
12805           IF l_debug = 1 THEN
12806                log_statement(l_api_name, 'poss_put_qty', 'Value of p_transaction_uom:'|| p_transaction_uom);
12807                log_statement(l_api_name, 'poss_put_qty', 'Value of p_primary_uom'|| p_primary_uom);
12808           END IF;
12809 
12810           IF p_transaction_uom <> p_primary_uom THEN
12811              IF l_debug = 1 THEN
12812                log_statement(l_api_name, 'poss_put_qty', 'In the condition for transaction_uom and primary uom different');
12813              END IF;
12814              l_possible_quantity := inv_convert.inv_um_convert(
12815                                         p_inventory_item_id
12816                                       , NULL
12817                                       , l_possible_quantity
12818                                       , p_transaction_uom
12819                                       , p_primary_uom
12820                                       , NULL
12821                                       , NULL
12822                                       );
12823           END IF;
12824 
12825           IF l_debug = 1 THEN
12826              log_statement(l_api_name, 'poss_put_qty', 'Value of l_possible_quantity' || l_possible_quantity);
12827              log_statement(l_api_name, 'poss_put_qty', 'Value of l_needed_quantity' || l_needed_quantity);
12828           END IF;
12829 
12830           /* End of fix for Bug 4544717 */
12831 
12832 
12833           -- correct possible quantity to what is really requested
12834           IF l_possible_quantity > l_needed_quantity THEN
12835             l_possible_quantity  := l_needed_quantity;
12836             l_sec_possible_quantity  := l_sec_needed_quantity;
12837             IF l_debug = 1 THEN
12838                log_statement(l_api_name, 'poss_put_qty', 'Possible quantity > needed quantity. New poss qty:' || l_possible_quantity);
12839             END IF;
12840           END IF;
12841 
12842 
12843           --
12844 
12845           --Determine if putaway sub is LPN controlled.  If it is not,
12846           --then we need to check cost group commingling always;
12847           -- Check cost group if
12848           -- Cost group is not null AND
12849           -- (sub is not lpn controlled OR
12850           --  No lpn on move order line OR
12851           --  not a staging transfer)
12852           --Never suggest comingling of cost groups, unless we are
12853           -- putting away a LPN.
12854           --When putting away an LPN, we assume that user is putting away
12855           -- whole LPN, which means there will never be comingling.
12856           --bug 1570597 - staging transfers are always put away in an LPN,
12857           -- so we don't need to check for comingling.
12858           --bug 2161565 - need to check for cg commingling if
12859           -- to subinventory is not LPN controlled.
12860           --bug 2492526 - putting away to a project controlled locator
12861           -- will always change the CG.  So no need to worry about CG
12862           -- commingling if the dest. loc is project controlled.
12863           IF l_to_cost_group_id IS NULL THEN
12864             l_check_cg  := FALSE;
12865           ELSIF l_oproject_id IS NOT NULL THEN
12866             l_check_cg  := FALSE;
12867           ELSIF (p_lpn_id IS NOT NULL
12868                  OR p_transaction_type_id IN (52, 53, 64)-- Added Move order transfer transaction - 64  for bug 14784282(FP of 11i bug 14757458) since MO xfer will always happen in a LPN
12869                 ) THEN                                   --For "Move Any LPN" which shares the same trx type = 64, the condition "p_lpn_id IS NOT NULL" will always be TRUE
12870                                                          --and so this change will not effect the "Move Any LPN" flow
12871 
12872 
12873 			    -- Start Added for Bug 14784282(FP of 11i bug 14757458)
12874 				IF l_debug = 1 THEN
12875                   log_statement(l_api_name, 'CG Check', 'In the condition for p_lpn_id not Null or Transaction type in 52,53,64');
12876                 END IF;
12877 				 -- End Added for Bug 14784282(FP of 11i bug 14757458)
12878 
12879             --only execute query if we did not already find lpn_controlled_flag
12880             -- when determining if sub is reservable
12881             If l_lpn_controlled_flag IS NULL Then
12882               --8809951 Removed cursor and using INV CACHE
12883           IF (inv_cache. set_tosub_rec(p_organization_id, l_osubinventory_code) )    THEN
12884                      l_lpn_controlled_flag  := inv_cache.tosub_rec.lpn_controlled_flag;
12885                      l_sub_rsv_type         := inv_cache.tosub_rec.reservable_type;
12886           END IF;
12887             End If;
12888 
12889 			-- Start Added for Bug 14784282(FP of 11i bug 14757458)
12890 				IF l_debug = 1 THEN
12891                   log_statement(l_api_name, 'CG Check', 'l_lpn_controlled_flag --> 1 -  LPN controlled SI::'||l_lpn_controlled_flag); --added for bug 14757458
12892                 END IF;
12893 			-- End Added for Bug 14784282(FP of 11i bug 14757458)
12894 
12895             IF l_lpn_controlled_flag = 1 THEN
12896               l_check_cg  := FALSE;
12897             ELSE
12898               l_check_cg  := TRUE;
12899             END IF;
12900           ELSE
12901             l_check_cg  := TRUE;
12902           END IF;
12903 
12904           --Check to see if putaway would comingle cost groups.
12905           IF l_check_cg THEN
12906 
12907 		    -- Start Added for Bug 14784282(FP of 11i bug 14757458)
12908 				IF l_debug = 1 THEN
12909                   log_statement(l_api_name, 'CG Check', 'Calling inv_comingling_utils.comingle_check'); --added for bug 14757458
12910                 END IF;
12911 			-- End Added for Bug 14784282(FP of 11i bug 14757458)
12912 
12913             inv_comingling_utils.comingle_check(
12914               x_return_status              => x_return_status
12915             , x_msg_count                  => x_msg_count
12916             , x_msg_data                   => x_msg_data
12917             , x_comingling_occurs          => l_comingle
12918             , x_count                      => l_dummy
12919             , p_organization_id            => p_organization_id
12920             , p_inventory_item_id          => p_inventory_item_id
12921             , p_revision                   => l_revision
12922             , p_lot_number                 => l_lot_number
12923             , p_subinventory_code          => l_osubinventory_code
12924             , p_locator_id                 => l_olocator_id
12925             , p_lpn_id                     => NULL
12926             , p_cost_group_id              => l_to_cost_group_id
12927             );
12928 
12929             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12930               IF l_debug = 1 THEN
12931                  log_statement(l_api_name, 'uerr_comingle_check', 'Unexpected error in comingle_check');
12932               END IF;
12933               RAISE fnd_api.g_exc_unexpected_error;
12934             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12935               IF l_debug = 1 THEN
12936                  log_statement(l_api_name, 'err_comingle_check', 'Error in comingle_check');
12937               END IF;
12938               RAISE fnd_api.g_exc_error;
12939             END IF;
12940 
12941             -- Skip record if it would cause comingling
12942             IF l_comingle = 'Y' THEN
12943               IF l_debug = 1 THEN
12944                  log_event(l_api_name, 'comingle_putaway', 'Putaway to this location would comingle cost groups. ' || 'Using next record');
12945               END IF;
12946               IF l_debug_on THEN
12947                 g_trace_recs(l_locs_index).cg_comingle_flag  := 'N';
12948               END IF;
12949                --
12950            -- Patchset 'J' error_message
12951            WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_COST_GROUP_COMINGLE' ;
12952               GOTO nextoutputrecord;
12953             END IF;
12954 
12955             IF l_debug_on THEN
12956               g_trace_recs(l_locs_index).cg_comingle_flag  := 'Y';
12957             END IF;
12958           END IF;
12959 
12960           -- Update locator capacity to reflect quantity we are putting
12961           -- away.  This API executes an autonomous commit.  Thus,
12962           -- if any sort of error occurs, we have to explicitly undo
12963           -- this update (we can't just do a rollback).
12964         --  IF (l_olocator_id IS NOT NULL) AND l_consider_staging_capacity THEN  --Added bug3237702 -- commented for bug 6369468
12965           IF l_olocator_id IS NOT NULL THEN
12966             IF l_debug = 1 THEN
12967                log_statement(l_api_name, 'update_capacity', 'Updating suggested capacity');
12968              END IF;
12969             inv_loc_wms_utils.update_loc_suggested_capacity(
12970               x_return_status              => x_return_status
12971             , x_msg_count                  => x_msg_count
12972             , x_msg_data                   => x_msg_data
12973             , p_organization_id            => p_organization_id
12974             , p_inventory_location_id      => l_olocator_id
12975             , p_inventory_item_id          => p_inventory_item_id
12976             , p_primary_uom_flag           => 'Y'
12977             , p_transaction_uom_code       => NULL
12978             , p_quantity                   => l_possible_quantity
12979             );
12980 
12981             IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12982               IF l_debug = 1 THEN
12983                  log_statement(l_api_name, 'uerr_update_capacity', 'Unexpected error in update_loc_suggested_capacity');
12984               END IF;
12985               RAISE fnd_api.g_exc_unexpected_error;
12986             ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12987               IF l_debug = 1 THEN
12988                  log_statement(l_api_name, 'err_update_capacity', 'Error in update_loc_suggested_capacity');
12989               END IF;
12990               RAISE fnd_api.g_exc_error;
12991             ELSE
12992               l_capacity_updated  := TRUE;
12993             END IF;
12994           END IF;
12995 
12996           IF l_debug_on THEN
12997             g_trace_recs(l_locs_index).suggested_qty  := l_possible_quantity;
12998             g_trace_recs(l_locs_index).secondary_suggested_qty  := l_sec_possible_quantity;
12999           END IF;
13000 
13001           -- no detail for serial numbers
13002           -- get the transaction quantity
13003           IF p_transaction_uom = p_primary_uom THEN
13004             l_possible_trx_qty  := l_possible_quantity;
13005           ELSE
13006             l_possible_trx_qty  :=
13007                    inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_possible_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
13008           END IF;
13009 
13010           IF l_debug = 1 THEN
13011             log_statement(l_api_name, 'insert_put_wtt_recs', 'Before insert values of l_possible_trx_qty'|| l_possible_trx_qty);
13012             log_statement(l_api_name, 'insert_put_wtt_recs', 'Before insert values of l_possible_quantity'|| l_possible_quantity);
13013           END IF;
13014 
13015           IF l_debug = 1 THEN
13016              log_statement(l_api_name, 'insert_put_wtt_recs', 'Inserting putaway records in wtt');
13017           END IF;
13018           -- insert temporary suggestion
13019           INSERT INTO wms_transactions_temp
13020                       (
13021                       pp_transaction_temp_id
13022                     , transaction_temp_id
13023                     , type_code
13024                     , line_type_code
13025                     , transaction_quantity
13026                     , primary_quantity
13027                     , secondary_quantity
13028                     , grade_code
13029                     , revision
13030                     , lot_number
13031                     , lot_expiration_date
13032                     , from_subinventory_code
13033                     , from_locator_id
13034                     , rule_id
13035                     , reservation_id
13036                     , to_subinventory_code
13037                     , to_locator_id
13038                     , from_cost_group_id
13039                     , to_cost_group_id
13040                     , lpn_id
13041                       )
13042                VALUES (
13043                       wms_transactions_temp_s.NEXTVAL
13044                     , p_transaction_temp_id
13045                     , p_type_code
13046                     , 2 -- line type code is output
13047                     , l_possible_trx_qty
13048                     , l_possible_quantity
13049                     , l_sec_possible_quantity
13050                     , l_grade_code
13051                     , l_revision
13052                     , l_lot_number
13053                     , l_lot_expiration_date
13054                     , l_from_subinventory_code
13055                     , l_from_locator_id
13056                     , l_rule_id
13057                     , l_reservation_id
13058                     , l_osubinventory_code
13059                     , l_olocator_id
13060                     , l_from_cost_group_id
13061                     , l_to_cost_group_id
13062                     , l_input_lpn_id
13063                       );
13064 
13065           --
13066           l_capacity_updated  := FALSE;
13067           --END IF;
13068 
13069           IF l_debug = 1 THEN
13070              log_event(l_api_name, 'putaway_loc_found', 'Found put away location for quantity ' || l_possible_quantity);
13071           END IF;
13072 
13073           -- keep track of the remaining transaction quantity
13074           IF l_needed_quantity > l_possible_quantity THEN
13075             l_needed_quantity  := l_needed_quantity - l_possible_quantity;
13076             l_sec_needed_quantity  := l_sec_needed_quantity - l_sec_possible_quantity;
13077           ELSE
13078             l_needed_quantity  := 0;
13079             l_sec_needed_quantity  := 0;
13080             IF l_debug = 1 THEN
13081                log_event(l_api_name, 'finished_putaway', 'Found put away locations for all quantity in this input record');
13082             END IF;
13083           END IF;
13084 
13085           --
13086           <<nextoutputrecord>>
13087           EXIT WHEN l_needed_quantity = 0;
13088         END LOOP; --} output records
13089       END IF; --} type_code = 1
13090 
13091       -- finally close the rule cursor
13092       IF l_debug = 1 THEN
13093          log_statement(l_api_name, 'close_curs', 'Calling close_curs');
13094       END IF;
13095 
13096       -- Bug# 4738161: Close the putaway cursors after each line is allocated if necessary
13097       IF p_type_code = 1 THEN
13098          close_put_rule(l_rule_id, v_put_cursor);
13099       ELSE
13100          close_pick_rule(l_rule_id, v_pick_cursor);
13101       END IF;
13102 
13103       IF l_debug = 1 THEN
13104          log_statement(l_api_name, 'finish_close_curs', 'Finished close_curs');
13105       END IF;
13106 
13107       IF (   (g_over_allocation = 'N'
13108               OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
13109               OR WMS_Engine_PVT.g_move_order_type <> 3 OR p_type_code <> 2)
13110          AND (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
13111                      AND (l_needed_quantity > 0 OR l_needed_quantity > l_max_tolerance))
13112              OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
13113                      AND (l_sec_needed_quantity > 0 OR l_sec_needed_quantity > l_max_sec_tolerance))
13114              )
13115          )
13116        OR
13117          (g_over_allocation = 'Y'
13118           AND NOT (p_type_code = 2 AND l_lot_divisible_flag = 'N' AND l_lot_control_code <> 1)
13119           AND WMS_Engine_PVT.g_move_order_type = 3 AND p_type_code = 2
13120           AND (  (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P'
13121                   AND (  (l_max_tolerance >= 0 AND (l_needed_quantity > l_max_tolerance)
13122                           AND (l_initial_pri_quantity - l_needed_quantity < WMS_RULE_PVT.g_min_qty_to_allocate))
13123                       OR (l_max_tolerance < 0
13124                           AND (l_initial_pri_quantity - l_needed_quantity < WMS_RULE_PVT.g_min_qty_to_allocate))
13125                       )
13126                  )
13127               OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S'
13128                   AND (  (l_max_sec_tolerance >= 0 AND (l_sec_needed_quantity > l_max_sec_tolerance)
13129                           AND (l_initial_sec_quantity - l_sec_needed_quantity < WMS_RULE_PVT.g_min_sec_qty_to_alloc))
13130                       OR (l_max_sec_tolerance < 0
13131                           AND (l_initial_sec_quantity - l_sec_needed_quantity < WMS_RULE_PVT.g_min_sec_qty_to_alloc))
13132                       )
13133                  )
13134               )
13135          )
13136       THEN --{
13137          -- notice, that at least one input record couldn't get satisfied
13138          x_finished := fnd_api.g_false;
13139 
13140          IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_needed_quantity = l_initial_pri_quantity)
13141              OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_needed_quantity = l_initial_sec_quantity)
13142          THEN
13143             -- Bug #3396532
13144             IF WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE IS NULL THEN
13145                WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
13146             END IF;
13147             IF l_debug = 1 THEN
13148                log_event(l_api_name, 'no_success', 'Found no locations for this rule');
13149             END IF;
13150          ELSE
13151             IF l_debug = 1 THEN
13152                log_event(l_api_name, 'partial_success', 'Successfully allocated some of the transaction '
13153                                       || 'quantity with this rule.');
13154             END IF;
13155          END IF;
13156 
13157          -- if partials are not allowed, exit after rolling back everything
13158          IF p_partial_success_allowed_flag = 'N' THEN --{
13159             -- restore qty tree
13160             IF l_debug = 1 THEN
13161                log_event(l_api_name, 'no_partials_allowed',
13162                                      'Partial success is not allowed for this rule - rolling back');
13163             END IF;
13164             IF p_type_code = 2 THEN --{
13165                IF l_debug = 1 THEN
13166                   log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
13167                END IF;
13168                inv_quantity_tree_pvt.restore_tree(x_return_status, p_tree_id);
13169 
13170                /*Start of fix for Bug 5251221 */
13171 
13172                OPEN l_get_serial;
13173                LOOP --{
13174                   FETCH l_get_serial INTO l_serial_number;
13175                   IF l_get_serial%NOTFOUND THEN
13176                      IF l_debug = 1 THEN
13177                         inv_log_util.trace('Serial not found', 'delete_serial_numbers', 9);
13178                      END IF;
13179                      EXIT;
13180                   ELSE --{
13181                      IF (inv_detail_util_pvt.g_serial_tbl_ptr > 0) THEN --{
13182                         IF l_debug = 1 THEN
13183                            inv_log_util.trace('Org: ' || p_organization_id, 'delete_serial_numbers', 9);
13184                            inv_log_util.trace('Item: ' || p_inventory_item_id, 'delete_serial_numbers', 9);
13185                            inv_log_util.trace('Serial: ' || l_serial_number, 'delete_serial_numbers', 9);
13186                            inv_log_util.trace('inv_detail_util_pvt.g_serial_tbl_ptr '
13187                                                || inv_detail_util_pvt.g_serial_tbl_ptr, 'delete_serial_numbers', 9);
13188                         END IF;
13189 
13190                         FOR i IN 1..inv_detail_util_pvt.g_serial_tbl_ptr LOOP --{
13191                             IF (inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id = p_inventory_item_id)
13192                                AND (inv_detail_util_pvt.g_output_serial_rows(i).organization_id = p_organization_id)
13193                                AND (inv_detail_util_pvt.g_output_serial_rows(i).serial_number = l_serial_number)
13194                             THEN --{
13195                                IF (inv_detail_util_pvt.g_serial_tbl_ptr > 1) THEN
13196                                   inv_detail_util_pvt.g_output_serial_rows(i).organization_id :=
13197                                       inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).organization_id;
13198                                   inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id :=
13199                                       inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).inventory_item_id;
13200                                   inv_detail_util_pvt.g_output_serial_rows(i).serial_number :=
13201                                       inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).serial_number;
13202 
13203                                   inv_detail_util_pvt.g_output_serial_rows.DELETE(inv_detail_util_pvt.g_serial_tbl_ptr);
13204                                   inv_detail_util_pvt.g_serial_tbl_ptr := inv_detail_util_pvt.g_serial_tbl_ptr-1;
13205 
13206                                   IF l_debug = 1 THEN
13207                                      inv_log_util.trace('inv_detail_util_pvt.g_serial_tbl_ptr '
13208                                                          || inv_detail_util_pvt.g_serial_tbl_ptr, 'delete_serial_numbers', 9);
13209                                   END IF;
13210 
13211                                ELSE
13212                                   inv_detail_util_pvt.g_output_serial_rows.DELETE;
13213                                   inv_detail_util_pvt.g_serial_tbl_ptr := inv_detail_util_pvt.g_serial_tbl_ptr-1;
13214 
13215                                   IF l_debug = 1 THEN
13216                                      inv_log_util.trace('Array cleared', 'delete_serial_numbers', 9);
13217                                   END IF;
13218 
13219                                END IF; -- End of IF (inv_detail_util_pvt.g_serial_tbl_ptr > 1)
13220 
13221                                EXIT; -- if a serial has been deleted, needn't check other serials present in g_output_serial_rows
13222                             END IF; --} End of  IF (inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id = p_inventory_item_id)
13223                         END LOOP; --} End of FOR loop
13224                      END IF; --} End of IF (inv_detail_util_pvt.g_serial_tbl_ptr > 0)
13225                   END IF; --} End of IF l_get_serial%NOTFOUND
13226                END LOOP; --} End of LOOP for CURSOR
13227 
13228                CLOSE l_get_serial;
13229                /*End of fix for Bug 5251221 */
13230 
13231                --
13232                IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13233                   IF l_debug = 1 THEN
13234                      log_statement(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
13235                   END IF;
13236                   RAISE fnd_api.g_exc_unexpected_error;
13237                ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13238                   IF l_debug = 1 THEN
13239                      log_statement(l_api_name, 'err_restore_tree', 'Error in restore_tree');
13240                   END IF;
13241                   RAISE fnd_api.g_exc_error;
13242                END IF;
13243             --}
13244             ELSE --{ for put away, restore capacity
13245                -- this function reduces the suggested units in the location
13246                -- for each record inserted in wms_transaction_temp as a
13247                -- putaway output record
13248                rollback_capacity_update(
13249                  x_return_status              => x_return_status
13250                , x_msg_count                  => x_msg_count
13251                , x_msg_data                   => x_msg_data
13252                , p_organization_id            => p_organization_id
13253                , p_inventory_item_id          => p_inventory_item_id
13254                );
13255 
13256                IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13257                   IF l_debug = 1 THEN
13258                      log_statement(l_api_name, 'uerr_rollback_cap', 'Unexpected error in rollback_capacity_update');
13259                   END IF;
13260                   RAISE fnd_api.g_exc_unexpected_error;
13261                ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13262                   IF l_debug = 1 THEN
13263                      log_statement(l_api_name, 'err_rollback_cap', 'Error in rollback_capacity_update');
13264                   END IF;
13265                   RAISE fnd_api.g_exc_error;
13266                END IF;
13267 
13268                -- if error occurred after capacity got updated but before
13269                -- insertion into WTT, fix the capacity for that record
13270                IF l_capacity_updated THEN
13271                   IF l_debug = 1 THEN
13272                      log_statement(l_api_name, 'revert_capacity', 'Calling revert_loc_suggested_capacity');
13273                   END IF;
13274                   inv_loc_wms_utils.revert_loc_suggested_capacity(
13275                     x_return_status              => x_return_status
13276                   , x_msg_count                  => x_msg_count
13277                   , x_msg_data                   => x_msg_data
13278                   , p_organization_id            => p_organization_id
13279                   , p_inventory_location_id      => l_olocator_id
13280                   , p_inventory_item_id          => p_inventory_item_id
13281                   , p_primary_uom_flag           => 'Y'
13282                   , p_transaction_uom_code       => NULL
13283                   , p_quantity                   => l_possible_quantity
13284                   );
13285 
13286                   IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13287                      IF l_debug = 1 THEN
13288                         log_statement(l_api_name, 'uerr_revert_capacity', 'Unexpected error in revert_loc_suggested_capacity');
13289                      END IF;
13290                      RAISE fnd_api.g_exc_unexpected_error;
13291                   ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13292                      IF l_debug = 1 THEN
13293                         log_statement(l_api_name, 'err_revert_capacity', 'Error in revert_loc_suggested_capacity');
13294                      END IF;
13295                      RAISE fnd_api.g_exc_error;
13296                   END IF;
13297 
13298                   l_capacity_updated  := FALSE;
13299                END IF;
13300             END IF; --}
13301 
13302             -- needs to set the trace flag for partial pick to N.
13303             IF l_debug_on THEN
13304                -- first record in g_trace_recs always at index 1
13305                l_cur_rec  := 1;
13306                LOOP
13307                   EXIT WHEN NOT g_trace_recs.EXISTS(l_cur_rec);
13308 
13309                   IF g_trace_recs(l_cur_rec).suggested_qty > 0 THEN
13310                      g_trace_recs(l_cur_rec).suggested_qty      := 0;
13311                      g_trace_recs(l_cur_rec).partial_pick_flag  := 'N';
13312                   END IF;
13313 
13314                   l_cur_rec  := l_cur_rec + 1;
13315                END LOOP;
13316 
13317                wms_search_order_globals_pvt.insert_trace_lines(
13318                  p_api_version                => 1.0
13319                , p_init_msg_list              => fnd_api.g_false
13320                , p_validation_level           => fnd_api.g_valid_level_full
13321                , x_return_status              => l_return_status
13322                , x_msg_count                  => x_msg_count
13323                , x_msg_data                   => x_msg_data
13324                , p_header_id                  => wms_engine_pvt.g_trace_header_id
13325                , p_rule_id                    => l_rule_id
13326                , p_pre_suggestions            => g_trace_recs
13327                );
13328             END IF;
13329 
13330             --
13331             ROLLBACK TO applyrulesp;
13332             EXIT;
13333          --}
13334          ELSE
13335             IF (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'P' AND l_needed_quantity <> l_initial_pri_quantity)
13336                 OR (NVL(wms_engine_pvt.g_fulfillment_base,'P') = 'S' AND l_sec_needed_quantity <> l_initial_sec_quantity)
13337             THEN
13338                IF l_debug = 1 THEN
13339                   log_statement(l_api_name, 'updating_input_rec', 'Updating the input line in WTT and pl/sql table');
13340                END IF;
13341 
13342                l_needed_quantity := l_needed_quantity - l_max_tolerance;
13343                l_sec_needed_quantity := l_sec_needed_quantity - l_max_sec_tolerance;
13344                UPDATE wms_transactions_temp
13345                   SET primary_quantity = l_needed_quantity
13346                     , secondary_quantity = l_sec_needed_quantity
13347                 WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
13348 
13349                wms_re_common_pvt.updateinputline(l_needed_quantity,l_sec_needed_quantity);
13350             END IF;
13351          END IF;
13352       --}
13353       ELSE --{
13354          x_finished := fnd_api.g_true;
13355          -- if input line could get satisfied
13356          -- delete the input line in the wms_transactions_temp table
13357          IF l_debug = 1 THEN
13358             log_statement(l_api_name, 'deleting_input_rec',
13359                                       'Deleting the input line in WTT and pl/sql table');
13360          END IF;
13361 
13362          DELETE FROM wms_transactions_temp
13363           WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
13364 
13365          --
13366          -- and delete input record in PL/SQL table, too
13367          wms_re_common_pvt.deleteinputline;
13368 
13369          -- Bug 13496654 ---
13370          IF l_debug = 1 THEN
13371             log_statement(l_api_name, 'After deleting  Wms_re_common_pvt.GetCountInputLines ',
13372                                        Wms_re_common_pvt.GetCountInputLines);
13373          END IF;
13374          IF p_type_code = 2 AND Wms_re_common_pvt.GetCountInputLines > 0  /*and l_consist_existsi */
13375             AND x_finished = fnd_api.g_true
13376          THEN
13377             x_finished := fnd_api.g_false;
13378             IF l_debug = 1 THEN
13379                log_statement(l_api_name, 'p_type_code 2: After   x_finished :' ,  'False'   );
13380             END IF;
13381          ELSIF p_type_code = 2 AND Wms_re_common_pvt.GetCountInputLines = 0 AND x_finished  = fnd_api.g_false
13382          THEN
13383             IF l_debug = 1 THEN
13384                log_statement(l_api_name, 'GetCountInputLines = 0 /    x_finished :' ,  'True'   );
13385             END IF;
13386             x_finished  := fnd_api.g_true;
13387          END IF;
13388          ----------- end of bug fix 13496654
13389 
13390          -- start of 8744417
13391          IF l_debug = 1 THEN
13392             log_statement(l_api_name, 'Wms_re_common_pvt.GetCountInputLines ' , Wms_re_common_pvt.GetCountInputLines  );
13393          END IF;
13394          IF p_type_code = 1 AND Wms_re_common_pvt.GetCountInputLines > 0
13395             AND x_finished = fnd_api.g_true
13396          THEN
13397             x_finished  := fnd_api.g_false;
13398             IF l_debug = 1 THEN
13399                log_statement(l_api_name, 'After   x_finished :' ,  'False'   );
13400             END IF;
13401          ELSIF p_type_code = 1 AND Wms_re_common_pvt.GetCountInputLines = 0
13402                AND x_finished = fnd_api.g_false
13403          THEN
13404             x_finished  := fnd_api.g_true;
13405             IF l_debug = 1 THEN
13406                log_statement(l_api_name, 'GetCountInputLines = 0 /    x_finished  :' ,  'True'   );
13407             END IF;
13408          END IF;
13409          -- end of 8744417
13410       END IF; --}
13411 
13412       IF l_debug_on THEN
13413          wms_search_order_globals_pvt.insert_trace_lines(
13414            p_api_version                => 1.0
13415          , p_init_msg_list              => fnd_api.g_false
13416          , p_validation_level           => fnd_api.g_valid_level_full
13417          , x_return_status              => l_return_status
13418          , x_msg_count                  => x_msg_count
13419          , x_msg_data                   => x_msg_data
13420          , p_header_id                  => wms_engine_pvt.g_trace_header_id
13421          , p_rule_id                    => l_rule_id
13422          , p_pre_suggestions            => g_trace_recs
13423          );
13424       END IF;
13425 
13426       <<NextINputRecord>>
13427       NULL;
13428     END LOOP; --} input records
13429 
13430     --
13431     -- Standard check of p_commit
13432     IF fnd_api.to_boolean(p_commit) THEN
13433        COMMIT WORK;
13434     END IF;
13435 
13436     -- end of debugging section
13437     IF l_debug = 1 THEN
13438        log_procedure(l_api_name, 'end', 'End Apply');
13439     END IF;
13440   --
13441   EXCEPTION
13442     WHEN fnd_api.g_exc_error THEN
13443       --
13444       --if l_pack_exists <>2, then open_curs was never called, so no need to
13445       --   close the cursor
13446       IF (l_pack_exists = 2) THEN
13447         close_pick_rule(l_rule_id, v_pick_cursor);
13448       END IF;
13449 
13450       --this function reduces the suggested units in the location
13451       -- for each record inserted in wms_transaction_temp as a
13452       -- putaway output record
13453       rollback_capacity_update(
13454         x_return_status              => l_return_status
13455       , x_msg_count                  => l_msg_count
13456       , x_msg_data                   => l_msg_data
13457       , p_organization_id            => p_organization_id
13458       , p_inventory_item_id          => p_inventory_item_id
13459       );
13460 
13461       --if error occurred after capacity got updated but before
13462       -- insertion into WTT, fix the capacity for that record
13463       IF l_capacity_updated THEN
13464         inv_loc_wms_utils.revert_loc_suggested_capacity(
13465           x_return_status              => l_return_status
13466         , x_msg_count                  => l_msg_count
13467         , x_msg_data                   => l_msg_data
13468         , p_organization_id            => p_organization_id
13469         , p_inventory_location_id      => l_olocator_id
13470         , p_inventory_item_id          => p_inventory_item_id
13471         , p_primary_uom_flag           => 'Y'
13472         , p_transaction_uom_code       => NULL
13473         , p_quantity                   => l_possible_quantity
13474         );
13475         l_capacity_updated  := FALSE;
13476       END IF;
13477 
13478       ROLLBACK TO applyrulesp;
13479       freeglobals;
13480       x_return_status  := fnd_api.g_ret_sts_error;
13481       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13482       IF l_debug = 1 THEN
13483          log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
13484       END IF;
13485     --
13486     WHEN fnd_api.g_exc_unexpected_error THEN
13487       --if l_pack_exists <>2, then open_curs was never called, so no need to
13488       --   close the cursor
13489       IF (l_pack_exists = 2) THEN
13490         close_put_rule(l_rule_id, v_put_cursor);
13491       END IF;
13492 
13493       --this function reduces the suggested units in the location
13494       -- for each record inserted in wms_transaction_temp as a
13495       -- putaway output record
13496       rollback_capacity_update(
13497         x_return_status              => l_return_status
13498       , x_msg_count                  => l_msg_count
13499       , x_msg_data                   => l_msg_data
13500       , p_organization_id            => p_organization_id
13501       , p_inventory_item_id          => p_inventory_item_id
13502       );
13503 
13504       --if error occurred after capacity got updated but before
13505       -- insertion into WTT, fix the capacity for that record
13506       IF l_capacity_updated THEN
13507         inv_loc_wms_utils.revert_loc_suggested_capacity(
13508           x_return_status              => l_return_status
13509         , x_msg_count                  => l_msg_count
13510         , x_msg_data                   => l_msg_data
13511         , p_organization_id            => p_organization_id
13512         , p_inventory_location_id      => l_olocator_id
13513         , p_inventory_item_id          => p_inventory_item_id
13514         , p_primary_uom_flag           => 'Y'
13515         , p_transaction_uom_code       => NULL
13516         , p_quantity                   => l_possible_quantity
13517         );
13518         l_capacity_updated  := FALSE;
13519       END IF;
13520 
13521       ROLLBACK TO applyrulesp;
13522       freeglobals;
13523       x_return_status  := fnd_api.g_ret_sts_unexp_error;
13524       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13525       IF l_debug = 1 THEN
13526          log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
13527       END IF;
13528     --
13529     WHEN OTHERS THEN
13530       --if l_pack_exists <>2, then open_curs was never called, so no need to
13531       --   close the cursor
13532       IF (l_pack_exists = 2) THEN
13533         close_put_rule(l_rule_id, v_put_cursor);
13534       END IF;
13535 
13536       --this function reduces the suggested units in the location
13537       -- for each record inserted in wms_transaction_temp as a
13538       -- putaway output record
13539       rollback_capacity_update(
13540         x_return_status              => l_return_status
13541       , x_msg_count                  => l_msg_count
13542       , x_msg_data                   => l_msg_data
13543       , p_organization_id            => p_organization_id
13544       , p_inventory_item_id          => p_inventory_item_id
13545       );
13546 
13547       --if error occurred after capacity got updated but before
13548       -- insertion into WTT, fix the capacity for that record
13549       IF l_capacity_updated THEN
13550         inv_loc_wms_utils.revert_loc_suggested_capacity(
13551           x_return_status              => l_return_status
13552         , x_msg_count                  => l_msg_count
13553         , x_msg_data                   => l_msg_data
13554         , p_organization_id            => p_organization_id
13555         , p_inventory_location_id      => l_olocator_id
13556         , p_inventory_item_id          => p_inventory_item_id
13557         , p_primary_uom_flag           => 'Y'
13558         , p_transaction_uom_code       => NULL
13559         , p_quantity                   => l_possible_quantity
13560         );
13561         l_capacity_updated  := FALSE;
13562       END IF;
13563 
13564       ROLLBACK TO applyrulesp;
13565       freeglobals;
13566       x_return_status  := fnd_api.g_ret_sts_unexp_error;
13567 
13568       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
13569         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
13570       END IF;
13571 
13572       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13573       IF l_debug = 1 THEN
13574          log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
13575       END IF;
13576   END apply;
13577 
13578 
13579   --
13580   -- --------------------------------------------------------------------------
13581   -- What does it do:
13582   -- Determines final location control based on location controls defined at
13583   -- organization, subinventory and item level.
13584   -- --------------------------------------------------------------------------
13585   --
13586   FUNCTION loc_control
13587     ( p_org_control      IN    NUMBER
13588      ,p_sub_control      IN    NUMBER
13589      ,p_item_control     IN    NUMBER DEFAULT NULL
13590      ,x_return_status    OUT   NOCOPY VARCHAR2
13591      ,x_msg_count        OUT   NOCOPY NUMBER
13592      ,x_msg_data         OUT   NOCOPY VARCHAR2
13593      ) RETURN NUMBER
13594     IS
13595         --
13596         -- constants
13597         l_api_name        CONSTANT VARCHAR(30) := 'loc_control';
13598         --
13599         -- return variable
13600         l_locator_control NUMBER;
13601         --
13602         -- exception
13603         invalid_loc_control_exception EXCEPTION;
13604         --
13605   BEGIN
13606      IF (p_org_control = 1) THEN
13607          l_locator_control := 1;
13608       ELSIF (p_org_control = 2) THEN
13609          l_locator_control := 2;
13610       ELSIF (p_org_control = 3) THEN
13611          l_locator_control := 2 ;
13612       ELSIF (p_org_control = 4) THEN
13613         IF (p_sub_control = 1) THEN
13614            l_locator_control := 1;
13615         ELSIF (p_sub_control = 2) THEN
13616            l_locator_control := 2;
13617         ELSIF (p_sub_control = 3) THEN
13618            l_locator_control := 2;
13619         ELSIF (p_sub_control = 5) THEN
13620           IF (p_item_control = 1) THEN
13621              l_locator_control := 1;
13622           ELSIF (p_item_control = 2) THEN
13623              l_locator_control := 2;
13624           ELSIF (p_item_control = 3) THEN
13625              l_locator_control := 2;
13626           ELSIF (p_item_control IS NULL) THEN
13627              l_locator_control := p_sub_control;
13628           ELSE
13629             RAISE invalid_loc_control_exception;
13630           END IF;
13631         ELSE
13632             RAISE invalid_loc_control_exception;
13633         END IF;
13634       ELSE
13635             RAISE invalid_loc_control_exception;
13636       END IF;
13637       --
13638       x_return_status := fnd_api.g_ret_sts_success;
13639       RETURN l_locator_control;
13640   EXCEPTION
13641      WHEN invalid_loc_control_exception THEN
13642         fnd_message.set_name('INV','INV_INVALID_LOC_CONTROL');
13643         fnd_msg_pub.ADD;
13644         --
13645         x_return_status := fnd_api.g_ret_sts_error ;
13646         l_locator_control := -1 ;
13647         RETURN l_locator_control ;
13648         --
13649      WHEN fnd_api.g_exc_error THEN
13650         x_return_status := fnd_api.g_ret_sts_error ;
13651         l_locator_control := -1 ;
13652         RETURN l_locator_control ;
13653         --
13654      WHEN fnd_api.g_exc_unexpected_error THEN
13655           x_return_status := fnd_api.g_ret_sts_unexp_error ;
13656           l_locator_control := -1 ;
13657           RETURN l_locator_control ;
13658           --
13659      WHEN OTHERS THEN
13660         x_return_status := fnd_api.g_ret_sts_unexp_error ;
13661         --
13662         IF (fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error)) THEN
13663               fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
13664         END IF;
13665         --
13666         l_locator_control := -1 ;
13667         RETURN l_locator_control ;
13668         --
13669   END loc_control;
13670   --
13671   -- --------------------------------------------------------------------------
13672   -- What does it do:
13673   -- Fetches default putaway sub/locations.
13674   -- they are retained as putaway sub/locations
13675   -- The following call will be used for Non WMS enabled org where default putaway rules
13676   -- are not used and If the input sub/loc are not null,
13677   -- This Procedure called from Applydef()
13678   -- --------------------------------------------------------------------------
13679   --
13680   PROCEDURE get_putaway_defaults
13681     ( p_organization_id           IN  NUMBER,
13682       p_inventory_item_id         IN  NUMBER,
13683       p_to_subinventory_code      IN  VARCHAR2,
13684       p_to_locator_id             IN  NUMBER,
13685       p_to_cost_group_id                IN  NUMBER,
13686       p_org_locator_control_code  IN  NUMBER,
13687       p_item_locator_control_code IN  NUMBER,
13688       p_transaction_type_id        IN  NUMBER,
13689       x_putaway_sub                  OUT NOCOPY VARCHAR2,
13690       x_putaway_loc                  OUT NOCOPY NUMBER,
13691       x_putaway_cost_group_id            OUT NOCOPY NUMBER,
13692       x_return_status                OUT NOCOPY VARCHAR2,
13693       x_msg_count                    OUT NOCOPY NUMBER,
13694       x_msg_data                     OUT NOCOPY VARCHAR2
13695      )
13696     IS
13697        -- constants
13698        l_api_name          CONSTANT VARCHAR(30) := 'get_putaway_defaults';
13699        l_return_status     VARCHAR2(1) :=  fnd_api.g_ret_sts_success;
13700        --
13701        -- variable
13702        l_sub_loc_control   NUMBER;
13703        l_loc_control       NUMBER;
13704        l_putaway_sub       VARCHAR2(30);
13705        l_putaway_loc       NUMBER;
13706        l_putaway_cg         NUMBER := NULL;
13707        l_putaway_cg_org         NUMBER;
13708        l_inventory_item_id NUMBER;
13709        l_organization_id   NUMBER;
13710        l_sub_status         NUMBER;
13711        l_loc_status         NUMBER;
13712        l_allowed                 VARCHAR2(1);
13713        l_primary_cost_method NUMBER;
13714        l_sub_found         BOOLEAN;
13715 
13716        l_debug NUMBER;
13717        --
13718        CURSOR l_subinventory_code_csr IS
13719           SELECT  subinventory_code
13720             FROM  mtl_item_sub_defaults
13721             WHERE inventory_item_id = l_inventory_item_id
13722               AND organization_id   = l_organization_id
13723               AND default_type      = 3;  -- default transfer order sub
13724 
13725        CURSOR l_locator_status_csr IS
13726           SELECT  status_id
13727             FROM  mtl_item_locations
13728             WHERE inventory_location_id = l_putaway_loc
13729               AND organization_id  = l_organization_id ;
13730        --
13731        CURSOR l_locator_csr IS
13732           SELECT  locator_id
13733             FROM  mtl_item_loc_defaults mtld,
13734                   mtl_item_locations mil
13735             WHERE mtld.locator_id        = mil.inventory_location_id
13736               AND mtld.organization_id   = mil.organization_id
13737               AND mtld.inventory_item_id = l_inventory_item_id
13738               AND mtld.organization_id   = l_organization_id
13739               AND mtld.subinventory_code = l_putaway_sub
13740               AND mtld.default_type      = 3
13741               AND nvl(mil.disable_date,sysdate + 1) > sysdate;
13742 
13743 
13744   BEGIN
13745      l_organization_id   := p_organization_id;
13746      l_inventory_item_id := p_inventory_item_id;
13747 
13748      IF  g_debug IS NOT NULL  THEN
13749           g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
13750      END IF;
13751      l_debug := g_debug;
13752 
13753      IF l_debug = 1  THEN
13754            log_procedure(l_api_name, 'start', 'Start get_putaway_defaults');
13755      END IF;
13756 
13757      -- search for default sub if to_sub in input row is null
13758      IF p_to_subinventory_code IS NULL THEN
13759         OPEN l_subinventory_code_csr;
13760         FETCH l_subinventory_code_csr INTO l_putaway_sub;
13761         IF l_subinventory_code_csr%notfound OR
13762                   l_putaway_sub IS NULL  THEN
13763              CLOSE l_subinventory_code_csr;
13764            fnd_message.set_name('INV','INV_NO_DEFAULT_SUB');
13765              fnd_msg_pub.ADD;
13766              RAISE fnd_api.g_exc_error;
13767         END IF;
13768         CLOSE l_subinventory_code_csr;
13769       ELSE
13770         l_putaway_sub := p_to_subinventory_code ;
13771      END IF;
13772 
13773      l_sub_found := INV_CACHE.set_tosub_rec(l_organization_id, l_putaway_sub);
13774 
13775      -- now get the locator control and then determine if
13776      -- default locator needs to be selected from item defaults
13777      --
13778     IF NOT l_sub_found THEN
13779         fnd_message.set_name('INV','INV_NO_SUB_LOC_CONTROL');
13780         fnd_msg_pub.ADD;
13781         RAISE fnd_api.g_exc_error;
13782      END if;
13783 
13784      l_sub_loc_control := INV_CACHE.tosub_rec.locator_type;
13785 
13786      IF l_debug = 1  THEN
13787         log_statement(l_api_name, 'p_org_locator_control_code',  p_org_locator_control_code);
13788         log_statement(l_api_name, 'l_sub_loc_control '        ,  l_sub_loc_control);
13789         log_statement(l_api_name, 'p_item_locator_control_code'    ,  p_item_locator_control_code);
13790      END IF;
13791 
13792      -- find out the real locator control
13793 
13794      l_loc_control := loc_control
13795        ( p_org_locator_control_code
13796         ,l_sub_loc_control
13797         ,p_item_locator_control_code
13798         ,l_return_status
13799         ,x_msg_count
13800         ,x_msg_data);
13801 
13802      IF l_debug = 1  THEN
13803          log_statement(l_api_name, 'l_sub_loc_control ',  l_sub_loc_control);
13804          log_statement(l_api_name, 'l_loc_control '    ,  l_loc_control);
13805      END IF;
13806 
13807      IF l_return_status = fnd_api.g_ret_sts_error THEN
13808         RAISE fnd_api.g_exc_error ;
13809       ELSIF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
13810         RAISE fnd_api.g_exc_unexpected_error;
13811      END IF;
13812 
13813     --
13814     IF l_loc_control = 2 THEN -- has locator control
13815         -- if no to_loc was supplied then get from defaults
13816         IF p_to_locator_id IS NULL THEN
13817            OPEN l_locator_csr;
13818            FETCH l_locator_csr INTO l_putaway_loc;
13819            IF l_locator_csr%notfound OR l_putaway_loc IS NULL THEN
13820               CLOSE l_locator_csr;
13821               fnd_message.set_name('INV','INV_NO_DEFAULT_LOC');
13822               fnd_msg_pub.ADD;
13823 
13824              RAISE fnd_api.g_exc_error;
13825            END IF;
13826          ELSE
13827            l_putaway_loc := p_to_locator_id ;
13828            IF l_debug = 1  THEN
13829               log_statement(l_api_name, 'l_putaway_loc'    ,  l_putaway_loc);
13830             END IF;
13831         END IF;
13832 
13833      END IF;
13834 
13835      -- Now get the cost group.  If the to_cost_group is specified
13836      -- on the move order, then use that.  If not, query the default
13837      -- cost group for the subinventory if in a standard costing org.
13838      -- If not defined there, or if avg. costing org
13839      -- try to get the default cost group from the organization
13840 
13841      IF p_to_cost_group_id IS NULL THEN
13842         IF INV_CACHE.set_org_rec(l_organization_id) THEN
13843            l_primary_cost_method := INV_CACHE.org_rec.primary_cost_method;
13844            l_putaway_cg_org := INV_CACHE.org_rec.default_cost_group_id;
13845         ELSE
13846            l_primary_cost_method := 2;
13847            l_putaway_cg_org := NULL;
13848         End If;
13849 
13850         If l_primary_cost_method = 1 Then
13851            IF l_sub_found THEN
13852               l_putaway_cg := INV_CACHE.tosub_rec.default_cost_group_id;
13853            ELSE
13854               l_putaway_cg := NULL;
13855            end if;
13856         End If;
13857 
13858         If l_putaway_cg IS NULL Then
13859            l_putaway_cg := l_putaway_cg_org;
13860            if l_putaway_cg IS NULL then
13861               fnd_message.set_name('INV','INV_NO_DEFAULT_COST_GROUP');
13862               fnd_msg_pub.ADD;
13863               RAISE fnd_api.g_exc_error;
13864            end if;
13865         End If;
13866       ELSE
13867         l_putaway_cg := p_to_cost_group_id;
13868      END IF;
13869 
13870      x_putaway_sub                 := l_putaway_sub;
13871      x_putaway_loc                 := l_putaway_loc;
13872      x_putaway_cost_group_id         := l_putaway_cg;
13873      x_return_status                 := l_return_status;
13874      /*
13875      IF l_putaway_loc is NULL THEN
13876         x_return_status   := 'N' ;
13877      END IF;
13878      */
13879 
13880      If l_debug = 1  THEN
13881         log_statement(l_api_name, 'Default Putaway values l_putaway_sub ', l_putaway_sub);
13882         log_statement(l_api_name, 'Default Putaway values l_putaway_loc ', l_putaway_loc);
13883         log_statement(l_api_name, 'Default Putaway values l_putaway_cg ',  l_putaway_cg);
13884         log_statement(l_api_name, 'Default Putaway values l_return_status ',  l_return_status);
13885      END IF;
13886 
13887 
13888   EXCEPTION
13889      WHEN fnd_api.g_exc_error THEN
13890           x_return_status := fnd_api.g_ret_sts_error ;
13891           x_putaway_loc   := NULL;
13892           x_putaway_sub   := NULL;
13893           x_putaway_cost_group_id := NULL;
13894           --
13895      WHEN fnd_api.g_exc_unexpected_error THEN
13896           x_return_status := fnd_api.g_ret_sts_unexp_error ;
13897           x_putaway_loc   := NULL;
13898           x_putaway_sub   := NULL;
13899           x_putaway_cost_group_id := NULL;
13900           --
13901      WHEN OTHERS THEN
13902         x_return_status := fnd_api.g_ret_sts_unexp_error ;
13903           x_putaway_loc   := NULL;
13904           x_putaway_sub   := NULL;
13905           x_putaway_cost_group_id := NULL;
13906           --
13907           IF (fnd_msg_pub.check_msg_level
13908               (fnd_msg_pub.g_msg_lvl_unexp_error)) THEN
13909              fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
13910           END IF;
13911   --
13912 
13913 END get_putaway_defaults ;
13914 --
13915 -- API name    : ApplyDefLoc
13916 -- Type        : Private
13917 -- Function    : Verifies a Putaway location with the given transaction
13918 --               input parameters and creates recommendations
13919 --               This API does not utlize the rules and should only be
13920 --               called when the Inventory Locator is specified on
13921 --               the input transaction and there is no requirement
13922 --               to check capacity.
13923 -- Pre-reqs    :
13924 --
13925 -- Parameters  :
13926 --   p_api_version          Standard Input Parameter
13927 --   p_init_msg_list        Standard Input Parameter
13928 --   p_commit               Standard Input Parameter
13929 --   p_validation_level     Standard Input Parameter
13930 --   p_transaction_temp_id  Identifier for the record in view
13931 --                          wms_strategy_mat_txn_tmp_v that represents
13932 --                          the request for detailing
13933 --   p_organization_id      Organization identifier
13934 --   p_inventory_item_id    Inventory item identifier
13935 --   p_transaction_uom      Transaction UOM code
13936 --   p_primary_uom          Primary UOM code
13937 --   p_project_id           Project associated with transaction
13938 --   p_task_id              Task associated with transaction
13939 --
13940 -- Output Parameters
13941 --   x_return_status        Standard Output Parameter
13942 --   x_msg_count            Standard Output Parameter
13943 --   x_msg_data             Standard Output Parameter
13944 --   x_finished             whether the rule has found enough quantity to
13945 --                          find a location that completely satisfy
13946 --                          the requested quantity (value is 'Y' or 'N')
13947 --
13948 -- Version
13949 --   Currently version is 1.0
13950 --
13951 -- Notes       : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
13952 --               This API must be called internally by
13953 --               WMS_Strategy_PVT.Apply only !
13954 --APPLY
13955 PROCEDURE applydefloc(
13956    p_api_version                  IN   NUMBER   ,
13957    p_init_msg_list                IN   VARCHAR2 ,
13958    p_commit                       IN   VARCHAR2 ,
13959    p_validation_level             IN   NUMBER   ,
13960    x_return_status                OUT NOCOPY VARCHAR2 ,
13961    x_msg_count                    OUT NOCOPY NUMBER   ,
13962    x_msg_data                     OUT NOCOPY VARCHAR2 ,
13963    p_transaction_temp_id          IN   NUMBER   ,
13964    p_organization_id              IN   NUMBER   ,
13965    p_inventory_item_id            IN   NUMBER   ,
13966    p_subinventory_code            IN   VARCHAR2 ,
13967    p_locator_id                   IN   NUMBER   ,
13968    p_transaction_uom              IN   VARCHAR2 ,
13969    p_primary_uom                  IN   VARCHAR2 ,
13970    p_transaction_type_id          IN   NUMBER   ,
13971    x_finished                     OUT NOCOPY VARCHAR2 ,
13972    p_lpn_id                       IN   NUMBER   ,
13973    p_simulation_mode              IN   NUMBER   ,
13974    p_project_id                   IN   NUMBER   ,
13975    p_task_id                      IN   NUMBER
13976   )
13977   IS
13978 
13979   -- API standard variables
13980   l_api_version          constant number       := 1.0;
13981   l_api_name             constant varchar2(30) := 'ApplyDefLoc';
13982   -- variables needed for dynamic SQL
13983   l_cursor               integer;
13984   l_rows                 integer;
13985   -- rule dynamic SQL input variables
13986   l_pp_transaction_temp_id
13987                          WMS_TRANSACTIONS_TEMP.PP_TRANSACTION_TEMP_ID%TYPE;
13988   l_revision             WMS_TRANSACTIONS_TEMP.REVISION%TYPE;
13989   l_lot_number           WMS_TRANSACTIONS_TEMP.LOT_NUMBER%TYPE;
13990   l_lot_expiration_date  WMS_TRANSACTIONS_TEMP.LOT_EXPIRATION_DATE%TYPE;
13991   l_from_subinventory_code WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
13992   l_to_subinventory_code WMS_TRANSACTIONS_TEMP.TO_SUBINVENTORY_CODE%TYPE;
13993   l_from_locator_id      WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
13994   l_to_locator_id        WMS_TRANSACTIONS_TEMP.TO_LOCATOR_ID%TYPE;
13995   l_from_cost_group_id   WMS_TRANSACTIONS_TEMP.FROM_COST_GROUP_ID%TYPE;
13996   l_to_cost_group_id     WMS_TRANSACTIONS_TEMP.TO_COST_GROUP_ID%TYPE;
13997   l_lpn_id               WMS_TRANSACTIONS_TEMP.LPN_ID%TYPE;
13998   l_initial_pri_quantity WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
13999   -- rule dynamic SQL output variables
14000   l_osubinventory_code   WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
14001   l_olocator_id          WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
14002   l_olocator_id_prev     WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
14003   l_olocator_id_new      WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
14004   l_olocator_id_exist    WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
14005   l_possible_quantity    WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
14006   l_possible_trx_qty     WMS_TRANSACTIONS_TEMP.TRANSACTION_QUANTITY%TYPE;
14007   l_sec_possible_quantity    WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
14008   l_sec_possible_trx_qty     WMS_TRANSACTIONS_TEMP.TRANSACTION_QUANTITY%TYPE;
14009   l_reservation_id       WMS_TRANSACTIONS_TEMP.RESERVATION_ID%TYPE;
14010   l_grade_code           VARCHAR2(150);
14011 
14012   l_needed_quantity     NUMBER;
14013   l_sec_needed_quantity NUMBER;
14014   l_locs_index          NUMBER;
14015   l_return_status       VARCHAR2(1);
14016   l_allowed             VARCHAR2(1);
14017   l_debug_on            BOOLEAN;
14018   l_check_cg            BOOLEAN;
14019   l_lpn_controlled_flag NUMBER;
14020   l_comingle            VARCHAR2(1);
14021   l_dummy               NUMBER;
14022 
14023   --added to support pjm
14024   l_project_id          NUMBER;
14025   l_task_id             NUMBER;
14026   l_input_lpn_id        NUMBER;
14027   l_debug               NUMBER;
14028   l_serial_number       NUMBER; -- [ new code ]
14029   use_supplied_loc      BOOLEAN;
14030 
14031   l_locator_type        NUMBER;
14032   x_subinventory_code   WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
14033   x_locator_id          WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
14034   x_cost_group_id       WMS_TRANSACTIONS_TEMP.FROM_COST_GROUP_ID%TYPE;
14035   l_to_cg_id            NUMBER ;  --10244350
14036 
14037    --cursor to get lpn controlled flag from subinventory
14038    CURSOR l_lpn_controlled IS
14039         SELECT lpn_controlled_flag
14040           FROM mtl_secondary_inventories
14041          WHERE organization_id = p_organization_id
14042            AND secondary_inventory_name = l_osubinventory_code;
14043 
14044 
14045 BEGIN
14046 
14047   IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
14048      g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
14049   END IF;
14050   l_debug := g_debug;
14051 
14052   If (l_debug = 1) then
14053     log_procedure(l_api_name, 'start', 'Start ApplyDefLoc');
14054   End if;
14055   -- end of debugging section
14056 
14057   -- Standard start of API savepoint
14058   SAVEPOINT ApplyRuleSP;
14059   --
14060 
14061 
14062   -- Standard call to check for call compatibility
14063   IF NOT fnd_api.compatible_api_call( l_api_version
14064                                      ,p_api_version
14065                                      ,l_api_name
14066                                      ,g_pkg_name ) THEN
14067     RAISE fnd_api.g_exc_unexpected_error;
14068   END IF;
14069 
14070   -- Initialize message list if p_init_msg_list is set to TRUE
14071   IF fnd_api.to_boolean( p_init_msg_list ) THEN
14072     fnd_msg_pub.initialize;
14073   END IF;
14074   --
14075   -- Initialize API return status to success
14076   x_return_status := fnd_api.g_ret_sts_success;
14077   --
14078   -- Initialize functional return status to completed
14079   x_finished := fnd_api.g_true;
14080   --
14081   -- Validate input parameters and pre-requisites, if validation level
14082   -- requires this
14083   IF p_validation_level <> fnd_api.g_valid_level_none THEN
14084     IF p_transaction_temp_id IS NULL OR
14085        p_transaction_temp_id = fnd_api.g_miss_num  THEN
14086       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14087         fnd_message.set_name('WMS','WMS_TRX_REQ_LINE_ID_MISS');
14088         If (l_debug = 1) then
14089           log_error_msg(l_api_name, 'trx_req_line_id_missing');
14090         End if;
14091         fnd_msg_pub.add;
14092       END IF;
14093       RAISE fnd_api.g_exc_error;
14094     END IF;
14095     IF p_organization_id IS NULL OR
14096        p_organization_id = fnd_api.g_miss_num  THEN
14097       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14098         fnd_message.set_name('INV','INV_NO_ORG_INFORMATION');
14099         If (l_debug = 1) then
14100           log_error_msg(l_api_name, 'org_id_missing');
14101         End if;
14102         fnd_msg_pub.add;
14103       END IF;
14104       RAISE fnd_api.g_exc_error;
14105     END IF;
14106     IF p_inventory_item_id IS NULL OR
14107        p_inventory_item_id = fnd_api.g_miss_num  THEN
14108       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14109         fnd_message.set_name('INV','INV_ITEM_ID_REQUIRED');
14110         If (l_debug = 1) then
14111           log_error_msg(l_api_name, 'item_id_missing');
14112         End if;
14113         fnd_msg_pub.add;
14114       END IF;
14115       RAISE fnd_api.g_exc_error;
14116     END IF;
14117   END IF;
14118   --inv_pp_debug.send_message_to_pipe('finished validations');
14119 
14120   --
14121   -- make sure, everything is clean
14122   FreeGlobals;
14123   wms_parameter_pvt.ClearCache;
14124   --
14125   g_trace_recs.DELETE;
14126   l_debug_on := IsRuleDebugOn(p_simulation_mode);
14127 
14128   if (l_debug = 1) then
14129     log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
14130     log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
14131   End if;
14132 
14133   -- Initialize the pointer to the first trx detail input line
14134   wms_re_common_pvt.InitInputPointer;
14135   --
14136   If (l_debug = 1) then
14137     log_statement(l_api_name, 'start_input_loop',
14138        'Starting loop through input lines');
14139   End if;
14140 
14141   -- Set the output locator and Sub to the supplied parameters
14142   l_osubinventory_code := p_subinventory_code;
14143   l_olocator_id        := p_locator_id;
14144 
14145 -- Loop through all the trx detail input lines
14146 -- Bug # 4637357
14147  use_supplied_loc := TRUE;
14148  WHILE use_supplied_loc LOOP
14149     If (l_debug = 1) then
14150          log_statement(l_api_name, 'getting input line',
14151            'calling wms_re_common_pvt.GetNextInputLine to get input line');
14152     End if;
14153 
14154          --
14155          -- Get the next trx detail input line
14156          wms_re_common_pvt.GetNextInputLine ( l_pp_transaction_temp_id
14157                                              ,l_revision
14158                                              ,l_lot_number
14159                                              ,l_lot_expiration_date
14160                                              ,l_from_subinventory_code
14161                                              ,l_from_locator_id
14162                                              ,l_from_cost_group_id
14163                                              ,l_to_subinventory_code
14164                                              ,l_to_locator_id
14165                                              ,l_to_cost_group_id
14166                                              ,l_needed_quantity
14167                                              ,l_sec_needed_quantity
14168                                              ,l_grade_code
14169                                              ,l_reservation_id
14170                                              ,l_serial_number -- [ new code ]
14171                                              ,l_lpn_Id);
14172          EXIT WHEN l_pp_transaction_temp_id IS NULL;
14173 
14174 
14175          IF  ( p_subinventory_code is NULL  AND  p_locator_id is NULL ) THEN
14176                 -- Set the output locator and Sub to the inlput line sub/loc
14177                 l_osubinventory_code := l_to_subinventory_code;
14178                 l_olocator_id        := l_to_locator_id;
14179 
14180          END IF;
14181 
14182 
14183          If (l_debug = 1) then
14184            log_statement(l_api_name, 'input_rec', 'Got next input line');
14185            log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
14186            log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
14187            log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
14188            log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
14189            log_statement(l_api_name, 'input_cg',  'cg:'  || l_from_cost_group_id);
14190            log_statement(l_api_name, 'input_tsub','tsub:'|| l_to_subinventory_code);
14191            log_statement(l_api_name, 'input_tloc','tloc:'|| l_to_locator_id);
14192            log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
14193            log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
14194            log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
14195            log_statement(l_api_name, 'input_sec_qty', 'sec qty:' || l_sec_needed_quantity);
14196      End if;
14197     --- Bug#4729564
14198     --- Populate default dest. loct for non-wms org if it is null and raise error if locator is null for dynamic loc controlled.
14199 
14200     /*10244350 -starts. For PJM orgs, the cost group at org/sub level may be different from that of project level CG */
14201     l_to_cg_id := l_to_cost_group_id ;
14202 
14203     IF ( l_to_cg_id  IS NULL AND p_transaction_type_id  in (51,52) AND p_project_id IS NOT NULL) THEN -- changes made for bug 13017591
14204           l_to_cg_id := l_from_cost_group_id;
14205     END IF;
14206     /*10244350 -Ends */
14207 
14208     get_putaway_defaults ( p_organization_id ,
14209                              p_inventory_item_id,
14210                              l_to_subinventory_code,
14211                              l_to_locator_id,
14212                              l_to_cg_id, --10244350
14213                              inv_cache.org_rec.stock_locator_control_code,
14214                              inv_cache.item_rec.location_control_code,
14215                              p_transaction_type_id,
14216                              x_subinventory_code ,
14217                              x_locator_id,
14218                              x_cost_group_id,
14219                              x_return_status,
14220                              x_msg_count,
14221                              x_msg_data );
14222 
14223     -- log_statement(l_api_name, 'Default Putaway values l_return_status ',  l_return_status);
14224 
14225     IF l_return_status = fnd_api.g_ret_sts_error THEN
14226          RAISE fnd_api.g_exc_error ;
14227          -- log_statement(l_api_name, 'ApplyDef()', 'Dest Loct is NUll' );
14228          -- GOTO NextOutputRecord;
14229     ELSIF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
14230          RAISE fnd_api.g_exc_unexpected_error;
14231     END IF;
14232 
14233    --log_statement(l_api_name, 'l_to_locator_id',nvl(l_to_locator_id, -9999) );
14234    IF  (l_osubinventory_code is NULL AND x_subinventory_code is not NULL ) then
14235        l_osubinventory_code := x_subinventory_code;
14236        If (l_debug = 1 ) then
14237           log_statement(l_api_name, 'Setting default SUB ',  l_osubinventory_code);
14238        End if;
14239    END IF;
14240 
14241    IF (l_olocator_id is NULL and x_locator_id is not NULL) THEN
14242        l_osubinventory_code := x_subinventory_code;
14243        l_olocator_id := x_locator_id;
14244        If (l_debug = 1 ) then
14245           log_statement(l_api_name, 'Setting default SUB / LOC ',  l_osubinventory_code);
14246           log_statement(l_api_name, 'Setting default LOC ',  l_olocator_id);
14247        End if;
14248    END IF;
14249 
14250    IF (l_to_cost_group_id is NULL and x_cost_group_id is NOT NULL ) THEN
14251        l_to_cost_group_id :=  x_cost_group_id;
14252    END IF;
14253    -- Bug 5682045 Changed l_to_locator_id to l_olocator_id
14254    IF l_olocator_id  is NULL THEN
14255       l_locator_type := NULL;
14256 
14257      -- log_statement(l_api_name, 'p_organization_id :', p_organization_id);
14258         log_statement(l_api_name, 'To check dynamic loc : l_to_subinventory_code', l_to_subinventory_code);
14259 
14260       select locator_type into l_locator_type
14261         from mtl_secondary_inventories
14262        where organization_id = p_organization_id
14263          and SECONDARY_INVENTORY_NAME  = l_to_subinventory_code;
14264 
14265       -- log_statement(l_api_name, 'l_locator_type' , l_locator_type);
14266 
14267       IF l_locator_type = 3 or l_locator_type = 2 THEN  -- Dynamic / Prespecified Loc Control
14268           If (l_debug = 1 ) then
14269             log_statement(l_api_name, 'Default Putaway values l_return_status ',  l_return_status);
14270             log_statement(l_api_name, 'ApplyDef()', 'Dest Loct is NUll / Go to Next record ' );
14271           End if;
14272 
14273          GOTO NextOutputRecord;
14274       END if;
14275   END IF;
14276   -- end of Bug#4729564
14277   --
14278 
14279   -- use_supplied_loc := TRUE;
14280   -- To support PJM, check project and task if supplied.
14281   -- Case 1) Project and Task not supplied do nothing
14282   --      2) Project and Task Supplied and current record has same
14283   --         project and task continue processing.
14284   --      3) Project and Task supplied, not in current record
14285   --         then create a new entry in MTL_ITEM_LOCATIONS with
14286   --         properties of current record but with require project and task
14287   --      <This assumes that the results are ordered by Project and Task>
14288   IF p_project_id IS NOT NULL THEN
14289 
14290       --bug 2400549 - for WIP backflush transfer putaway,
14291       --always use the locator specified on the move order line, even
14292       --if that locator is from common stock (not project)
14293       IF NOT(wms_engine_pvt.g_move_order_type = 7 and
14294          wms_engine_pvt.g_transaction_action_id = 2) THEN
14295         If (l_debug = 1) then
14296           log_statement(l_api_name, 'do_project2',
14297               'Calling do project check');
14298         End if;
14299         IF DoProjectCheck(l_return_status, l_olocator_id,
14300                   p_project_id, p_task_id, l_olocator_id_new, l_olocator_id_exist)
14301         THEN
14302           If (l_debug = 1) then
14303             log_statement(l_api_name, 'do_project_success',
14304               'Do project check returned new locator');
14305           End if;
14306           l_olocator_id_prev := l_olocator_id;
14307           l_olocator_id := l_olocator_id_new;
14308         ELSE
14309           -- Current locator does not have required project/task
14310           -- If it exists use it
14311           If l_olocator_id_exist IS NOT NULL THEN
14312              l_olocator_id := l_olocator_id_exist;
14313           ELSE
14314              use_supplied_loc := false;
14315              x_finished := fnd_api.g_false;
14316              If (l_debug = 1) then
14317                log_statement(l_api_name, 'do_project_fail',
14318                  'Do project check failed. Cannot use supplied locator with this Project and Task.');
14319              End if;
14320           End if;
14321         END IF; --do project check
14322       END IF;  -- not wip backflush
14323   END IF; -- needed project <> -9999
14324 
14325 
14326   --check status to see if putting away to this location is allowed
14327   -- for this transaction type
14328   -- This API checks the status for the subinventory, locator,
14329   -- and lot
14330 
14331   -- Pass in NULL for lot number as this was checked during Pick
14332   If (l_debug = 1) then
14333        log_statement(l_api_name, 'checking_status',
14334          'calling is_sub_loc_lot_trx_allowed to check status');
14335   End if;
14336   If g_transaction_type_id = p_transaction_type_id AND
14337      g_organization_id = p_organization_id AND
14338      g_inventory_item_id = p_inventory_item_id AND
14339      g_subinventory_code = l_osubinventory_code AND
14340      g_st_locator_id = l_olocator_id  THEN
14341      l_allowed := g_allowed;
14342   ELSE
14343 
14344      l_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
14345               p_transaction_type_id  => p_transaction_type_id
14346              ,p_organization_id      => p_organization_id
14347              ,p_inventory_item_id    => p_inventory_item_id
14348              ,p_subinventory_code    => l_osubinventory_code
14349              ,p_locator_id           => l_olocator_id
14350              ,p_lot_number           => NULL);
14351 
14352 
14353      -- When changing SUB value set lpn_controlled_flag to null
14354      IF (g_organization_id = p_organization_id) OR (g_subinventory_code <> l_osubinventory_code) THEN
14355         g_lpn_controlled_flag := NULL;
14356      END IF;
14357 
14358      g_transaction_type_id := p_transaction_type_id;
14359      g_organization_id := p_organization_id;
14360      g_inventory_item_id := p_inventory_item_id;
14361      g_subinventory_code := l_osubinventory_code;
14362      g_st_locator_id := l_olocator_id;
14363      g_allowed := l_allowed;
14364    END IF;
14365 
14366    IF l_allowed <> 'Y' THEN
14367       use_supplied_loc := false;
14368       x_finished := fnd_api.g_false;
14369       If (l_debug = 1) then
14370          log_event(l_api_name, 'bad_status',
14371              'This transaction type is not allowed by the status ' ||
14372              'for the subinventory, locator. ');
14373       GOTO NextOutputRecord; --added for bug8533610
14374       End if;
14375    END IF;
14376 
14377 /* Commented and moved the following code above
14378    Check the tag  bug # 4637357
14379 
14380   -- Loop through all the trx detail input lines
14381   WHILE use_supplied_loc LOOP
14382      If (l_debug = 1) then
14383        log_statement(l_api_name, 'getting input line',
14384          'calling wms_re_common_pvt.GetNextInputLine to get input line');
14385      End if;
14386 
14387      --
14388      -- Get the next trx detail input line
14389      wms_re_common_pvt.GetNextInputLine ( l_pp_transaction_temp_id
14390                                          ,l_revision
14391                                          ,l_lot_number
14392                                          ,l_lot_expiration_date
14393                                          ,l_from_subinventory_code
14394                                          ,l_from_locator_id
14395                                          ,l_from_cost_group_id
14396                                          ,l_to_subinventory_code
14397                                          ,l_to_locator_id
14398                                          ,l_to_cost_group_id
14399                                          ,l_needed_quantity
14400                                          ,l_sec_needed_quantity
14401                                          ,l_grade_code
14402                                          ,l_reservation_id
14403                                          ,l_serial_number -- [ new code ]
14404                                          ,l_lpn_Id);
14405      EXIT WHEN l_pp_transaction_temp_id IS NULL;
14406 
14407      If (l_debug = 1) then
14408        log_statement(l_api_name, 'input_rec', 'Got next input line');
14409        log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
14410        log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
14411        log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
14412        log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
14413        log_statement(l_api_name, 'input_cg',  'cg:'  || l_from_cost_group_id);
14414        log_statement(l_api_name, 'input_tsub','tsub:'|| l_to_subinventory_code);
14415        log_statement(l_api_name, 'input_tloc','tloc:'|| l_to_locator_id);
14416        log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
14417        log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
14418        log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
14419        log_statement(l_api_name, 'input_sec_qty', 'sec qty:' || l_sec_needed_quantity);
14420      End if;
14421 */
14422      -- Save the initial input qty for later usage
14423      l_initial_pri_quantity := l_needed_quantity;
14424      --
14425      l_input_lpn_id := l_lpn_id;
14426 
14427      l_locs_index := 0;
14428 
14429      IF l_debug_on THEN
14430           g_trace_recs(l_locs_index).revision := l_revision;
14431           g_trace_recs(l_locs_index).lot_number := l_lot_number;
14432           g_trace_recs(l_locs_index).lot_expiration_date := l_lot_expiration_date;
14433           g_trace_recs(l_locs_index).subinventory_code := l_osubinventory_code;
14434           g_trace_recs(l_locs_index).locator_id := l_olocator_id;
14435           g_trace_recs(l_locs_index).cost_group_id := l_to_cost_group_id;
14436           g_trace_recs(l_locs_index).uom_code := NULL;
14437           g_trace_recs(l_locs_index).lpn_id := l_input_lpn_id;
14438           g_trace_recs(l_locs_index).quantity := NULL;
14439           --init to 0, in case of error
14440           g_trace_recs(l_locs_index).suggested_qty := 0;
14441           g_trace_recs(l_locs_index).Material_status_flag := 'Y';
14442 
14443           log_statement(l_api_name, 'fetch_put_sub',
14444                'Subinventory: ' || l_osubinventory_code);
14445           log_statement(l_api_name, 'fetch_put_loc',
14446                'Locator: ' || l_olocator_id);
14447           log_statement(l_api_name, 'fetch_put_proj',
14448                'Project: ' || l_project_id);
14449           log_statement(l_api_name, 'fetch_put_task',
14450                'Task: ' || l_task_id);
14451 
14452 
14453      END IF;
14454 
14455      --Determine if putaway sub is LPN controlled.  If it is not,
14456      --then we need to check cost group commingling always;
14457      -- Check cost group if
14458      -- Cost group is not null AND
14459      -- (sub is not lpn controlled OR
14460      --  No lpn on move order line OR
14461      --  not a staging transfer)
14462      --Never suggest comingling of cost groups, unless we are
14463      -- putting away a LPN.
14464      --When putting away an LPN, we assume that user is putting away
14465      -- whole LPN, which means there will never be comingling.
14466      --bug 1570597 - staging transfers are always put away in an LPN,
14467      -- so we don't need to check for comingling.
14468      --bug 2161565 - need to check for cg commingling if
14469      -- to subinventory is not LPN controlled.
14470      --bug 2492526 - putting away to a project controlled locator
14471      -- will always change the CG.  So no need to worry about CG
14472      -- commingling if the dest. loc is project controlled.
14473      If (l_debug = 1) then
14474        log_statement(l_api_name, 'Check LPN Controlled',
14475          'Check if cost group or project supplied and lpn controlled');
14476      End if;
14477      IF l_to_cost_group_id IS NULL THEN
14478         l_check_cg := FALSE;
14479      ELSIF l_project_id IS NOT NULL THEN
14480         l_check_cg := FALSE;
14481      ELSIF (p_lpn_id IS NOT NULL OR
14482         p_transaction_type_id IN (52,53,64)) THEN-- Added Move order transfer transaction - 64  for bug 14784282(FP of 11i bug 14757458) since MO xfer will always happen in a LPN
14483 		                                         --For "Move Any LPN" which shares the same trx type = 64, the condition "p_lpn_id IS NOT NULL" will always be TRUE
14484 												 --and so this change will not effect the "Move Any LPN" flow
14485 
14486         -- Start Added for Bug 14784282(FP of 11i bug 14757458)
14487 				IF l_debug = 1 THEN
14488                   log_statement(l_api_name, 'CG Check', 'In the condition for p_lpn_id not Null or Transaction type in 52,53,64');
14489                 END IF;
14490 		-- End Added for Bug 14784282(FP of 11i bug 14757458)
14491 
14492         If (nvl(g_subinventory_code,'-9999') <> l_osubinventory_code OR
14493              g_lpn_controlled_flag IS NULL) THEN
14494            OPEN l_lpn_controlled;
14495            FETCH l_lpn_controlled INTO g_lpn_controlled_flag;
14496            g_subinventory_code := l_osubinventory_code;
14497 
14498            -- by default, assume sub is lpn controlled
14499            If l_lpn_controlled%notfound OR
14500              g_lpn_controlled_flag IS NULL OR
14501              g_lpn_controlled_flag NOT IN (1,2) Then
14502                 g_lpn_controlled_flag := 1;
14503            End If;
14504            CLOSE l_lpn_controlled;
14505         End If;
14506         l_lpn_controlled_flag := g_lpn_controlled_flag;
14507 
14508         If (l_debug = 1) then
14509            log_statement(l_api_name, 'Check LPN Controlled',
14510             'lpn_control_flag : ' || l_lpn_controlled_flag);
14511         End if;
14512 
14513         If l_lpn_controlled_flag = 1 Then
14514            l_check_cg := FALSE;
14515         Else
14516            l_check_cg := TRUE;
14517         End If;
14518      ELSE
14519         l_check_cg := TRUE;
14520      END IF;
14521      --Check to see if putaway would comingle cost groups.
14522      IF l_check_cg THEN
14523         If (l_debug = 1) then
14524           log_statement(l_api_name, 'Check comingling',
14525              'calling inv_comingling_utils.comingle_check');
14526         End if;
14527         inv_comingling_utils.comingle_check(
14528               x_return_status => x_return_status
14529              ,x_msg_count => x_msg_count
14530              ,x_msg_data  => x_msg_data
14531              ,x_comingling_occurs => l_comingle
14532              ,x_count     => l_dummy
14533              ,p_organization_id => p_organization_id
14534              ,p_inventory_item_id => p_inventory_item_id
14535              ,p_revision => l_revision
14536              ,p_lot_number => l_lot_number
14537              ,p_subinventory_code => l_osubinventory_code
14538              ,p_locator_id => l_olocator_id
14539              ,p_lpn_id => NULL
14540              ,p_cost_group_id => l_to_cost_group_id
14541           );
14542         if x_return_status = fnd_api.g_ret_sts_unexp_error then
14543           If (l_debug = 1) then
14544             log_statement(l_api_name, 'uerr_comingle_check',
14545               'Unexpected error in comingle_check');
14546           End if;
14547           RAISE fnd_api.g_exc_unexpected_error;
14548         elsif x_return_status = fnd_api.g_ret_sts_error then
14549           If (l_debug = 1) then
14550             log_statement(l_api_name, 'err_comingle_check',
14551               'Error in comingle_check');
14552           End if;
14553           RAISE fnd_api.g_exc_error;
14554         end if;
14555 
14556         -- Skip record if it would cause comingling
14557         if l_comingle = 'Y' then
14558           If (l_debug = 1) then
14559             log_event(l_api_name, 'comingle_putaway',
14560               'Putaway to this location would comingle cost groups. ');
14561           End if;
14562           if l_debug_on then
14563              g_trace_recs(l_locs_index).CG_comingle_flag := 'N';
14564           end if;
14565           GOTO NextOutputRecord;
14566         end if;
14567 
14568         if l_debug_on then
14569              g_trace_recs(l_locs_index).CG_comingle_flag := 'Y';
14570         end if;
14571 
14572      END IF;
14573 
14574      l_possible_quantity := l_needed_quantity;
14575      l_sec_possible_quantity := l_sec_needed_quantity;
14576 
14577      IF l_debug_on THEN
14578         g_trace_recs(l_locs_index).suggested_qty := l_possible_quantity;
14579      END IF;
14580 
14581      -- get the transaction quantity
14582      IF p_transaction_uom = p_primary_uom THEN
14583         l_possible_trx_qty := l_possible_quantity;
14584       ELSE
14585         l_possible_trx_qty :=
14586              inv_convert.inv_um_convert(
14587                                         p_inventory_item_id
14588                                         ,NULL
14589                                         ,l_possible_quantity
14590                                         ,p_primary_uom
14591                                         ,p_transaction_uom
14592                                         ,NULL
14593                                         ,NULL);
14594      END IF;
14595      l_sec_possible_trx_qty := l_sec_possible_quantity;
14596      If (l_debug = 1) then
14597         log_statement(l_api_name, 'insert_put_wtt_recs',
14598          'Inserting putaway records in wtt');
14599      End if;
14600      -- insert temporary suggestion
14601      INSERT
14602        INTO WMS_TRANSACTIONS_TEMP
14603        ( PP_TRANSACTION_TEMP_ID
14604         ,TRANSACTION_TEMP_ID
14605         ,TYPE_CODE
14606         ,LINE_TYPE_CODE
14607         ,TRANSACTION_QUANTITY
14608         ,PRIMARY_QUANTITY
14609         ,SECONDARY_QUANTITY
14610         ,GRADE_CODE
14611         ,REVISION
14612         ,LOT_NUMBER
14613         ,LOT_EXPIRATION_DATE
14614         ,FROM_SUBINVENTORY_CODE
14615         ,FROM_LOCATOR_ID
14616         ,RULE_ID
14617         ,RESERVATION_ID
14618         ,TO_SUBINVENTORY_CODE
14619         ,TO_LOCATOR_ID
14620         ,FROM_COST_GROUP_ID
14621         ,TO_COST_GROUP_ID
14622         ,LPN_ID
14623         ) VALUES
14624        ( wms_transactions_temp_s.NEXTVAL
14625         ,p_transaction_temp_id
14626         ,1      -- p_type_code
14627         ,2             -- line type code is output
14628         ,l_possible_trx_qty
14629         ,l_possible_quantity
14630         ,l_sec_possible_quantity
14631         ,l_grade_code
14632         ,l_revision
14633         ,l_lot_number
14634         ,l_lot_expiration_date
14635         ,l_from_subinventory_code
14636         ,l_from_locator_id
14637         ,NULL   -- l_rule_id
14638         ,l_reservation_id
14639         ,l_osubinventory_code
14640         ,l_olocator_id
14641         ,l_from_cost_group_id
14642         ,l_to_cost_group_id
14643         ,l_input_lpn_id
14644          );
14645 
14646      If (l_debug = 1) then
14647        log_event(l_api_name, 'putaway_loc_found',
14648           'Found put away location for quantity ' || l_possible_quantity);
14649      End if;
14650 
14651      l_needed_quantity := 0;
14652 
14653      <<NextOutputRecord>>
14654 
14655 
14656 
14657      -- if input line couldn't get satisfied ...
14658      IF l_needed_quantity > 0 THEN
14659          -- notice, that at least one input record couldn't get satisfied
14660          x_finished := fnd_api.g_false;
14661          If (l_debug = 1) then
14662            log_event(l_api_name, 'no_success',
14663                'Locator supplied could not be used');
14664          End if;
14665 
14666      ELSE
14667          x_finished := fnd_api.g_true;
14668          -- if input line could get satisfied
14669          -- delete the input line in the wms_transactions_temp table
14670          If (l_debug = 1) then
14671           log_statement(l_api_name, 'deleting_input_rec',
14672               'Deleting the input line in WTT and pl/sql table');
14673          End if;
14674          DELETE
14675            FROM WMS_TRANSACTIONS_TEMP
14676            WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
14677          --
14678          -- and delete input record in PL/SQL table, too
14679          wms_re_common_pvt.DeleteInputLine;
14680      END IF;
14681      IF l_debug_on THEN
14682         wms_search_order_globals_pvt.insert_trace_lines(
14683            p_api_version => 1.0
14684           ,p_init_msg_list => fnd_api.g_false
14685           ,p_validation_level => fnd_api.g_valid_level_full
14686           ,x_return_status => l_return_status
14687           ,x_msg_count => x_msg_count
14688           ,x_msg_data => x_msg_data
14689           ,p_header_id => wms_engine_pvt.g_trace_header_id
14690           ,p_rule_id => null
14691           ,p_pre_suggestions => g_trace_recs
14692          );
14693      END IF;
14694 
14695   END LOOP;         -- input records
14696   --
14697   -- Standard check of p_commit
14698   IF fnd_api.to_boolean(p_commit) THEN
14699      COMMIT WORK;
14700   END IF;
14701   --
14702   If (l_debug = 1) then
14703     log_procedure(l_api_name, 'end', 'End Apply');
14704   End if;
14705   l_debug := NULL;
14706   --
14707 EXCEPTION
14708    WHEN fnd_api.g_exc_error THEN
14709 
14710     ROLLBACK TO ApplyRuleSP;
14711     FreeGlobals;
14712     x_return_status := fnd_api.g_ret_sts_error;
14713     fnd_msg_pub.count_and_get( p_count => x_msg_count
14714                                ,p_data  => x_msg_data );
14715     If (l_debug = 1) then
14716       log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
14717     End if;
14718     l_debug := NULL;
14719    --
14720    WHEN fnd_api.g_exc_unexpected_error THEN
14721     ROLLBACK TO ApplyRuleSP;
14722     FreeGlobals;
14723     x_return_status := fnd_api.g_ret_sts_unexp_error;
14724     fnd_msg_pub.count_and_get( p_count => x_msg_count
14725                               ,p_data  => x_msg_data );
14726     If (l_debug = 1) then
14727       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
14728     End if;
14729     l_debug := NULL;
14730    --
14731    WHEN OTHERS THEN
14732 
14733     ROLLBACK TO ApplyRuleSP;
14734     FreeGlobals;
14735     x_return_status := fnd_api.g_ret_sts_unexp_error;
14736     IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14737        fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14738     END IF;
14739     fnd_msg_pub.count_and_get( p_count => x_msg_count
14740                                ,p_data  => x_msg_data );
14741     If (l_debug = 1) then
14742       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
14743     End if;
14744     l_debug := NULL;
14745 
14746 END applydefloc;
14747 
14748 
14749 
14750   --
14751   --
14752   -- API name    : CheckSyntax
14753   -- Type        : Private
14754   -- Function    : This wrapper on Generate_Rule_Package is
14755   --     called from the WMS_RULES form
14756   -- Pre-reqs    : one record in WMS_RULES_B uniquely identified by parameter
14757   --                p_rule_id
14758   -- Input Parameters  :
14759   --   p_api_version       Standard Input Parameter
14760   --   p_init_msg_list     Standard Input Parameter
14761   --   p_validation_level  Standard Input Parameter
14762   --   p_rule_id           Identifier of the rule to check
14763   --
14764   -- Output Parameters  :
14765   --   x_return_status     Standard Output Parameter
14766   --   x_msg_count         Standard Output Parameter
14767   --   x_msg_data          Standard Output Parameter
14768   --
14769   -- Version     :
14770   --   Current version 1.0
14771   --
14772   -- Notes       : calls API's of WMS_RE_Common_PVT
14773   --
14774   PROCEDURE checksyntax(
14775     p_api_version      IN            NUMBER
14776   , p_init_msg_list    IN            VARCHAR2
14777   , p_validation_level IN            NUMBER
14778   , x_return_status    OUT NOCOPY    VARCHAR2
14779   , x_msg_count        OUT NOCOPY    NUMBER
14780   , x_msg_data         OUT NOCOPY    VARCHAR2
14781   , p_rule_id          IN            NUMBER
14782   ) IS
14783     PRAGMA AUTONOMOUS_TRANSACTION;
14784     -- API standard variables
14785     l_api_version CONSTANT NUMBER       := 1.0;
14786     l_api_name    CONSTANT VARCHAR2(30) := 'CheckSyntax';
14787   --
14788   --
14789   BEGIN
14790      --
14791     -- Standard call to check for call compatibility
14792     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
14793       RAISE fnd_api.g_exc_unexpected_error;
14794     END IF;
14795 
14796     -- Initialize message list if p_init_msg_list is set to TRUE
14797     IF fnd_api.to_boolean(p_init_msg_list) THEN
14798       fnd_msg_pub.initialize;
14799     END IF;
14800 
14801     --
14802     -- Initialize API return status to success
14803     x_return_status  := fnd_api.g_ret_sts_success;
14804     generaterulepackage(p_api_version, p_init_msg_list, p_validation_level, x_return_status, x_msg_count, x_msg_data, p_rule_id);
14805 
14806     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
14807       RAISE fnd_api.g_exc_unexpected_error;
14808     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
14809       RAISE fnd_api.g_exc_error;
14810     END IF;
14811 
14812   EXCEPTION
14813     WHEN fnd_api.g_exc_error THEN
14814       --
14815       x_return_status  := fnd_api.g_ret_sts_error;
14816       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14817     --
14818     WHEN fnd_api.g_exc_unexpected_error THEN
14819       x_return_status  := fnd_api.g_ret_sts_unexp_error;
14820       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14821     --
14822     WHEN OTHERS THEN
14823       freeglobals;
14824       x_return_status  := fnd_api.g_ret_sts_unexp_error;
14825 
14826       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14827         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14828       END IF;
14829 
14830       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14831   --
14832   END checksyntax;
14833 
14834   --
14835   -- API name    : Find_Rule
14836   -- Type        : Private
14837   -- Function    : find a rule by id
14838   -- Input Parameters  :
14839   --   p_api_version     Standard Input Parameter
14840   --   p_init_msg_list   Standard Input Parameter
14841   --   p_rule_id         Identifier of the rule
14842   --
14843   -- Output Parameters:
14844   --   x_return_status   Standard Output Parameter
14845   --   x_msg_count       Standard Output Parameter
14846   --   x_msg_data        Standard Output Parameter
14847   --   x_found           true if found ; else false
14848   --   x_rule_rec        info of the rule if found
14849 
14850   -- Version     :
14851   --   Current version 1.0
14852   --
14853   -- Notes       : calls API's of WMS_RE_Common_PVT
14854   --
14855   PROCEDURE find_rule(
14856     p_api_version   IN            NUMBER
14857   , p_init_msg_list IN            VARCHAR2
14858   , x_return_status OUT NOCOPY    VARCHAR2
14859   , x_msg_count     OUT NOCOPY    NUMBER
14860   , x_msg_data      OUT NOCOPY    VARCHAR2
14861   , p_rule_id       IN            NUMBER
14862   , x_found         OUT NOCOPY    BOOLEAN
14863   , x_rule_rec      OUT NOCOPY    rule_rec
14864   ) IS
14865     -- API standard variables
14866     l_api_version CONSTANT NUMBER       := 1.0;
14867     l_api_name    CONSTANT VARCHAR2(30) := 'Find_Rule';
14868 
14869     --
14870     CURSOR l_cur IS
14871       SELECT rule_id
14872            , organization_id
14873            , type_code
14874            , NAME
14875            , description
14876            , qty_function_parameter_id
14877            , enabled_flag
14878            , user_defined_flag
14879            , attribute_category
14880            , attribute1
14881            , attribute2
14882            , attribute3
14883            , attribute4
14884            , attribute5
14885            , attribute6
14886            , attribute7
14887            , attribute8
14888            , attribute9
14889            , attribute10
14890            , attribute11
14891            , attribute12
14892            , attribute13
14893            , attribute14
14894            , attribute15
14895         FROM wms_rules_vl
14896        WHERE rule_id = p_rule_id;
14897 
14898     --
14899     l_rule_rec             rule_rec;
14900   BEGIN
14901     OPEN l_cur;
14902     FETCH l_cur INTO l_rule_rec;
14903 
14904     --
14905     IF l_cur%NOTFOUND THEN
14906       x_found  := FALSE;
14907     ELSE
14908       x_found     := TRUE;
14909       x_rule_rec  := l_rule_rec;
14910     END IF;
14911 
14912     CLOSE l_cur;
14913   --
14914   EXCEPTION
14915     WHEN fnd_api.g_exc_error THEN
14916       x_return_status  := fnd_api.g_ret_sts_error;
14917       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14918     --
14919     WHEN fnd_api.g_exc_unexpected_error THEN
14920       x_return_status  := fnd_api.g_ret_sts_unexp_error;
14921       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14922     --
14923     WHEN OTHERS THEN
14924       x_return_status  := fnd_api.g_ret_sts_unexp_error;
14925 
14926       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14927         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14928       END IF;
14929 
14930       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14931   --
14932   END find_rule;
14933 
14934   --GetPackageName
14935   --
14936   --This function establishes the naming standard for the rule packages.
14937   --Currently, the naming standard is WMS_RULE_## , where ## is rule id
14938   PROCEDURE getpackagename(p_rule_id IN NUMBER, x_package_name OUT NOCOPY VARCHAR2) IS
14939   BEGIN
14940     x_package_name  := 'WMS_RULE_' || p_rule_id;
14941   END getpackagename;
14942 
14943   -- InitBuildPackage
14944   --    Called from GenerateRulePackage. Initializes
14945   -- the global variables needed to dynamically build the
14946   -- rule package.
14947   PROCEDURE initbuildpackage IS
14948   BEGIN
14949     g_build_package_row  := 0;
14950     g_build_package_tbl.DELETE;
14951   END initbuildpackage;
14952 
14953   --Build Package
14954   --This API takes a VARCHAR of undetermined length
14955   -- and breaks it up into varchars of length 255.  These
14956   -- smaller strings are stored in the g_build_package_tbl,
14957   -- and compose the sql statement to create the
14958   -- Rules package.
14959   PROCEDURE buildpackage(p_package_string IN VARCHAR2) IS
14960     l_cur_start      NUMBER;
14961     l_package_length NUMBER;
14962     l_num_chars      NUMBER := 255;
14963     l_row            NUMBER;
14964   BEGIN
14965     l_cur_start          := 1;
14966     -- get last filled row of table
14967     l_row                := g_build_package_row;
14968     l_package_length     := LENGTH(p_package_string);
14969     inv_log_util.trace( l_package_length ,'l_package_length' , 9);
14970     inv_log_util.trace( p_package_string ,'p_package_string' , 9);
14971     -- return if string is null
14972     IF l_package_length IS NULL
14973        OR l_package_length = 0 THEN
14974       RETURN;
14975     END IF;
14976 
14977     --Loop through string, reading off l_num_chars bytes at a time
14978     LOOP
14979       --When at end of varchar, exit loop;
14980       EXIT WHEN l_cur_start > l_package_length;
14981       l_row                       := l_row + 1;
14982       --Get substring from package_string
14983       g_build_package_tbl(l_row)  := SUBSTR(p_package_string, l_cur_start, l_num_chars);
14984       --Call build package to add row
14985       -- We may need to call this API for AOL standards.
14986       --ad_ddl.build_package(l_cur_string, l_row);
14987 
14988       --increment pointers
14989       l_cur_start                 := l_cur_start + l_num_chars;
14990 
14991       IF l_cur_start + l_num_chars > l_package_length THEN
14992         l_num_chars  := l_package_length - l_cur_start + 1;
14993       END IF;
14994     END LOOP;
14995 
14996     g_build_package_row  := l_row;
14997   END buildpackage;
14998 
14999   --CreatePackage
15000   -- This API calls dynamic SQL to build the package
15001   -- currently sitting in the g_build_package_tbl.
15002   --   p_package_body = TRUE if the package to be created is a body
15003   PROCEDURE createpackage(x_return_status OUT NOCOPY VARCHAR2, p_package_name IN VARCHAR2, p_package_body IN BOOLEAN) IS
15004     l_schema     VARCHAR2(30);
15005     l_status     VARCHAR2(1);
15006     l_industry   VARCHAR2(1);
15007     l_comp_error VARCHAR2(40);
15008     l_return     BOOLEAN;
15009     l_cursor     INTEGER;
15010     l_error      VARCHAR2(10);
15011 
15012     CURSOR c_package_status IS
15013       SELECT status
15014       FROM   user_objects
15015       WHERE  object_name = UPPER(p_package_name)
15016       AND    object_type='PACKAGE'
15017       AND    status <> 'VALID'
15018       AND    rownum = 1;
15019 
15020     CURSOR c_package_body_status IS
15021       SELECT status
15022       FROM   user_objects
15023       WHERE  object_name = UPPER(p_package_name)
15024       AND    object_type = 'PACKAGE BODY'
15025       AND    status <> 'VALID'
15026       AND    rownum = 1;
15027 
15028   BEGIN
15029     x_return_status  := fnd_api.g_ret_sts_unexp_error;
15030 
15031 	if ad_zd.get_edition('PATCH') is not null then
15032 	-- an online patch is in progress, return error
15033 	fnd_message.set_name('FND', 'AD_ZD_DISABLED_FEATURE');
15034 	-- bug#13565649 raise_application_error ('-20000', fnd_message.get);
15035 	fnd_msg_pub.ADD; -- bug#13565649
15036 	RAISE fnd_api.g_exc_error; -- bug#13565649
15037 	end if;
15038 
15039     --open cursor
15040     l_cursor         := DBMS_SQL.open_cursor;
15041     --parse cursor
15042     DBMS_SQL.parse(l_cursor, g_build_package_tbl, 1, g_build_package_row, FALSE, DBMS_SQL.native);
15043     --close cursor
15044     DBMS_SQL.close_cursor(l_cursor);
15045 
15046     /* We may need to call this API for AOL standards
15047        --get schema info
15048        l_return := fnd_installation.get_app_info(
15049        application_short_name => 'FND'
15050       ,status => l_status
15051       ,industry => l_industry
15052       ,oracle_schema => l_schema
15053            );
15054        IF l_return = FALSE THEN
15055       RAISE fnd_api.g_exc_error;
15056        END IF;
15057 
15058        --Call create package
15059        ad_ddl.create_plsql_object(
15060       applsys_schema => l_schema
15061            ,application_short_name => 'WMS'
15062            ,object_name => p_package_name
15063            ,lb      => 1
15064            ,ub      => g_build_package_row
15065            ,insert_newlines => 'FALSE'
15066            ,comp_error => l_comp_error
15067            );
15068 
15069        IF l_comp_error = 'TRUE' THEN
15070       RAISE fnd_api.g_exc_error;
15071        END IF;
15072     */
15073        --Check status, return error if package that was created
15074        --  is invalid
15075     IF p_package_body THEN
15076       OPEN c_package_body_status;
15077       FETCH c_package_body_status INTO l_error;
15078 
15079       IF c_package_body_status%FOUND THEN
15080         x_return_status  := fnd_api.g_ret_sts_unexp_error;
15081       ELSE
15082         x_return_status  := fnd_api.g_ret_sts_success;
15083       END IF;
15084 
15085       CLOSE c_package_body_status;
15086     ELSE
15087       OPEN c_package_status;
15088       FETCH c_package_status INTO l_error;
15089 
15090       IF c_package_status%FOUND THEN
15091         x_return_status  := fnd_api.g_ret_sts_unexp_error;
15092       ELSE
15093         x_return_status  := fnd_api.g_ret_sts_success;
15094       END IF;
15095 
15096       CLOSE c_package_status;
15097     END IF;
15098   EXCEPTION
15099     WHEN fnd_api.g_exc_error THEN --added for bug#13565649
15100       x_return_status  := fnd_api.g_ret_sts_error;
15101     WHEN OTHERS THEN
15102       x_return_status  := fnd_api.g_ret_sts_unexp_error;
15103   END createpackage;
15104 
15105   -- API name    : GenerateRulePackage
15106   -- Type        : Private
15107   -- Function    : generate a package for a rule that can be used in
15108   --      picking and put away
15109   -- Input Parameters  :
15110   --   p_api_version     Standard Input Parameter
15111   --   p_init_msg_list   Standard Input Parameter
15112   --   p_validation_level Standard Input Parameter
15113   --   p_rule_id         Identifier of the rule
15114   --
15115   -- Output Parameters:
15116   --   x_return_status   Standard Output Parameter
15117   --   x_msg_count       Standard Output Parameter
15118   --   x_msg_data        Standard Output Parameter
15119   --
15120   --  Called by the WMS Rules form (WMSRULEF.fmb), this function
15121   --  creates a package for the given rule.  The package has three
15122   --  functions, open_curs, fetch_one_row, and close_curs.  Open_curs
15123   --  opens the cursor used by picking/put away to find locations for
15124   --  transactions.  Fetch_one_row returns the next set of results from
15125   --  the cursor. Close_curs closes the cursor.  Much of this function is
15126   --  devoted to building the necessary cursors.  For picking, there are
15127   --  three cursors - one for detailing serials, one for serial controlled
15128   --  items when not detailing, and one for non-serial items.
15129   --  For put away, task type, label, and cost group rules,
15130   --  there is only one cursor
15131 
15132 
15133 
15134   PROCEDURE generaterulepackage(
15135     p_api_version      IN            NUMBER
15136   , p_init_msg_list    IN            VARCHAR2
15137   , p_validation_level IN            NUMBER
15138   , x_return_status    OUT NOCOPY    VARCHAR2
15139   , x_msg_count        OUT NOCOPY    NUMBER
15140   , x_msg_data         OUT NOCOPY    VARCHAR2
15141   , p_rule_id          IN            NUMBER
15142   ) IS
15143     -- API standard variables
15144     l_api_version CONSTANT NUMBER                                              := 1.0;
15145     l_api_name    CONSTANT VARCHAR2(30)                                        := 'GenerateRulePackage';
15146     --
15147     -- variables needed for dynamic SQL
15148     l_cursor               INTEGER;
15149     l_rows                 INTEGER;
15150     --
15151     -- rule dynamic SQL output variables
15152     l_revision             wms_transactions_temp.revision%TYPE;
15153     l_lot_number           wms_transactions_temp.lot_number%TYPE;
15154     l_lot_expiration_date  wms_transactions_temp.lot_expiration_date%TYPE;
15155     l_subinventory_code    wms_transactions_temp.from_subinventory_code%TYPE;
15156     l_locator_id           wms_transactions_temp.from_locator_id%TYPE;
15157     l_cost_group_id        wms_transactions_temp.from_cost_group_id%TYPE;
15158     l_possible_quantity    wms_transactions_temp.primary_quantity%TYPE;
15159     --
15160     -- other variables
15161     l_type_code            wms_rules_b.type_code%TYPE;
15162     l_package_name         VARCHAR2(128);
15163     l_pack_sql             VARCHAR2(32000);
15164     l_pack_body_sql        VARCHAR2(32000);
15165     --
15166     l_subinventory_where   VARCHAR2(100);
15167     l_locator_where        VARCHAR2(100);
15168     l_stmt                 LONG;
15169     l_allocation_mode_id   NUMBER;
15170 
15171     l_rest_sql             VARCHAR2(32000);
15172     -- cursor for validation of input parameters and pre-requisites
15173     CURSOR rule IS
15174       SELECT type_code
15175            , allocation_mode_id
15176         FROM wms_rules_b mpr
15177        WHERE mpr.rule_id = p_rule_id;
15178   --
15179   BEGIN
15180      --
15181     -- Standard call to check for call compatibility
15182     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
15183       RAISE fnd_api.g_exc_unexpected_error;
15184     END IF;
15185 
15186     --
15187     -- Initialize message list if p_init_msg_list is set to TRUE
15188     IF fnd_api.to_boolean(p_init_msg_list) THEN
15189       fnd_msg_pub.initialize;
15190     END IF;
15191 
15192     --
15193     -- Initialize API return status to success
15194     x_return_status  := fnd_api.g_ret_sts_success;
15195 
15196     log_procedure(l_api_name, 'start', 'Start GenerateRulePackage');
15197 
15198     -- end of debugging section
15199     --
15200     -- Validate input parameter, if validation level requires this
15201     IF p_validation_level <> fnd_api.g_valid_level_none THEN
15202       IF p_rule_id IS NULL
15203          OR p_rule_id = fnd_api.g_miss_num THEN
15204         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15205           fnd_message.set_name('WMS', 'WMS_RULE_ID_MISSING');
15206           log_error_msg(l_api_name, 'rule_id_missing');
15207           fnd_msg_pub.ADD;
15208         END IF;
15209 
15210         RAISE fnd_api.g_exc_error;
15211       END IF;
15212     END IF;
15213 
15214     --
15215     -- Get type code of the rule
15216     OPEN rule;
15217     FETCH rule INTO l_type_code, l_allocation_mode_id;
15218 
15219     IF rule%NOTFOUND THEN
15220       CLOSE rule;
15221       RAISE NO_DATA_FOUND;
15222     END IF;
15223 
15224     CLOSE rule;
15225     --
15226 
15227     -- clean up the global variables holding dynamic SQL text
15228     freeglobals;
15229 
15230     --
15231 
15232     /* For Task type rule (TTA) and label rule, calculate initial rule weight*/
15233     --  We don't want to pre-calculate rule weight any more, because
15234     --  of the uniqueness check on rule weight
15235     /*
15236     IF l_type_code = 3 OR l_type_code = 4 THEN
15237        calcRuleWeight(p_rule_id);
15238     END IF;
15239     */
15240 
15241 
15242 
15243     --For pick and put away rules, build the Base and Input portions
15244     -- of the SQL statement.  Not used in task type, label, and cost group
15245     -- rules
15246     IF l_type_code = 1
15247        OR l_type_code = 2 THEN
15248       -- Build the base part of the SQL statement
15249       buildbasesql(x_return_status, x_msg_count, x_msg_data, l_type_code, l_allocation_mode_id);
15250 
15251       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15252         RAISE fnd_api.g_exc_unexpected_error;
15253       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15254         RAISE fnd_api.g_exc_error;
15255       END IF;
15256 
15257       -- Build the input parameter dependent part of the SQL statement
15258       buildinputsql(x_return_status, x_msg_count, x_msg_data, l_type_code);
15259 
15260       --
15261       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15262         RAISE fnd_api.g_exc_unexpected_error;
15263       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15264         RAISE fnd_api.g_exc_error;
15265       END IF;
15266     END IF;
15267 
15268     -- Build the rule dependent part of the SQL statement.
15269     -- Happens for rules of all type
15270     buildrulesql(x_return_status, x_msg_count, x_msg_data, p_rule_id, l_type_code, l_allocation_mode_id);
15271 
15272     --
15273     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15274       RAISE fnd_api.g_exc_unexpected_error;
15275     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15276       RAISE fnd_api.g_exc_error;
15277     END IF;
15278 
15279     --
15280 
15281 
15282     --inv_pp_debug.send_long_to_pipe(g_base_from_serial);
15283 
15284     --build the sql portion of the cursor for lot-controlled items
15285     IF (l_type_code = 2) THEN --pick only
15286 
15287         g_rule_from  := g_rule_from || g_line_feed  || ' MTL_LOT_NUMBERS mlna , ' || g_line_feed;
15288 
15289       --inv_pp_debug.send_long_to_pipe(g_base_from_serial);
15290 
15291             IF (g_input_where IS NULL AND g_rule_where IS NULL) THEN
15292          g_rule_where := g_rule_where
15293                  ||'  mlna.ORGANIZATION_ID (+) = base.ORGANIZATION_ID ' || g_line_feed
15294          ||' and mlna.INVENTORY_ITEM_ID (+) = base.INVENTORY_ITEM_ID ' || g_line_feed
15295          ||' and mlna.LOT_NUMBER (+) = base.LOT_NUMBER ' || g_line_feed
15296          ||' and ( mlna.EXPIRATION_DATE is NULL OR mlna.EXPIRATION_DATE > sysdate OR wms_rule_pvt.g_allow_expired_lot_txn = ''Y'' ) ' ;
15297         ELSE
15298              g_rule_where := g_rule_where
15299                  ||' and mlna.ORGANIZATION_ID (+) = base.ORGANIZATION_ID ' || g_line_feed
15300          ||' and mlna.INVENTORY_ITEM_ID (+) = base.INVENTORY_ITEM_ID ' || g_line_feed
15301          ||' and mlna.LOT_NUMBER (+) = base.LOT_NUMBER ' || g_line_feed
15302          ||' and ( mlna.EXPIRATION_DATE is NULL OR mlna.EXPIRATION_DATE > sysdate OR wms_rule_pvt.g_allow_expired_lot_txn = ''Y'' ) ' ;
15303                  END IF;
15304 
15305           IF inv_pp_debug.is_debug_mode THEN
15306         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
15307         -- the message retrieved here since it is no longer on the stack
15308         inv_pp_debug.set_last_error_message(SQLERRM);
15309         inv_pp_debug.send_message_to_pipe(g_base_from_serial);
15310         inv_pp_debug.send_last_error_message;
15311       END IF;
15312 
15313           --inv_pp_debug.send_long_to_pipe(g_rule_from);
15314           --inv_pp_debug.send_long_to_pipe(g_rule_where);
15315       --g_rule_from
15316 
15317       g_stmt_serial         :=    'select '
15318                                || g_base_select
15319                                || g_rule_select_serial_new -- Added for Bug 13448337
15320                                || ' from '
15321                                || g_rule_from
15322                                || g_base_from_serial
15323                                || ' where '
15324                                || g_input_where
15325                                || g_rule_where
15326                                || ' group by '
15327                                || g_base_group_by
15328                                || g_rule_group_by_new; -- Added for Bug 13448337
15329 
15330       g_stmt_serial_validate :=    'select '
15331                                || g_base_select
15332                                || g_rule_select_serial_new -- Added for Bug 13448337
15333                                || ' from '
15334                                || g_rule_from
15335                                || g_base_from_serial_v
15336                                || ' where '
15337                                || g_input_where
15338                                || g_rule_where
15339                                || ' group by '
15340                                || g_base_group_by
15341                                || g_rule_group_by_new; -- Added for Bug 13448337
15342 
15343       g_stmt_serial_detail  :=    'select '
15344                                || g_base_select
15345                                || g_rule_select
15346                                || ' from '
15347                                || g_rule_from
15348                                || g_base_from_serial
15349                                || ' where '
15350                                || g_input_where
15351                                || g_rule_where;
15352 
15353      g_stmt_serial_detail_new  :=    'select '
15354                                || g_base_select
15355                                || g_rule_select
15356                                || ' from '
15357                                || g_rule_from
15358                                || g_base_from_serial_detail
15359                                || ' where '
15360                                || g_input_where
15361                                || g_rule_where;
15362 
15363       IF g_rule_order IS NOT NULL THEN
15364         g_stmt_serial           := g_stmt_serial || ' order by ' || g_rule_order_new; -- Added for Bug 13448337
15365         g_stmt_serial_validate  := g_stmt_serial_validate || ' order by ' || g_rule_order_new; -- Added for Bug 13448337
15366         g_stmt_serial_detail    := g_stmt_serial_detail || ' order by ' || g_rule_order;
15367         g_stmt_serial_detail_new := g_stmt_serial_detail_new || ' order by ' || g_rule_order;
15368       END IF;
15369     --    inv_pp_debug.send_long_to_pipe(g_stmt_serial);
15370     --    inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
15371 
15372     ELSE
15373       --if not pick, we don't need these cursors, so we set them to
15374       -- dummy values.  Used only so package will compile.
15375       g_stmt_serial          := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
15376       g_stmt_serial_validate := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
15377       g_stmt_serial_detail   := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
15378       g_stmt_serial_detail_new   := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
15379     END IF;
15380 
15381     --get the package name
15382     getpackagename(p_rule_id, l_package_name);
15383     -- Initialize the global variables needed to build package
15384     initbuildpackage;
15385 
15386     -- Generate Package for Label Rules
15387     IF (l_type_code = 4) THEN
15388       g_stmt           :=    'select count(*) '
15389                           || '  from '
15390                           || NVL(g_rule_from, 'WMS_LABEL_REQUESTS wlr')
15391                           || ' where wlr.label_request_id = p_label_request_id '
15392                           || g_rule_where;
15393       --assemble create package statement
15394       l_pack_sql       :=
15395              'CREATE OR REPLACE PACKAGE '
15396           || l_package_name
15397           || ' AS
15398                    procedure Get_label_format (
15399                    p_label_request_id           IN NUMBER,
15400                    x_return_status              OUT NOCOPY NUMBER);
15401 
15402                 end '
15403           || l_package_name
15404           || ';';
15405       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
15406       --open cursor
15407       --l_cursor := dbms_sql.open_cursor;
15408       --parse cursor
15409       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
15410       --close cursor
15411       --dbms_sql.close_cursor(l_cursor);
15412       buildpackage(l_pack_sql);
15413       --create the package spec
15414       createpackage(x_return_status, l_package_name, FALSE);
15415 
15416       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15417         RAISE fnd_api.g_exc_unexpected_error;
15418       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15419         RAISE fnd_api.g_exc_error;
15420       END IF;
15421 
15422       --re initialize global variables
15423       initbuildpackage;
15424       --inv_pp_debug.send_long_to_pipe(g_stmt);
15425 
15426       --assemble the dynamic package creation statment
15427       l_pack_body_sql  :=
15428              'CREATE OR REPLACE PACKAGE BODY '
15429           || l_package_name
15430           || ' AS
15431      PROCEDURE Get_Label_Format (
15432         p_label_request_id        IN NUMBER,
15433         x_return_status           OUT NOCOPY NUMBER) IS
15434 
15435         CURSOR get_label_rule_curs IS
15436      ';
15437       buildpackage(l_pack_body_sql);
15438       buildpackage(g_stmt);
15439       l_pack_body_sql  :=
15440              ';
15441 
15442   BEGIN
15443            x_return_status := 0;
15444            OPEN get_label_rule_curs;
15445            FETCH get_label_rule_curs into x_return_status;
15446            CLOSE get_label_rule_curs;
15447 
15448         END Get_Label_Format;
15449 
15450    END '
15451           || l_package_name
15452           || ';';
15453     ELSIF (l_type_code = 7) THEN
15454       -- Generate package for Operation Plan Rules
15455       g_stmt           :=    'select count(*) '
15456                           || '  from '
15457                           || NVL(g_rule_from, 'MTL_MATERIAL_TRANSACTIONS_TEMP mmtt')
15458                           || ' where mmtt.transaction_temp_id = p_pp_transaction_temp_id '
15459                           || g_rule_where;
15460       --assemble create package statement
15461       l_pack_sql       :=
15462              'CREATE OR REPLACE PACKAGE '
15463           || l_package_name
15464           || ' AS
15465                     procedure Get_OP (
15466                     p_pp_transaction_temp_id     IN NUMBER,
15467                     x_return_status              OUT NOCOPY NUMBER);
15468 
15469  end '
15470           || l_package_name
15471           || ';';
15472       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
15473       --open cursor
15474       --l_cursor := dbms_sql.open_cursor;
15475       --parse cursor
15476       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
15477       --close cursor
15478       --dbms_sql.close_cursor(l_cursor);
15479       buildpackage(l_pack_sql);
15480       createpackage(x_return_status, l_package_name, FALSE);
15481 
15482       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15483         RAISE fnd_api.g_exc_unexpected_error;
15484       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15485         RAISE fnd_api.g_exc_error;
15486       END IF;
15487 
15488       initbuildpackage;
15489       --inv_pp_debug.send_long_to_pipe(g_stmt);
15490 
15491       --assemble the dynamic package creation statment
15492       l_pack_body_sql  :=
15493              'CREATE OR REPLACE PACKAGE BODY '
15494           || l_package_name
15495           || ' AS
15496       PROCEDURE Get_OP (
15497           p_pp_transaction_temp_id IN  NUMBER,
15498           x_return_status          OUT NOCOPY NUMBER) IS
15499 
15500           CURSOR g_operation_plan_curs IS
15501        ';
15502       buildpackage(l_pack_body_sql);
15503       buildpackage(g_stmt);
15504       l_pack_body_sql  :=
15505              ';  -- for OP
15506 
15507        BEGIN
15508           x_return_status := 0;
15509           OPEN g_operation_plan_curs;
15510           FETCH g_operation_plan_curs  INTO x_return_status;
15511           CLOSE g_operation_plan_curs;
15512       END Get_OP;
15513 
15514 END '
15515           || l_package_name
15516           || ';';
15517     ELSIF (l_type_code = 3) THEN
15518       -- Generate package for Task Type Rules
15519       g_stmt           :=    'select count(*) '
15520                           || '  from '
15521                           || NVL(g_rule_from, 'MTL_MATERIAL_TRANSACTIONS_TEMP mmtt')
15522                           || ' where (MMTT.PARENT_LINE_ID = p_pp_transaction_temp_id or MMTT.TRANSACTION_TEMP_ID = p_pp_transaction_temp_id) '   -- Bug Fix 5560849, 8546026(High vol project)
15523                           || g_rule_where;
15524       --assemble create package statement
15525       l_pack_sql       :=
15526              'CREATE OR REPLACE PACKAGE '
15527           || l_package_name
15528           || ' AS
15529                 procedure Get_Task (
15530                    p_pp_transaction_temp_id     IN NUMBER,
15531                    x_return_status              OUT NOCOPY NUMBER);
15532 
15533  end '
15534           || l_package_name
15535           || ';';
15536       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
15537       --open cursor
15538       --l_cursor := dbms_sql.open_cursor;
15539       --parse cursor
15540       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
15541       --close cursor
15542       --dbms_sql.close_cursor(l_cursor);
15543       buildpackage(l_pack_sql);
15544       createpackage(x_return_status, l_package_name, FALSE);
15545 
15546       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15547         RAISE fnd_api.g_exc_unexpected_error;
15548       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15549         RAISE fnd_api.g_exc_error;
15550       END IF;
15551 
15552       initbuildpackage;
15553       --inv_pp_debug.send_long_to_pipe(g_stmt);
15554 
15555       --assemble the dynamic package creation statment
15556       l_pack_body_sql  :=
15557              'CREATE OR REPLACE PACKAGE BODY '
15558           || l_package_name
15559           || ' AS
15560      PROCEDURE Get_Task (
15561          p_pp_transaction_temp_id IN  NUMBER,
15562          x_return_status          OUT NOCOPY NUMBER) IS
15563 
15564          CURSOR g_task_type_curs IS
15565       ';
15566       buildpackage(l_pack_body_sql);
15567       buildpackage(g_stmt);
15568       l_pack_body_sql  :=
15569              ';  -- for TTA
15570 
15571       BEGIN
15572          x_return_status := 0;
15573          OPEN g_task_type_curs;
15574          FETCH g_task_type_curs INTO x_return_status;
15575          CLOSE g_task_type_curs;
15576       END Get_Task;
15577 
15578 END '
15579           || l_package_name
15580           || ';';
15581     -- Call CreatePackage after IF statement
15582 
15583     ELSIF (l_type_code = 5) THEN
15584       -- Build package for Cost Group Rules
15585       g_stmt           :=    'select count(*) '
15586                           || '  from '
15587                           || NVL(g_rule_from, 'WMS_COST_GROUPS_INPUT_V wcgiv')
15588                           || ' where wcgiv.line_id = g_line_id '
15589                           || g_rule_where;
15590       --assemble create package statement
15591       l_pack_sql       :=
15592              'CREATE OR REPLACE PACKAGE '
15593           || l_package_name
15594           || ' AS
15595 
15596                    PROCEDURE Get_CostGroup(
15597                        p_line_id        IN NUMBER,
15598                        x_return_status  OUT NOCOPY NUMBER);
15599 
15600     end '
15601           || l_package_name
15602           || ';';
15603       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
15604       --open cursor
15605       --l_cursor := dbms_sql.open_cursor;
15606       --parse cursor
15607       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
15608       --close cursor
15609       --dbms_sql.close_cursor(l_cursor);
15610       buildpackage(l_pack_sql);
15611       createpackage(x_return_status, l_package_name, FALSE);
15612 
15613       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15614         RAISE fnd_api.g_exc_unexpected_error;
15615       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15616         RAISE fnd_api.g_exc_error;
15617       END IF;
15618 
15619       initbuildpackage;
15620       --inv_pp_debug.send_long_to_pipe(g_stmt);
15621 
15622       --assemble the dynamic package creation statment
15623       l_pack_body_sql  :=
15624              'CREATE OR REPLACE PACKAGE BODY '
15625           || l_package_name
15626           || ' AS
15627          PROCEDURE Get_CostGroup(
15628                   p_line_id IN  NUMBER,
15629                   x_return_status OUT NOCOPY NUMBER) IS
15630 
15631            g_line_id  NUMBER;
15632 
15633                  CURSOR g_cursor_cost_group IS
15634                  ';
15635       buildpackage(l_pack_body_sql);
15636       buildpackage(g_stmt);
15637       l_pack_body_sql  :=
15638              ';
15639 
15640              BEGIN
15641                    g_line_id := p_line_id;
15642 
15643              OPEN g_cursor_cost_group;
15644 
15645              IF g_cursor_cost_group%isopen THEN
15646 
15647                 FETCH g_cursor_cost_group INTO
15648                 x_return_status;
15649 
15650              ELSE
15651                 x_return_status := 0;
15652              END IF;
15653 
15654              IF(g_cursor_cost_group%isopen) THEN
15655 
15656                 CLOSE g_cursor_cost_group;
15657 
15658              END IF;
15659 
15660               END Get_CostGroup;
15661   END '
15662           || l_package_name
15663           || ';';
15664     ELSIF l_type_code = 1 THEN
15665       -- Build for Put Away
15666       l_subinventory_where  := g_base_table_alias || '.subinventory_code = g_subinventory_code' || g_line_feed;
15667       l_locator_where       := g_base_table_alias || '.locator_id = g_locator_id' || g_line_feed;
15668       --build the sql portion of the cursor for non-serial-controlled items
15669        log_procedure(l_api_name, '=>', '*********************   200');
15670       g_stmt                :=
15671                               'select ' || g_base_select || ' from ' || g_rule_from || g_base_from || ' where ' || g_input_where || g_rule_where;
15672       --inv_pp_debug.send_long_to_pipe('g_base_from : ' || g_base_from);
15673 
15674      log_procedure(l_api_name, '=>', '*********************   199');
15675 
15676       --assemble create package statement
15677       l_pack_sql            :=
15678              'CREATE OR REPLACE PACKAGE '
15679           || l_package_name
15680           || ' AS
15681                    procedure open_curs (
15682                    p_cursor                     IN OUT NOCOPY WMS_RULE_PVT.CV_PUT_TYPE,
15683                    p_organization_id            IN NUMBER,
15684                    p_inventory_item_id          IN NUMBER,
15685        p_transaction_type_id        IN NUMBER,
15686                    p_subinventory_code          IN VARCHAR2,
15687                    p_locator_id                 IN NUMBER,
15688                    p_pp_transaction_temp_id     IN NUMBER,
15689        p_restrict_subs_code   IN NUMBER,
15690        p_restrict_locs_code   IN NUMBER,
15691        p_project_id     IN NUMBER,
15692        p_task_id      IN NUMBER,
15693                    x_result                     OUT NOCOPY NUMBER);
15694 
15695                    PROCEDURE fetch_one_row  (
15696                       p_cursor              IN  WMS_RULE_PVT.CV_PUT_TYPE,
15697                       x_subinventory_code   OUT NOCOPY VARCHAR2,
15698                       x_locator_id          OUT NOCOPY NUMBER,
15699                       x_project_id          OUT NOCOPY NUMBER,
15700                       x_task_id             OUT NOCOPY NUMBER,
15701                       x_return_status       OUT NOCOPY NUMBER);
15702 
15703                    PROCEDURE close_curs(p_cursor IN  WMS_RULE_PVT.CV_PUT_TYPE );
15704 
15705     end '
15706           || l_package_name
15707           || ';';
15708      log_procedure(l_api_name, '=>', '*********************   198');
15709       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
15710       --open cursor
15711       --l_cursor := dbms_sql.open_cursor;
15712       --parse cursor
15713       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
15714       --close cursor
15715       --dbms_sql.close_cursor(l_cursor);
15716       buildpackage(l_pack_sql);
15717       createpackage(x_return_status, l_package_name, FALSE);
15718 
15719       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15720         RAISE fnd_api.g_exc_unexpected_error;
15721       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15722         RAISE fnd_api.g_exc_error;
15723       END IF;
15724 
15725       initbuildpackage;
15726       --   inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
15727        --  inv_pp_debug.send_long_to_pipe(g_stmt_serial);
15728          --assemble the dynamic package creation statment
15729        log_procedure(l_api_name, '=>', '*********************  197');
15730       l_pack_body_sql       :=
15731              'CREATE OR REPLACE PACKAGE BODY '
15732           || l_package_name
15733           || ' AS
15734 
15735      PROCEDURE open_curs (
15736                 p_cursor                 IN OUT NOCOPY WMS_RULE_PVT.cv_put_type,
15737     p_organization_id   IN NUMBER,
15738     p_inventory_item_id   IN NUMBER,
15739     p_transaction_type_id   IN NUMBER,
15740     p_subinventory_code IN VARCHAR2,
15741     p_locator_id    IN NUMBER,
15742     p_pp_transaction_temp_id IN NUMBER,
15743     p_restrict_subs_code  IN NUMBER,
15744     p_restrict_locs_code  IN NUMBER,
15745     p_project_id    IN NUMBER,
15746     p_task_id   IN NUMBER,
15747     x_result    OUT NOCOPY NUMBER) IS
15748 
15749                 g_organization_id           NUMBER;
15750                 g_inventory_item_id         NUMBER;
15751                 g_transaction_type_id       NUMBER;
15752                 g_subinventory_code         VARCHAR2(10);
15753                 g_locator_id                NUMBER;
15754                 g_pp_transaction_temp_id    NUMBER;
15755                 g_restrict_subs_code        NUMBER;
15756                 g_restrict_locs_code        NUMBER;
15757     g_project_id                NUMBER;
15758     g_task_id                   NUMBER;
15759 
15760     BEGIN
15761     g_organization_id :=p_organization_id;
15762     g_inventory_item_id := p_inventory_item_id;
15763     g_transaction_type_id := p_transaction_type_id;
15764           IF p_subinventory_code = ''-9999'' THEN
15765       g_subinventory_code := NULL;
15766     ELSE
15767       g_subinventory_code := p_subinventory_code;
15768     END IF;
15769           IF p_locator_id = -9999 THEN
15770       g_locator_id := NULL;
15771     ELSE
15772       g_locator_id := p_locator_id;
15773     END IF;
15774     g_pp_transaction_temp_id := p_pp_transaction_temp_id;
15775     g_restrict_subs_code := p_restrict_subs_code;
15776     g_restrict_locs_code := p_restrict_locs_code;
15777     g_project_id := p_project_id;
15778     g_task_id := p_task_id;
15779 
15780     --if no restrictions
15781     IF g_restrict_subs_code = 2 AND
15782        g_restrict_locs_code = 2 THEN
15783 
15784       If g_subinventory_code IS NULL Then
15785       --if nothing passed, OPEN c_no_restrict_no_passed;
15786 
15787         OPEN p_cursor FOR ';
15788       buildpackage(l_pack_body_sql);
15789       --build correct statement
15790       log_procedure(l_api_name, '=>', '*********************   1961');
15791       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
15792       log_procedure(l_api_name, '=> Lenght ', length(l_stmt));
15793       l_rest_sql := l_stmt;
15794       log_procedure(l_api_name, '=> Lenght ', length(l_stmt));
15795       log_procedure(l_api_name, '=>_rest_sql', l_rest_sql);
15796       IF g_rule_order IS NOT NULL THEN
15797         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15798       END IF;
15799        log_procedure(l_api_name, '=>', '*********************   1963');
15800 
15801       buildpackage(l_stmt);
15802        log_procedure(l_api_name, '=>', '*********************   1964');
15803       l_pack_body_sql       :=
15804           ';
15805 
15806       Elsif g_locator_id IS NULL Then
15807 
15808       --if only subinventory passed , OPEN c_no_restrict_sub_passed;
15809 
15810         OPEN p_cursor FOR ';
15811       buildpackage(l_pack_body_sql);
15812       --build correct statement
15813        log_procedure(l_api_name, '=>', '*********************   195');
15814       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
15815       l_stmt                := l_stmt || ' and ' || l_subinventory_where;
15816        log_procedure(l_api_name, '=>', '*********************   194');
15817       IF g_rule_order IS NOT NULL THEN
15818         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15819       END IF;
15820 
15821       buildpackage(l_stmt);
15822       l_pack_body_sql       :=
15823           ';
15824 
15825       Else
15826       --if subinventory and locator passed, OPEN c_no_restrict_loc_passed;
15827         OPEN p_cursor FOR ';
15828       buildpackage(l_pack_body_sql);
15829       --build correct statement
15830       log_procedure(l_api_name, '=>', '*********************   99');
15831       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
15832       log_procedure(l_api_name, '=>', '*********************   98');
15833       l_stmt                := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
15834       log_procedure(l_api_name, '=>', '*********************   97');
15835       IF g_rule_order IS NOT NULL THEN
15836         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15837       END IF;
15838 
15839       buildpackage(l_stmt);
15840       l_pack_body_sql       :=
15841           ';
15842       End If;
15843     ELSIF g_restrict_locs_code = 2 THEN
15844       If g_subinventory_code IS NULL Then
15845       --if nothing passed, OPEN c_sub_restrict_no_passed;
15846         OPEN p_cursor FOR ';
15847       buildpackage(l_pack_body_sql);
15848       --build correct statement
15849       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
15850 
15851       IF g_rule_order IS NOT NULL THEN
15852         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15853       END IF;
15854 
15855       buildpackage(l_stmt);
15856       l_pack_body_sql       :=
15857           ';
15858       Elsif g_locator_id IS NULL Then
15859       --if only subinventory passed, OPEN c_sub_restrict_sub_passed;
15860          OPEN p_cursor FOR ';
15861       buildpackage(l_pack_body_sql);
15862       --build correct statement
15863       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
15864       l_stmt                := l_stmt || ' and ' || l_subinventory_where;
15865 
15866       IF g_rule_order IS NOT NULL THEN
15867         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15868       END IF;
15869 
15870       buildpackage(l_stmt);
15871       l_pack_body_sql       :=
15872               ';
15873 
15874       Else
15875       --if subinventory and locator passed, OPEN c_sub_restrict_loc_passed;
15876         OPEN p_cursor FOR ';
15877       buildpackage(l_pack_body_sql);
15878       --build correct statement
15879       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
15880       l_stmt                := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
15881 
15882       IF g_rule_order IS NOT NULL THEN
15883         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15884       END IF;
15885 
15886       buildpackage(l_stmt);
15887       l_pack_body_sql       :=
15888           ';
15889       End If;
15890     ELSE
15891       If g_subinventory_code IS NULL Then
15892       --if nothing passed, OPEN c_loc_restrict_no_passed;
15893         OPEN p_cursor FOR ';
15894       buildpackage(l_pack_body_sql);
15895       --build correct statement
15896       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
15897 
15898       IF g_rule_order IS NOT NULL THEN
15899         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15900       END IF;
15901 
15902       buildpackage(l_stmt);
15903       l_pack_body_sql       :=
15904           ';
15905 
15906       Elsif g_locator_id IS NULL Then
15907       --if only subinventory passed,OPEN c_loc_restrict_sub_passed;
15908         OPEN p_cursor FOR ';
15909       buildpackage(l_pack_body_sql);
15910       --build correct statement
15911       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
15912       l_stmt                := l_stmt || ' and ' || l_subinventory_where;
15913 
15914       IF g_rule_order IS NOT NULL THEN
15915         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15916       END IF;
15917 
15918       buildpackage(l_stmt);
15919       l_pack_body_sql       :=
15920               ';
15921 
15922       Else
15923       --if subinventory and locator passed, OPEN c_loc_restrict_loc_passed;
15924         OPEN p_cursor FOR ';
15925       buildpackage(l_pack_body_sql);
15926       --build correct statement
15927       l_stmt                := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
15928       l_stmt                := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
15929 
15930       IF g_rule_order IS NOT NULL THEN
15931         l_stmt  := l_stmt || ' order by ' || g_rule_order;
15932       END IF;
15933 
15934       buildpackage(l_stmt);
15935       l_pack_body_sql       :=
15936              ';
15937       End If;
15938     END IF;
15939 
15940     x_result :=1;
15941 
15942    END open_curs;
15943 
15944    PROCEDURE fetch_one_row(
15945                         p_cursor  IN WMS_RULE_PVT.cv_put_type,
15946       x_subinventory_code OUT NOCOPY VARCHAR2,
15947       x_locator_id OUT NOCOPY NUMBER,
15948       x_project_id OUT NOCOPY NUMBER,
15949       x_task_id OUT NOCOPY NUMBER,
15950       x_return_status OUT NOCOPY NUMBER) IS
15951 
15952 
15953    BEGIN
15954       if p_cursor%ISOPEN then
15955          FETCH p_cursor INTO
15956                x_subinventory_code, x_locator_id, x_project_id, x_task_id;
15957           IF p_cursor%FOUND THEN
15958                 x_return_status := 1;
15959           ELSE
15960                x_return_status := 0;
15961           END IF;
15962       else
15963               x_return_status := 0;
15964       end if;
15965 
15966    END fetch_one_row;
15967 
15968    PROCEDURE close_curs( p_cursor  IN WMS_RULE_PVT.cv_put_type) IS
15969    BEGIN
15970        if p_cursor%ISOPEN then
15971            CLOSE p_cursor;
15972          end if;
15973    END close_curs;
15974 
15975    END '
15976           || l_package_name
15977           || ';';
15978     ELSE
15979       -- Build for Pick
15980       IF l_allocation_mode_id IN (1, 2) THEN
15981         --build the sql portion of the cursor for non-serial-controlled items
15982         g_stmt  :=
15983              'select ' || g_base_select || g_rule_select || ' from ' || g_rule_from || g_base_from || ' where ' || g_input_where || g_rule_where;
15984       --Ensures that we only get one rec per rev/lot/sub/loc, grouping
15985       -- all recs together regardless of LPN
15986       -- l_allocation_mode_id IN (3,4)
15987       ELSE
15988         g_stmt  :=    'select '
15989                    || g_base_select
15990                    || g_rule_select_serial
15991                    || ' from '
15992                    || g_rule_from
15993                    || g_base_from
15994                    || ' where '
15995                    || g_input_where
15996                    || g_rule_where
15997                    || 'group by '
15998                    || g_base_group_by
15999                    || g_rule_group_by;
16000       END IF;
16001 
16002       --inv_pp_debug.send_long_to_pipe('g_base_from : ' || g_base_from);
16003 
16004       IF g_rule_order IS NOT NULL THEN
16005         g_stmt  := g_stmt || ' order by ' || g_rule_order;
16006       END IF;
16007 
16008       --assemble create package statement
16009       l_pack_sql       :=
16010              'CREATE OR REPLACE PACKAGE '
16011           || l_package_name
16012           || ' AS
16013                    procedure open_curs (
16014                    p_cursor            IN OUT NOCOPY WMS_RULE_PVT.cv_pick_type,
16015                    p_organization_id            IN NUMBER,
16016                    p_inventory_item_id          IN NUMBER,
16017                    p_transaction_type_id        IN NUMBER,
16018                    p_revision                   IN VARCHAR2,
16019                    p_lot_number                 IN VARCHAR2,
16020                    p_subinventory_code          IN VARCHAR2,
16021                    p_locator_id                 IN NUMBER,
16022                    p_cost_group_id          IN NUMBER,
16023                    p_pp_transaction_temp_id     IN NUMBER,
16024                    p_serial_controlled    IN NUMBER,
16025                    p_detail_serial    IN NUMBER,
16026                    p_detail_any_serial    IN NUMBER,
16027                    p_from_serial_number   IN VARCHAR2,
16028                    p_to_serial_number   IN VARCHAR2,
16029                    p_unit_number    IN VARCHAR2,
16030                    p_lpn_id     IN NUMBER,
16031                    p_project_id     IN NUMBER,
16032                    p_task_id      IN NUMBER,
16033                    x_result                     OUT NOCOPY NUMBER);
16034 
16035                    PROCEDURE fetch_one_row  (
16036                       p_cursor                 IN WMS_RULE_PVT.cv_pick_type,
16037                       x_revision               OUT NOCOPY VARCHAR2,
16038                       x_lot_number             OUT NOCOPY VARCHAR2,
16039                       x_lot_expiration_date    OUT NOCOPY DATE,
16040                       x_subinventory_code      OUT NOCOPY VARCHAR2,
16041                       x_locator_id             OUT NOCOPY NUMBER,
16042                       x_cost_group_id          OUT NOCOPY NUMBER,
16043                       x_uom_code               OUT NOCOPY VARCHAR2,
16044                       x_lpn_id                 OUT NOCOPY NUMBER,
16045                       x_serial_number          OUT NOCOPY VARCHAR2,
16046                       x_possible_quantity      OUT NOCOPY NUMBER,
16047                       x_sec_possible_quantity  OUT NOCOPY NUMBER,
16048                       x_grade_code             OUT NOCOPY VARCHAR2,
16049                       x_consist_string         OUT NOCOPY VARCHAR2,
16050                       x_order_by_string        OUT NOCOPY VARCHAR2,
16051                       x_return_status          OUT NOCOPY NUMBER);
16052 
16053             PROCEDURE close_curs( p_cursor  IN WMS_RULE_PVT.cv_pick_type);
16054 
16055             PROCEDURE fetch_available_rows  (
16056                       p_cursor              IN WMS_RULE_PVT.cv_pick_type,
16057                       x_return_status       OUT NOCOPY NUMBER);
16058 
16059 
16060 
16061     end '
16062           || l_package_name
16063           || ';';
16064       --inv_pp_debug.send_long_to_pipe(l_pack_sql);
16065       --open cursor
16066       --l_cursor := dbms_sql.open_cursor;
16067       --parse cursor
16068       --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
16069       --close cursor
16070       --dbms_sql.close_cursor(l_cursor);
16071       buildpackage(l_pack_sql);
16072       createpackage(x_return_status, l_package_name, FALSE);
16073 
16074       IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
16075         RAISE fnd_api.g_exc_unexpected_error;
16076       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
16077         RAISE fnd_api.g_exc_error;
16078       END IF;
16079 
16080       initbuildpackage;
16081       --   inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
16082        --  inv_pp_debug.send_long_to_pipe(g_stmt_serial);
16083          --assemble the dynamic package creation statment
16084 
16085       l_pack_body_sql  :=
16086              'CREATE OR REPLACE PACKAGE BODY '
16087           || l_package_name
16088           || ' AS
16089 
16090      PROCEDURE open_curs
16091         (
16092                 p_cursor                IN OUT NOCOPY WMS_RULE_PVT.cv_pick_type,
16093                 p_organization_id   IN NUMBER,
16094                 p_inventory_item_id   IN NUMBER,
16095                 p_transaction_type_id   IN NUMBER,
16096                 p_revision    IN VARCHAR2,
16097                 p_lot_number    IN VARCHAR2,
16098                 p_subinventory_code IN VARCHAR2,
16099                 p_locator_id    IN NUMBER,
16100                 p_cost_group_id   IN NUMBER,
16101                 p_pp_transaction_temp_id IN NUMBER,
16102                 p_serial_controlled IN NUMBER,
16103                 p_detail_serial   IN NUMBER,
16104                 p_detail_any_serial IN NUMBER,
16105                 p_from_serial_number  IN VARCHAR2,
16106                 p_to_serial_number  IN VARCHAR2,
16107                 p_unit_number   IN VARCHAR2,
16108                 p_lpn_id    IN NUMBER,
16109                 p_project_id    IN NUMBER,
16110                 p_task_id   IN NUMBER,
16111                 x_result    OUT NOCOPY NUMBER
16112         ) IS
16113                 g_organization_id             NUMBER;
16114                 g_inventory_item_id           NUMBER;
16115                 g_transaction_type_id         NUMBER;
16116                 g_revision                    VARCHAR2(3);
16117                 g_lot_number                  VARCHAR2(80);
16118                 g_subinventory_code           VARCHAR2(10);
16119                 g_locator_id                  NUMBER;
16120                 g_cost_group_id               NUMBER;
16121                 g_pp_transaction_temp_id      NUMBER;
16122                 g_serial_control              NUMBER;
16123                 g_detail_serial               NUMBER;
16124                 g_detail_any_serial           NUMBER;
16125                 g_from_serial_number          VARCHAR2(30);
16126                 g_to_serial_number            VARCHAR2(30);
16127                 g_unit_number                 VARCHAR2(30);
16128                 g_lpn_id                      NUMBER;
16129                 g_project_id                  NUMBER;
16130                 g_task_id                     NUMBER;
16131                                 l_allow_expired_lot_txn       NUMBER := 0;
16132 
16133 
16134     BEGIN
16135       g_organization_id :=p_organization_id;
16136       g_inventory_item_id := p_inventory_item_id;
16137       g_transaction_type_id := p_transaction_type_id;
16138       g_revision := p_revision;
16139       g_lot_number := p_lot_number;
16140       g_subinventory_code :=p_subinventory_code;
16141       g_locator_id := p_locator_id;
16142       g_cost_group_id := p_cost_group_id;
16143       g_pp_transaction_temp_id := p_pp_transaction_temp_id;
16144       g_serial_control:= p_serial_controlled;
16145       g_detail_serial := p_detail_serial;
16146       g_detail_any_serial := p_detail_any_serial;
16147       g_from_serial_number := p_from_serial_number;
16148       g_to_serial_number := p_to_serial_number;
16149       g_unit_number := p_unit_number;
16150       g_lpn_id := p_lpn_id;
16151       g_project_id := p_project_id;
16152       g_task_id := p_task_id;
16153 
16154      IF (g_serial_control = 1)    AND (g_detail_serial in (1,2)) THEN
16155          OPEN p_cursor FOR ';
16156               buildpackage(l_pack_body_sql);
16157               buildpackage(g_stmt_serial_detail_new);
16158               l_pack_body_sql  := ';
16159      Elsif (g_serial_control = 1) AND (g_detail_serial = 3) THEN
16160         OPEN p_cursor FOR ';
16161              buildpackage(l_pack_body_sql);
16162              buildpackage(g_stmt_serial_validate);
16163              l_pack_body_sql  := ';
16164      Elsif (g_serial_control = 1) AND  (g_detail_serial = 4) THEN
16165            OPEN p_cursor FOR ';
16166                 buildpackage(l_pack_body_sql);
16167                 buildpackage(g_stmt_serial);
16168                 l_pack_body_sql  := ';
16169 
16170      Elsif ((g_serial_control <> 1) OR (g_detail_serial = 0)) THEN
16171        OPEN p_cursor FOR ';
16172         buildpackage(l_pack_body_sql);
16173         buildpackage(g_stmt);
16174         l_pack_body_sql  :=
16175              ';
16176      END IF;
16177 
16178     x_result :=1;
16179 
16180    END open_curs;
16181 
16182    PROCEDURE fetch_one_row(
16183                         p_cursor   IN WMS_RULE_PVT.cv_pick_type,
16184                         x_revision OUT NOCOPY VARCHAR2,
16185                         x_lot_number OUT NOCOPY VARCHAR2,
16186                         x_lot_expiration_date OUT NOCOPY DATE,
16187                         x_subinventory_code OUT NOCOPY VARCHAR2,
16188                         x_locator_id OUT NOCOPY NUMBER,
16189                         x_cost_group_id OUT NOCOPY NUMBER,
16190                         x_uom_code OUT NOCOPY VARCHAR2,
16191                         x_lpn_id OUT NOCOPY NUMBER,
16192                         x_serial_number OUT NOCOPY VARCHAR2,
16193                         x_possible_quantity OUT NOCOPY NUMBER,
16194                         x_sec_possible_quantity  OUT NOCOPY NUMBER,
16195                         x_grade_code             OUT NOCOPY VARCHAR2,
16196                         x_consist_string  OUT NOCOPY VARCHAR2,
16197                         x_order_by_string OUT NOCOPY VARCHAR2,
16198                         x_return_status OUT NOCOPY NUMBER) IS
16199 
16200 
16201    BEGIN
16202            IF (p_cursor%ISOPEN) THEN
16203 
16204                FETCH p_cursor INTO
16205                x_revision
16206                , x_lot_number
16207                , x_lot_expiration_date
16208                , x_subinventory_code
16209                , x_locator_id
16210                , x_cost_group_id
16211                , x_uom_code
16212                , x_lpn_id
16213                , x_serial_number
16214                , x_possible_quantity
16215                , x_sec_possible_quantity
16216                , x_grade_code
16217                , x_consist_string
16218                , x_order_by_string;
16219                IF p_cursor%FOUND THEN
16220                   x_return_status :=1;
16221                ELSE
16222                   x_return_status :=0;
16223                END IF;
16224             ELSE
16225                x_return_status:=0;
16226             END IF;
16227 
16228 
16229    END fetch_one_row;
16230 
16231    PROCEDURE close_curs( p_cursor IN WMS_RULE_PVT.cv_pick_type) IS
16232    BEGIN
16233         if (p_cursor%ISOPEN) THEN
16234             CLOSE p_cursor;
16235         END IF;
16236    END close_curs;
16237 
16238    -- LG convergence new procedure for the new manual picking select screen
16239    PROCEDURE fetch_available_rows(
16240       p_cursor   IN WMS_RULE_PVT.cv_pick_type,
16241       x_return_status OUT NOCOPY NUMBER) IS
16242 
16243     /* Fix for Bug#8360804 . Added temp variable of type available_inventory_tbl */
16244 
16245      l_available_inv_tbl WMS_SEARCH_ORDER_GLOBALS_PVT.available_inventory_tbl;
16246      l_count number ;
16247 
16248 
16249    BEGIN
16250            IF (p_cursor%ISOPEN) THEN
16251 
16252               /* Fix for bug#8360804. Collect into temp variable and then add it to g_available_inv_tbl */
16253 
16254                FETCH p_cursor bulk collect INTO l_available_inv_tbl;
16255 
16256                IF p_cursor%FOUND THEN
16257                   x_return_status :=1;
16258                ELSE
16259                   x_return_status :=0;
16260                END IF;
16261 
16262                IF (WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.exists(1)) THEN
16263 
16264                   l_count := WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.LAST ;
16265 
16266                   FOR i in l_available_inv_tbl.FIRST..l_available_inv_tbl.LAST LOOP
16267                     l_count := l_count + 1 ;
16268                     WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(l_count) := l_available_inv_tbl(i) ;
16269                   END LOOP ;
16270 
16271                ELSE
16272                    WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl := l_available_inv_tbl ;
16273                END IF ;
16274             ELSE
16275                x_return_status:=0;
16276             END IF;
16277 
16278 
16279    END fetch_available_rows;
16280 
16281    -- end LG convergence
16282 
16283    END '
16284           || l_package_name
16285           || ';';
16286     END IF; -- type_code = 4
16287 
16288     -- Add last part of SQL to the global table, then call
16289     --  CreatePackage to generate package body
16290     buildpackage(l_pack_body_sql);
16291     createpackage(x_return_status, l_package_name, TRUE);
16292 
16293     IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
16294       RAISE fnd_api.g_exc_unexpected_error;
16295     ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
16296       RAISE fnd_api.g_exc_error;
16297     END IF;
16298 
16299     initbuildpackage;
16300      -- inv_pp_debug.send_long_to_pipe(l_pack_body_sql);
16301     /*
16302       --open cursor
16303 
16304       l_cursor := dbms_sql.open_cursor;
16305       dbms_out
16306       --parse cursor
16307 
16308       dbms_sql.parse(l_cursor, l_pack_body_sql, dbms_sql.native);
16309 
16310       --close cursor
16311       dbms_sql.close_cursor(l_cursor);
16312     */
16313 
16314 
16315 
16316     --
16317     -- clean up everything again
16318     freeglobals;
16319 
16320     --
16321 
16322     /*
16323     IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_success) THEN
16324         fnd_message.set_name('WMS','WMS_SYNTAX_CHECK_SUCCESS');
16325         fnd_msg_pub.add;
16326       END IF;
16327     */ --
16328     -- end of debugging section
16329     log_procedure(l_api_name, 'end', 'End GenerateRulePackage');
16330   --
16331   EXCEPTION
16332     WHEN fnd_api.g_exc_error THEN
16333       --
16334       -- debugging portion
16335       -- can be commented ut for final code
16336       IF inv_pp_debug.is_debug_mode THEN
16337         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
16338         -- the message retrieved here since it is no longer on the stack
16339         inv_pp_debug.set_last_error_message(SQLERRM);
16340         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
16341         inv_pp_debug.send_last_error_message;
16342       END IF;
16343 
16344       -- end of debugging section
16345       --
16346       IF DBMS_SQL.is_open(l_cursor) THEN
16347         DBMS_SQL.close_cursor(l_cursor);
16348       END IF;
16349 
16350       freeglobals;
16351       x_return_status  := fnd_api.g_ret_sts_error;
16352       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16353       log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
16354     --
16355     WHEN fnd_api.g_exc_unexpected_error THEN
16356       --
16357       -- debugging portion
16358       -- can be commented ut for final code
16359       IF inv_pp_debug.is_debug_mode THEN
16360         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
16361         -- the message retrieved here since it is no longer on the stack
16362         inv_pp_debug.set_last_error_message(SQLERRM);
16363         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
16364         inv_pp_debug.send_last_error_message;
16365       END IF;
16366 
16367       -- end of debugging section
16368       --
16369       IF DBMS_SQL.is_open(l_cursor) THEN
16370         DBMS_SQL.close_cursor(l_cursor);
16371       END IF;
16372 
16373       freeglobals;
16374       fnd_message.set_name('WMS', 'WMS_PACKAGE_GEN_FAILED');
16375       fnd_msg_pub.ADD;
16376       x_return_status  := fnd_api.g_ret_sts_unexp_error;
16377       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16378       log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
16379     --
16380     WHEN OTHERS THEN
16381       --
16382       -- debugging portion
16383       -- can be commented ut for final code
16384       IF inv_pp_debug.is_debug_mode THEN
16385         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
16386         -- the message retrieved here since it is no longer on the stack
16387         inv_pp_debug.set_last_error_message(SQLERRM);
16388         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
16389         inv_pp_debug.send_last_error_message;
16390       END IF;
16391 
16392       -- end of debugging section
16393       --
16394       IF rule%ISOPEN THEN
16395         CLOSE rule;
16396       END IF;
16397 
16398       IF DBMS_SQL.is_open(l_cursor) THEN
16399         DBMS_SQL.close_cursor(l_cursor);
16400       END IF;
16401 
16402       freeglobals;
16403       fnd_message.set_name('WMS', 'WMS_PACKAGE_GEN_FAILED');
16404       fnd_msg_pub.ADD;
16405       x_return_status  := fnd_api.g_ret_sts_unexp_error;
16406 
16407       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16408         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
16409       END IF;
16410 
16411       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16412       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
16413   --
16414   END generaterulepackage;
16415 
16416   -- API name    : Assign_operation_plans
16417   -- Type        : Private
16418   -- Function    : Assign operation plans to records in MMTT
16419   -- Input Parameters  :
16420   --
16421   -- Output Parameters:
16422   -- Version     :
16423   --   Current version 1.0
16424   --
16425   -- Notes       : calls Assign_operation_plan(p_task_id NUMBER)
16426   --
16427   -- This procedure loops through mtl_material_transactions_temp table, assign
16428   -- user defined operation plans to tasks that have not been assigned a operation_plan
16429   -- for the given Move Order Header.
16430   --
16431 
16432 
16433   PROCEDURE assign_operation_plans(
16434     p_api_version          IN            NUMBER
16435   , p_init_msg_list        IN            VARCHAR2
16436   , p_commit               IN            VARCHAR2
16437   , p_validation_level     IN            NUMBER
16438   , x_return_status        OUT NOCOPY    VARCHAR2
16439   , x_msg_count            OUT NOCOPY    NUMBER
16440   , x_msg_data             OUT NOCOPY    VARCHAR2
16441   , p_move_order_header_id IN            NUMBER
16442   ) IS
16443     CURSOR c_tasks IS
16444       SELECT mmtt.transaction_temp_id
16445         FROM mtl_material_transactions_temp mmtt, mtl_txn_request_lines mol
16446        WHERE mmtt.operation_plan_id IS NULL
16447          AND mmtt.move_order_line_id = mol.line_id
16448          AND mol.header_id = p_move_order_header_id;
16449 
16450     l_task_id       NUMBER;
16451     l_return_status VARCHAR2(1);
16452     l_msg_count     NUMBER;
16453     l_msg_data      VARCHAR2(2000);
16454     l_api_name      VARCHAR2(30)   := 'assign_operation_plans';
16455     l_count         NUMBER;
16456   BEGIN
16457     -- Initialize API return status to success
16458     x_return_status  := fnd_api.g_ret_sts_success;
16459 
16460     -- Bug# 4587423
16461     -- See if there are any enabled rules for Operation Plan Selection.
16462     l_count := 0;
16463     BEGIN
16464        SELECT 1 INTO l_count
16465          FROM dual
16466          WHERE EXISTS (SELECT 1 FROM wms_rules_b rules
16467                        WHERE  rules.type_code = 7
16468                        AND    rules.enabled_flag = 'Y'
16469                        AND    (organization_id = -1
16470                                OR organization_id IN (SELECT mmtt.organization_id
16471                                                       FROM mtl_material_transactions_temp mmtt,
16472                                                       mtl_txn_request_lines mol
16473                                                       WHERE mmtt.operation_plan_id IS NULL /*bug9128227*/
16474                                                       AND mmtt.move_order_line_id = mol.line_id
16475                                                       AND mol.header_id = p_move_order_header_id)));
16476     EXCEPTION
16477        WHEN OTHERS THEN
16478           l_count := 0;
16479     END;
16480 
16481     -- Bug# 4587423
16482     -- If there is at least one operation plan selection rule enabled,
16483     -- go through the existing logic.
16484     IF (l_count > 0) THEN
16485        OPEN c_tasks;
16486        LOOP
16487           FETCH c_tasks INTO l_task_id;
16488           EXIT WHEN c_tasks%NOTFOUND;
16489 
16490           if (inv_control.g_current_release_level >= inv_release.g_j_release_level
16491               and  wms_ui_tasks_apis.g_wms_patch_level >= wms_ui_tasks_apis.g_patchset_j)
16492             then
16493              -- ### Outbound for patchset 'J'
16494              wms_rule_pvt_ext_psetj.assign_operation_plan_psetj
16495                (p_api_version      => 1.0,
16496                 x_return_status    => l_return_status,
16497                 x_msg_count        => l_msg_count,
16498                 x_msg_data         => l_msg_data,
16499                 p_task_id          => l_task_id
16500                 );
16501            elsif (inv_control.g_current_release_level < inv_release.g_j_release_level
16502                   or wms_ui_tasks_apis.g_wms_patch_level < wms_ui_tasks_apis.g_patchset_j)
16503              then
16504              -- ### Outbound for patchset 'I'
16505              assign_operation_plan
16506                (p_api_version      => 1.0,
16507                 p_task_id          => l_task_id,
16508                 x_return_status    => l_return_status,
16509                 x_msg_count        => l_msg_count,
16510                 x_msg_data         => l_msg_data
16511                 );
16512           end if;
16513 
16514           IF l_return_status <> fnd_api.g_ret_sts_success THEN
16515              x_return_status  := fnd_api.g_ret_sts_error;
16516           END IF;
16517        END LOOP;
16518 
16519        CLOSE c_tasks;
16520      ELSE
16521        -- Bug# 4587423
16522        -- No rules exist for outbound operaton plan selection.
16523        -- Just stamp the org default outbound operation plan or the default
16524        -- "Locator and LPN Based Consolidation in Staging Lane" seeded outbound operation plan
16525        -- for the MMTT records associated with the move order header.
16526        UPDATE mtl_material_transactions_temp mmtt
16527          SET mmtt.operation_plan_id = (SELECT NVL(default_pick_op_plan_id, 1)
16528                                        FROM mtl_parameters mp
16529                                        WHERE mp.organization_id = mmtt.organization_id)
16530          WHERE mmtt.operation_plan_id IS NULL
16531            AND mmtt.move_order_line_id IN (SELECT line_id
16532                                            FROM mtl_txn_request_lines mol
16533                                            WHERE mol.header_id = p_move_order_header_id)
16534            AND mmtt.transaction_source_type_id in (2, 8);
16535     END IF;
16536 
16537   EXCEPTION
16538      WHEN OTHERS THEN
16539         x_return_status  := fnd_api.g_ret_sts_unexp_error;
16540   END assign_operation_plans;
16541 
16542   --
16543   -- API name    : Assign Operation Plan
16544   -- Type        : Private
16545   -- Function    : Assign Operation plan to a specific record in MMTT
16546   -- Input Parameters  :
16547   --           p_task_id NUMBER
16548   --
16549   -- Output Parameters:
16550   -- Version     :
16551   --   Current version 1.0
16552   --
16553   -- Notes       :
16554   --
16555   -- This procedure assign user defined operation plan to a specific task in
16556   -- mtl_material_transactions_temp. Operation plan is implemeted by WMS rules.
16557   -- This procedure calls the rule package created for operation plan rules to check
16558   -- which operation plan rule actually matches the task in question.
16559 
16560 
16561   PROCEDURE assign_operation_plan(
16562     p_api_version      IN            NUMBER
16563   , p_init_msg_list    IN            VARCHAR2
16564   , p_commit           IN            VARCHAR2
16565   , p_validation_level IN            NUMBER
16566   , x_return_status    OUT NOCOPY    VARCHAR2
16567   , x_msg_count        OUT NOCOPY    NUMBER
16568   , x_msg_data         OUT NOCOPY    VARCHAR2
16569   , p_task_id          IN            NUMBER
16570   ) IS
16571     l_rule_id              NUMBER;
16572     l_pack_exists          NUMBER;
16573     l_package_name         VARCHAR2(30);
16574     l_count                NUMBER;
16575     l_return_status        NUMBER;
16576     l_found                BOOLEAN      := FALSE;
16577     l_organization_id      NUMBER;
16578     l_wms_task_type        NUMBER;
16579     l_operation_plan_id    NUMBER;
16580     l_api_version CONSTANT NUMBER       := 1.0;
16581     l_api_name    CONSTANT VARCHAR2(30) := 'Assign_operation_plan';
16582 
16583     -- Cursor for task type rule loop
16584     -- Only rules with the same WMS system task type as the task
16585     -- will be selected
16586     -- Rules are ordered by rule weight and creation date
16587 
16588     CURSOR c_rules IS
16589       SELECT   rules.rule_id
16590              , mmtt.organization_id
16591              , mmtt.wms_task_type
16592              , rules.type_hdr_id
16593           FROM wms_rules_b rules, wms_op_plans_b wop, mtl_material_transactions_temp mmtt
16594         WHERE rules.type_code = 7
16595         AND rules.enabled_flag = 'Y'
16596         AND rules.type_hdr_id = wop.operation_plan_id
16597         AND wop.system_task_type = NVL(mmtt.wms_task_type, wop.system_task_type)
16598         --AND    mmtt.transaction_source_type_id <> 5 -- exclude wip issue tasks
16599         AND    mmtt.transaction_source_type_id IN (2, 8) --restrict to sales order and internal order mmtts only
16600         AND mmtt.transaction_temp_id = p_task_id
16601         AND rules.organization_id IN (mmtt.organization_id, -1)
16602         AND NVL(wop.organization_id, mmtt.organization_id) = mmtt.organization_id
16603            AND wop.enabled_flag = 'Y'
16604       ORDER BY rules.rule_weight DESC, rules.creation_date;
16605 
16606     -- Bug# 4587423: If a default outbound operation plan is not defined for the org,
16607     -- default to 1 (Locator and LPN Based Consolidation in Staging Lane)
16608     CURSOR c_default_operation_plan IS
16609       SELECT NVL(default_pick_op_plan_id, 1)
16610         FROM mtl_parameters
16611        WHERE organization_id = l_organization_id;
16612 
16613        l_rule_counter           INTEGER;
16614   BEGIN
16615     SAVEPOINT assign_operation_plan_sp;
16616 
16617     -- Standard call to check for call compatibility
16618     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
16619       RAISE fnd_api.g_exc_unexpected_error;
16620     END IF;
16621 
16622     -- Initialize message list if p_init_msg_list is set to TRUE
16623     IF fnd_api.to_boolean(p_init_msg_list) THEN
16624       fnd_msg_pub.initialize;
16625     END IF;
16626 
16627     --
16628     -- Initialize API return status to success
16629     x_return_status  := fnd_api.g_ret_sts_success;
16630 
16631     -- Validate input parameters and pre-requisites, if validation level
16632     -- requires this
16633     IF p_validation_level <> fnd_api.g_valid_level_none THEN
16634       -- in case further needs for validation
16635       NULL;
16636     END IF;
16637 
16638     OPEN c_rules; -- open the eligible rules cursor
16639 
16640     LOOP -- loop through the rules
16641       FETCH c_rules INTO l_rule_id, l_organization_id, l_wms_task_type, l_operation_plan_id;
16642       EXIT WHEN c_rules%NOTFOUND;
16643 
16644       BEGIN
16645         -- get the pre-generated package name for this rule
16646         getpackagename(l_rule_id, l_package_name);
16647 
16648          --- Execute op Rule
16649         For l_rule_counter IN 1..2  LOOP
16650             execute_op_rule(l_rule_id, p_task_id, l_return_status);
16651             IF (l_return_status = -1) and l_rule_counter   = 2 THEN --error
16652                 fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
16653                 fnd_message.set_token('RULEID', l_rule_id);
16654                 fnd_msg_pub.ADD;
16655                 log_error_msg(l_api_name, 'rule_package_missing');
16656                 log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
16657                 RAISE fnd_api.g_exc_unexpected_error;
16658             ELSIF l_return_status <> -1 THEN
16659                 EXIT;
16660             END IF;
16661        END LOOP;
16662 
16663        IF l_return_status > 0 THEN -- the rule matches the task
16664           l_found  := TRUE;
16665 
16666           -- update mmtt table to assign the operation plan
16667 
16668 
16669           UPDATE mtl_material_transactions_temp mmtt
16670              SET mmtt.operation_plan_id = l_operation_plan_id
16671            WHERE mmtt.transaction_temp_id = p_task_id;
16672 
16673           EXIT; -- operation plan assigned, jump out of the rule loop
16674         END IF; -- l_return_status > 0
16675       EXCEPTION -- handle exceptions for matching one rule
16676         WHEN fnd_api.g_exc_error THEN
16677           NULL;
16678         WHEN OTHERS THEN
16679           NULL;
16680       END; -- end matching one rule
16681     END LOOP;
16682 
16683     CLOSE c_rules; --close the rule cursor
16684 
16685     -- get default operation plan
16686     IF NOT l_found THEN
16687 
16688       begin
16689             select organization_id
16690              into  l_organization_id
16691              from  mtl_material_transactions_temp
16692               where  transaction_temp_id = p_task_id
16693               AND transaction_source_type_id IN (2, 8);   -- bug fix 3361560
16694       exception
16695             when others then
16696                 null;
16697       end;
16698 
16699       IF NVL(g_current_organization_id, -1) <> l_organization_id THEN
16700         g_current_organization_id  := l_organization_id;
16701         OPEN c_default_operation_plan;
16702         FETCH c_default_operation_plan INTO g_default_operation_plan_id;
16703 
16704         IF c_default_operation_plan%NOTFOUND THEN
16705           l_operation_plan_id  := NULL;
16706         END IF;
16707 
16708         CLOSE c_default_operation_plan;
16709       END IF;
16710 
16711       l_operation_plan_id  := g_default_operation_plan_id;
16712 
16713       UPDATE mtl_material_transactions_temp mmtt
16714          SET mmtt.operation_plan_id = l_operation_plan_id
16715        WHERE mmtt.transaction_temp_id = p_task_id;
16716     END IF;
16717 
16718     -- Standard check of p_commit
16719     IF fnd_api.to_boolean(p_commit) THEN
16720       COMMIT WORK;
16721     END IF;
16722   EXCEPTION
16723     WHEN fnd_api.g_exc_error THEN
16724       -- if the rule package not created yet, close the rule cursor
16725       IF c_rules%ISOPEN THEN
16726         CLOSE c_rules;
16727       END IF;
16728 
16729       ROLLBACK TO assign_operation_plan_sp;
16730       freeglobals;
16731       x_return_status  := fnd_api.g_ret_sts_error;
16732 
16733       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16734         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
16735       END IF;
16736 
16737       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16738     WHEN OTHERS THEN
16739       ROLLBACK TO assign_operation_plan_sp;
16740       freeglobals;
16741       x_return_status  := fnd_api.g_ret_sts_unexp_error;
16742 
16743       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16744         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
16745       END IF;
16746 
16747       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16748   END assign_operation_plan;
16749 
16750   --**************************************
16751 
16752   --
16753   -- API name    : AssignTT
16754   -- Type        : Private
16755   -- Function    : Assign task type to records in MMTT
16756   -- Input Parameters  :
16757   --
16758   -- Output Parameters:
16759   -- Version     :
16760   --   Current version 1.0
16761   --
16762   -- Notes       : calls AssignTTs(p_task_id NUMBER)
16763   --
16764   -- This procedure loops through mtl_material_transactions_temp table, assign
16765   -- user defined task type to tasks that have not been assigned a task type
16766   -- for the given Move Order Header.
16767   --
16768 
16769 
16770   PROCEDURE assigntts(
16771     p_api_version          IN            NUMBER
16772   , p_init_msg_list        IN            VARCHAR2
16773   , p_commit               IN            VARCHAR2
16774   , p_validation_level     IN            NUMBER
16775   , x_return_status        OUT NOCOPY    VARCHAR2
16776   , x_msg_count            OUT NOCOPY    NUMBER
16777   , x_msg_data             OUT NOCOPY    VARCHAR2
16778   , p_move_order_header_id IN            NUMBER
16779   ) IS
16780     CURSOR c_tasks IS
16781       SELECT mmtt.transaction_temp_id
16782             ,mmtt.organization_id -- Added new
16783             ,mmtt.wms_task_type   -- Added new
16784         FROM mtl_material_transactions_temp mmtt, mtl_txn_request_lines mol
16785        WHERE mmtt.standard_operation_id IS NULL
16786          AND mmtt.move_order_line_id = mol.line_id
16787          AND mol.header_id = p_move_order_header_id;
16788 
16789     l_task_id           NUMBER;
16790     l_organization_id   NUMBER; -- Added new
16791     l_wms_task_type     NUMBER; -- Added new
16792     l_return_status VARCHAR2(1);
16793     l_msg_count     NUMBER;
16794     l_msg_data      VARCHAR2(2000);
16795     l_api_name      VARCHAR2(30)   := 'assignTTs';
16796     l_count         NUMBER;
16797   BEGIN
16798     -- Initialize API return status to success
16799     x_return_status  := fnd_api.g_ret_sts_success;
16800 
16801     -- Bug# 4587423
16802     -- See if there are any enabled rules for Task Type Assignment for
16803     -- all orgs or for the orgs in the set of MMTT records for the given move order header.
16804     l_count := 0;
16805     BEGIN
16806        SELECT 1 INTO l_count
16807          FROM dual
16808          WHERE EXISTS (SELECT 1 FROM wms_rules_b rules
16809                        WHERE  rules.type_code = 3
16810                        AND    rules.enabled_flag = 'Y'
16811                        AND    (organization_id = -1
16812                                OR organization_id IN (SELECT mmtt.organization_id
16813                                                       FROM mtl_material_transactions_temp mmtt,
16814                                                       mtl_txn_request_lines mol
16815                                                       WHERE mmtt.standard_operation_id IS NULL
16816                                                       AND mmtt.move_order_line_id = mol.line_id
16817                                                       AND mol.header_id = p_move_order_header_id)));
16818     EXCEPTION
16819        WHEN OTHERS THEN
16820           l_count := 0;
16821     END;
16822 
16823     -- Bug# 4587423
16824     -- If there is at least one task type assignment rule enabled,
16825     -- go through the existing logic.
16826     IF (l_count > 0) THEN
16827        OPEN c_tasks;
16828        LOOP
16829           FETCH c_tasks INTO l_task_id
16830                             ,l_organization_id  -- new
16831                             ,l_wms_task_type;    -- new
16832           EXIT WHEN c_tasks%NOTFOUND;
16833           assigntt
16834             (p_api_version                => 1.0,
16835              p_task_id                    => l_task_id,
16836              x_return_status              => l_return_status,
16837              x_msg_count                  => l_msg_count,
16838              x_msg_data                   => l_msg_data
16839              );
16840 
16841           IF l_return_status <> fnd_api.g_ret_sts_success THEN
16842              x_return_status  := fnd_api.g_ret_sts_error;
16843           END IF;
16844        END LOOP;
16845 
16846        CLOSE c_tasks;
16847      ELSE
16848        -- Bug# 4587423
16849        -- No valid rules exist for task type assignment so just stamp the org level
16850        -- default task type for the given WMS task type on the MMTT record.
16851        UPDATE mtl_material_transactions_temp mmtt
16852          SET standard_operation_id =
16853          (SELECT DECODE(mmtt.wms_task_type, 1, default_pick_task_type_id,
16854                         2, default_putaway_task_type_id,
16855                         3, default_cc_task_type_id,
16856                         4, default_repl_task_type_id,
16857                         5, default_moxfer_task_type_id,
16858                         6, default_moissue_task_type_id,
16859                         NULL)
16860           FROM mtl_parameters mp WHERE mp.organization_id = mmtt.organization_id)
16861          WHERE mmtt.standard_operation_id IS NULL
16862            AND mmtt.move_order_line_id IN (SELECT line_id
16863                                            FROM mtl_txn_request_lines mol
16864                                            WHERE mol.header_id = p_move_order_header_id);
16865     END IF;
16866 
16867   EXCEPTION
16868      WHEN OTHERS THEN
16869         x_return_status  := fnd_api.g_ret_sts_unexp_error;
16870   END assigntts;
16871 
16872   --
16873   -- API name    : AssignTT
16874   -- Type        : Private
16875   -- Function    : Assign task type to a specific record in MMTT
16876   -- Input Parameters  :
16877   --           p_task_id NUMBER
16878   --
16879   -- Output Parameters:
16880   -- Version     :
16881   --   Current version 1.0
16882   --
16883   -- Notes       :
16884   --
16885   -- This procedure assign user defined task types to a specific task in
16886   -- mtl_material_transactions_temp. Task type is implemeted by WMS rules.
16887   -- This procedure calls the rule package created for task type rules to check
16888   -- which task type rule actually matches the task in question.
16889   --
16890 
16891   PROCEDURE assigntt(
16892     p_api_version      IN            NUMBER
16893   , p_init_msg_list    IN            VARCHAR2
16894   , p_commit           IN            VARCHAR2
16895   , p_validation_level IN            NUMBER
16896   , x_return_status    OUT NOCOPY    VARCHAR2
16897   , x_msg_count        OUT NOCOPY    NUMBER
16898   , x_msg_data         OUT NOCOPY    VARCHAR2
16899   , p_task_id          IN            NUMBER
16900    ) IS
16901     l_rule_id                   NUMBER;
16902     l_pack_exists               NUMBER;
16903     l_package_name              VARCHAR2(30);
16904     l_rule_func_sql             LONG;
16905     l_rule_result               NUMBER;
16906     l_cursor                    INTEGER;
16907     l_dummy                     NUMBER;
16908     l_count                     NUMBER;
16909     l_return_status             NUMBER;
16910     l_revision_dummy            VARCHAR2(10);
16911     l_lot_number_dummy          VARCHAR2(80);
16912     l_lot_expiration_date_dummy DATE;
16913     l_subinventory_code_dummy   VARCHAR2(10);
16914     l_locator_id_dummy          NUMBER;
16915     l_possible_qty_dummy        NUMBER;
16916     l_uom_code_dummy            VARCHAR2(3);
16917     l_order_by_string_dummy     VARCHAR2(1000);
16918     l_found                     BOOLEAN        := FALSE;
16919     l_organization_id           NUMBER;
16920     l_wms_task_type             NUMBER;
16921     l_task_type_id              NUMBER;
16922     l_type_hdr_id               NUMBER;
16923 
16924     l_api_version      CONSTANT NUMBER         := 1.0;
16925     l_api_name         CONSTANT VARCHAR2(30)   := 'AssignTT';
16926 
16927     l_debug                     NUMBER;
16928 
16929 
16930     -- Cursor for task type rule loop
16931     -- Only rules with the same WMS system task type as the task
16932     -- will be selected
16933     -- Rules are ordered by rule weight and creation date
16934 
16935     CURSOR c_rules IS
16936       SELECT   rules.rule_id
16937              , rules.type_hdr_id /* Added this Column */
16938              , mmtt.organization_id
16939              , mmtt.wms_task_type
16940           FROM wms_rules_b rules, bom_standard_operations bso , mtl_material_transactions_temp mmtt
16941          WHERE rules.type_code = 3
16942            AND rules.enabled_flag = 'Y'
16943            AND rules.type_hdr_id = bso.standard_operation_id
16944            AND bso.wms_task_type = NVL(mmtt.wms_task_type, bso.wms_task_type)
16945            AND mmtt.transaction_temp_id = p_task_id
16946            AND rules.organization_id IN (mmtt.organization_id, -1)
16947            AND bso.organization_id = mmtt.organization_id
16948       ORDER BY rules.rule_weight DESC, rules.creation_date;
16949 
16950   /*CURSOR c_rules_new IS
16951     SELECT   rules.rule_id ,  rules.type_hdr_id
16952         FROM wms_rules_b rules, bom_standard_operations bso
16953        WHERE rules.type_code = 3
16954          AND rules.enabled_flag = 'Y'
16955          AND rules.type_hdr_id = bso.standard_operation_id
16956          AND bso.wms_task_type = NVL(p_wms_task_type, bso.wms_task_type)
16957          AND rules.organization_id IN (p_organization_id, -1)
16958          AND bso.organization_id = p_organization_id
16959     ORDER BY rules.rule_weight DESC, rules.creation_date; */
16960 
16961     -- Following Code is commented because now we need to get 2 more default task_type..MOISSUE and MOXFER
16962       /*CURSOR c_default_task_type IS
16963       SELECT default_pick_task_type_id
16964             ,default_cc_task_type_id
16965             ,default_putaway_task_type_id
16966             ,default_repl_task_type_id
16967         FROM mtl_parameters
16968        WHERE organization_id = l_organization_id;
16969       */
16970 
16971     CURSOR c_default_task_type IS
16972       SELECT default_pick_task_type_id
16973            , default_cc_task_type_id
16974            , default_putaway_task_type_id
16975            , default_repl_task_type_id
16976            , default_moxfer_task_type_id
16977            , default_moissue_task_type_id
16978            , default_pick_op_plan_id
16979         FROM mtl_parameters
16980        WHERE organization_id =  l_organization_id;
16981 
16982        l_rule_counter           INTEGER;
16983   BEGIN
16984     SAVEPOINT assignttsp;
16985 
16986     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
16987        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
16988      END IF;
16989     l_debug := g_debug;
16990 
16991     -- Standard call to check for call compatibility
16992     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
16993       RAISE fnd_api.g_exc_unexpected_error;
16994     END IF;
16995 
16996     -- Initialize message list if p_init_msg_list is set to TRUE
16997     IF fnd_api.to_boolean(p_init_msg_list) THEN
16998       fnd_msg_pub.initialize;
16999     END IF;
17000 
17001     --
17002     -- Initialize API return status to success
17003     x_return_status  := fnd_api.g_ret_sts_success;
17004 
17005     -- Validate input parameters and pre-requisites, if validation level
17006     -- requires this
17007     IF p_validation_level <> fnd_api.g_valid_level_none THEN
17008       -- in case further needs for validation
17009       NULL;
17010     END IF;
17011 
17012     OPEN c_rules; -- open the eligible rules cursor
17013 
17014     LOOP -- loop through the rules
17015       FETCH c_rules INTO l_rule_id, l_type_hdr_id, l_organization_id, l_wms_task_type;
17016       EXIT WHEN c_rules%NOTFOUND;
17017 
17018       --inv_log_util.TRACE('found the rule', 'RULE_ENGINE', 4);
17019 
17020       BEGIN
17021         -- get the pre-generated package name for this rule
17022         getpackagename(l_rule_id, l_package_name);
17023 
17024         --- Execute Task Rule
17025 
17026        -- execute_task_rule(l_rule_id, p_task_id, l_return_status);
17027         For l_rule_counter IN 1..2  LOOP
17028            IF l_debug = 1 THEN
17029               log_error(l_api_name, 'Assigntt', 'Inside Loop :l_rule_counter         ' || l_rule_counter);
17030               log_error(l_api_name, 'Assigntt', 'Calling execute_Task :l_rul        e_id ' || l_rule_id);
17031               log_error(l_api_name, 'Assigntt', 'Calling execute_Task :p_Tas        k_id ' || p_task_id);
17032            END IF;
17033            execute_task_rule(l_rule_id, p_task_id, l_return_status);
17034              IF (l_return_status = -1) and l_rule_counter   = 2 THEN --error
17035                fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
17036                fnd_message.set_token('RULEID', l_rule_id);
17037                fnd_msg_pub.ADD;
17038                IF l_debug = 1 THEN
17039                   log_error_msg(l_api_name, 'rule_package_missing');
17040                   log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
17041                END IF;
17042                RAISE fnd_api.g_exc_unexpected_error;
17043              ELSIF  l_return_status <> -1 THEN
17044                 EXIT;
17045              END IF;
17046         END LOOP;
17047         If l_debug = 1 THEN
17048            log_error(l_api_name, 'Assigntt', 'After Execute_Task :l_return_s        tatus ' || l_return_status);
17049         END IF;
17050 
17051         IF l_return_status > 0 THEN -- the rule matches the task
17052            l_found  := TRUE;
17053 
17054           -- update mmtt table to assign the task type
17055 
17056           UPDATE mtl_material_transactions_temp mmtt
17057              SET mmtt.standard_operation_id = l_type_hdr_id
17058            WHERE mmtt.transaction_temp_id = p_task_id;
17059            /*
17060            UPDATE mtl_material_transactions_temp mmtt
17061                         SET mmtt.standard_operation_id = (SELECT type_hdr_id
17062                                                             FROM wms_rules_b
17063                                                            WHERE rule_id = l_rule_id)
17064            WHERE mmtt.transaction_temp_id = p_task_id
17065            */
17066 
17067           EXIT; -- task assigned, jump out of the rule loop
17068         END IF; -- l_return_status > 0
17069       EXCEPTION -- handle exceptions for matching one rule
17070         WHEN fnd_api.g_exc_error THEN
17071           NULL;
17072         WHEN OTHERS THEN
17073           NULL;
17074       END; -- end matching one rule
17075     END LOOP;
17076 
17077     CLOSE c_rules; --close the rule cursor
17078 
17079     -- get default task type
17080     IF NOT l_found THEN
17081      -- bug 2737846
17082      begin
17083       select organization_id, wms_task_type
17084        into  l_organization_id, l_wms_task_type
17085        from  mtl_material_transactions_temp
17086       where  transaction_temp_id = p_task_id;
17087      exception
17088         when others then
17089           null;
17090      end;
17091 
17092       --inv_log_util.TRACE('NOT found the rule: g_current_organization_id'||g_current_organization_id, 'RULE_ENGINE', 4);
17093       --inv_log_util.TRACE('NOT found the rule: l_organization_id:'||l_organization_id, 'RULE_ENGINE', 4);
17094       IF NVL(g_current_organization_id, -1) <> l_organization_id THEN
17095         g_current_organization_id  := l_organization_id;
17096 
17097 
17098         OPEN c_default_task_type;
17099         /*FETCH c_default_task_type INTO g_default_pick_task_type_id
17100                           ,g_default_cc_task_type_id
17101                           ,g_default_putaway_task_type_id
17102                           ,g_default_repl_task_type_id;
17103          */
17104         FETCH c_default_task_type INTO g_default_pick_task_type_id
17105                                      , g_default_cc_task_type_id
17106                                      , g_default_putaway_task_type_id
17107                                      , g_default_repl_task_type_id
17108                                      , g_default_moxfer_task_type_id
17109                                      , g_default_moissue_task_type_id
17110                                      , g_default_operation_plan_id;
17111 
17112         IF c_default_task_type%NOTFOUND THEN
17113           g_current_organization_id       := NULL;
17114           g_default_pick_task_type_id     := NULL;
17115           g_default_cc_task_type_id       := NULL;
17116           g_default_putaway_task_type_id  := NULL;
17117           g_default_repl_task_type_id     := NULL;
17118           g_default_moxfer_task_type_id   := NULL;
17119           g_default_moissue_task_type_id  := NULL;
17120           g_default_operation_plan_id          := NULL;
17121           --inv_log_util.TRACE('default_task_type not found', 'RULE_ENGINE', 4);
17122         END IF;
17123 
17124         CLOSE c_default_task_type;
17125       END IF;
17126 
17127       --inv_log_util.TRACE('inside cursor c_defualt_task_type', 'RULE_ENGINE', 4);
17128 
17129 
17130       IF l_wms_task_type = 1 THEN
17131          l_task_type_id  := g_default_pick_task_type_id;
17132       ELSIF l_wms_task_type = 2 THEN
17133         l_task_type_id  := g_default_putaway_task_type_id;
17134       ELSIF l_wms_task_type = 3 THEN
17135         l_task_type_id  := g_default_cc_task_type_id; --g_default_repl_task_type_id; --Bug# 3110550
17136       ELSIF l_wms_task_type = 4 THEN
17137         l_task_type_id  := g_default_repl_task_type_id; --g_default_cc_task_type_id; --Bug# 3110550
17138       ELSIF l_wms_task_type = 5 THEN
17139         l_task_type_id  := g_default_moxfer_task_type_id;
17140       ELSIF l_wms_task_type = 6 THEN
17141         l_task_type_id  := g_default_moissue_task_type_id;
17142       ELSE
17143         l_task_type_id  := NULL;
17144       END IF;
17145 
17146       --inv_log_util.TRACE('wms_task_type = 1, task_type_id=:' || l_task_type_id, 'RULE_ENGINE', 4);
17147       --inv_log_util.TRACE('before update statement', 'RULE_ENGINE', 4);
17148 
17149       UPDATE mtl_material_transactions_temp mmtt
17150          SET mmtt.standard_operation_id = l_task_type_id
17151        WHERE mmtt.transaction_temp_id = p_task_id;
17152 
17153        --inv_log_util.TRACE('after update statement: standard_operation_id:'||jxlu_soi, 'RULE_ENGINE', 4);
17154     END IF;
17155 
17156     -- Standard check of p_commit
17157     IF fnd_api.to_boolean(p_commit) THEN
17158       COMMIT WORK;
17159     END IF;
17160   EXCEPTION
17161     WHEN fnd_api.g_exc_error THEN
17162       -- if the rule package not created yet, close the rule cursor
17163       IF c_rules%ISOPEN THEN
17164         CLOSE c_rules;
17165       END IF;
17166 
17167       ROLLBACK TO assignttsp;
17168       freeglobals;
17169       x_return_status  := fnd_api.g_ret_sts_error;
17170 
17171       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17172         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
17173       END IF;
17174 
17175       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
17176     WHEN OTHERS THEN
17177       ROLLBACK TO assignttsp;
17178       freeglobals;
17179       x_return_status  := fnd_api.g_ret_sts_unexp_error;
17180 
17181       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17182         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
17183       END IF;
17184 
17185       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
17186   END assigntt;
17187 
17188   --
17189   -- API name    : CalcRuleWeight
17190   -- Type        : Private
17191   -- Function    : Calculate initial rule weight based on number of distinct restriction
17192   --               parameters. This is currently the requirement for task type assignment
17193   --
17194   -- Input Parameters  :
17195   --           p_task_id NUMBER
17196   --
17197   -- Output Parameters:
17198   -- Version     :
17199   --   Current version 1.0
17200   --
17201   -- Notes       :
17202   --
17203   -- This procedure will be called by Define Rule form through generate rule package call
17204 
17205   PROCEDURE calcruleweight(p_rule_id NUMBER) IS
17206   BEGIN
17207 
17208     UPDATE wms_rules_b
17209        SET rule_weight = (SELECT 100 * COUNT(parameter_id)
17210                             FROM (SELECT DISTINCT rules.rule_id
17211                                                 , par.parameter_id
17212                                              FROM wms_rules_b rules, wms_restrictions rest, wms_parameters_b par
17213                                             WHERE rules.rule_id = p_rule_id
17214                                               AND rules.rule_id = rest.rule_id(+)
17215                                               AND rest.parameter_id = par.parameter_id(+)
17216                                               AND (NVL(par.use_for_tt_assn_flag, 'Y') = 'Y'
17217                                                    OR NVL(par.use_for_label_rest_flag, 'Y') = 'Y'
17218                                                   )))
17219      WHERE rule_id = p_rule_id
17220        AND rule_weight IS NULL;
17221 
17222 
17223   EXCEPTION
17224     WHEN OTHERS THEN
17225       NULL;
17226   END calcruleweight;
17227 
17228   --===========================================================================================
17229   --
17230   -- API name    : ApplyLabel
17231   -- Type        : Private
17232   -- Function    : Retrieve Label based on Label request
17233   -- Input Parameters  :
17234   --           p_label_request_id  NUMBER
17235   --           p_document_id       NUMBER
17236   --
17237   -- Output Parameters: x_label_format_id
17238   -- Version     :
17239   -- Current version 1.0
17240   --
17241   -- Notes       :
17242   --
17243   -- This procedure retrieves a specific label for a label request in
17244   -- wms_label_requests.
17245   -- This procedure calls the rule package created for Label rules to check
17246   -- which label rule actually matches the label request in question.
17247   --===========================================================================
17248   PROCEDURE applylabel(
17249     p_api_version       IN            NUMBER
17250   , p_init_msg_list     IN            VARCHAR2
17251   , p_commit            IN            VARCHAR2
17252   , p_validation_level  IN            NUMBER
17253   , p_label_request_id  IN            NUMBER
17254   , x_return_status     OUT NOCOPY    VARCHAR2
17255   , x_msg_count         OUT NOCOPY    NUMBER
17256   , x_msg_data          OUT NOCOPY    VARCHAR2
17257   , x_label_format_id   OUT NOCOPY    NUMBER
17258   , x_label_format_name OUT NOCOPY    VARCHAR2
17259   ) IS
17260     l_rule_id              NUMBER;
17261     l_rule_weight          NUMBER;
17262     l_pack_exists          NUMBER;
17263     l_package_name         VARCHAR2(30);
17264     l_rule_func_sql        LONG;
17265     l_rule_result          NUMBER;
17266     l_cursor               INTEGER;
17267     l_dummy                NUMBER;
17268     l_count                NUMBER;
17269     l_return_status        NUMBER;
17270     l_label_format_id      NUMBER;
17271     l_document_id          NUMBER;
17272     l_label_format_name    wms_label_formats.label_format_name%TYPE;
17273     l_api_version CONSTANT NUMBER                                     := 1.0;
17274     l_api_name    CONSTANT VARCHAR2(30)                               := 'ApplyLabel';
17275     l_msg_data             VARCHAR2(2000);
17276     l_strategy_id          NUMBER                                     := NULL;
17277 
17278 
17279     -- Cursor for label rule loop
17280     -- Only rules with the type_code = 4
17281     -- will be selected
17282     -- Rules are ordered by rule weight and creation date
17283 
17284     CURSOR c_rules IS
17285       SELECT   rules.rule_id
17286              , rules.rule_weight
17287              , rules.type_hdr_id
17288              , wl.label_format_name
17289              , wl.document_id
17290           FROM wms_rules_b rules, wms_label_formats wl, wms_label_requests wlr
17291          WHERE rules.type_code = 4
17292            AND rules.type_hdr_id = wl.label_format_id
17293            AND wl.label_format_id = NVL(wlr.label_format_id, wl.label_format_id)
17294            AND NVL(format_disable_date, SYSDATE + 1) > SYSDATE   --Bug #3452076
17295            AND wlr.document_id = wl.document_id
17296            AND wlr.label_request_id = p_label_request_id
17297            AND rules.enabled_flag = 'Y'
17298            AND (rules.organization_id = wlr.organization_id
17299                 OR rules.organization_id = -1
17300                ) -- Common to All Org.
17301       ORDER BY rules.rule_weight DESC, rules.creation_date;
17302 
17303     CURSOR l_default_label_curs IS
17304       SELECT label_format_id
17305            , label_format_name
17306         FROM wms_label_formats
17307        WHERE document_id = l_document_id
17308          AND default_format_flag IN ('Y', 'y');
17309 
17310     CURSOR l_label_requests_curs IS
17311       SELECT *
17312         FROM wms_label_requests
17313        WHERE label_request_id = p_label_request_id;
17314 
17315     l_label_req_rc         wms_label_requests%ROWTYPE;
17316     l_rule_counter           INTEGER;
17317     l_debug                  NUMBER;
17318     ll_ctr                   NUMBER;
17319   BEGIN
17320     SAVEPOINT assignlabelsp;
17321    ----
17322        SELECT   count(rules.rule_id ) into  ll_ctr
17323        FROM wms_rules_b rules, wms_label_formats wl, wms_label_requests wlr
17324        WHERE rules.type_code = 4
17325                   AND rules.type_hdr_id = wl.label_format_id
17326                   AND wl.label_format_id = NVL(wlr.label_format_id, wl.label_format_id)
17327                   AND NVL(format_disable_date, SYSDATE + 1) > SYSDATE   --Bug #        3452076
17328                   AND wlr.document_id = wl.document_id
17329                   AND wlr.label_request_id = p_label_request_id
17330                   AND rules.enabled_flag = 'Y'
17331                   AND (rules.organization_id = wlr.organization_id
17332                        OR rules.organization_id = -1
17333                   ) ;
17334    ----
17335     IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
17336        g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
17337     END IF;
17338     l_debug := g_debug;
17339     IF l_debug = 1 THEN
17340        TRACE('Executing ApplyLabel()...Label_request_ID :  '|| p_label_request_id);
17341        TRACE('Number of rules to process(LL_CTR) :' || ll_ctr);
17342     END IF;
17343 
17344     -- Standard call to check for call compatibility
17345     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
17346       RAISE fnd_api.g_exc_unexpected_error;
17347     END IF;
17348 
17349     -- Initialize message list if p_init_msg_list is set to TRUE
17350     IF fnd_api.to_boolean(p_init_msg_list) THEN
17351       fnd_msg_pub.initialize;
17352     END IF;
17353 
17354     --
17355     -- Initialize API return status to success
17356     x_return_status      := fnd_api.g_ret_sts_success;
17357 
17358     -- Validate input parameters and pre-requisites, if validation level
17359     -- requires this
17360     IF p_validation_level <> fnd_api.g_valid_level_none THEN
17361       -- in case further needs for validation
17362       NULL;
17363     END IF;
17364 
17365     -- Retrieve document_id based on P_label_request_id
17366 
17367     OPEN l_label_requests_curs;
17368     FETCH l_label_requests_curs INTO l_label_req_rc;
17369 
17370     --dummy should = 2, one for package, one for package body
17371     IF (l_label_requests_curs%NOTFOUND) THEN
17372       CLOSE l_label_requests_curs;
17373       IF l_debug = 1 THEN
17374          TRACE('Invalid Label Request Id : '|| p_label_request_id);
17375       END IF;
17376       fnd_message.set_name('WMS', 'INVALID_LABEL_REQ');
17377       fnd_msg_pub.ADD;
17378       RAISE fnd_api.g_exc_error;
17379     END IF;
17380 
17381     CLOSE l_label_requests_curs;
17382 
17383     l_document_id        := l_label_req_rc.document_id;
17384     IF l_debug = 1 THEN
17385        TRACE('Label request document Id : '|| l_document_id);
17386     END IF;
17387     l_return_status      := 0; -- Initialize to 0
17388     OPEN c_rules; -- open the eligible rules cursor
17389 
17390     LOOP -- loop through the rules
17391       FETCH c_rules INTO l_rule_id, l_rule_weight, l_label_format_id, l_label_format_name, l_label_req_rc.document_id;
17392       EXIT WHEN c_rules%NOTFOUND;
17393       -- get the pre-generated package name for this rule
17394       getpackagename(l_rule_id, l_package_name);
17395 
17396       FOR l_rule_counter IN 1..2  LOOP
17397            IF l_debug = 1 THEN
17398             log_error(l_api_name, 'AssignLabel', 'Inside Loop :l_rule_counter ' || l_rule_counter);
17399             log_error(l_api_name, 'AssignLabel', 'Calling execute_label :l_rule_id ' || l_rule_id);
17400             log_error(l_api_name, 'AssignLabel', 'p_label_request_id ' || p_label_request_id);
17401            END IF;
17402            execute_label_rule(l_rule_id, p_label_request_id, l_return_status);
17403            IF l_debug = 1 THEN
17404               log_statement(l_api_name, 'Inside Loop', 'l_return_status' || l_return_status);
17405            END IF;
17406            log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
17407            IF (l_return_status = -1) and l_rule_counter   = 2 THEN --error
17408               fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
17409               fnd_message.set_token('RULEID', l_rule_id);
17410               fnd_msg_pub.ADD;
17411               IF l_debug = 1 THEN
17412                  log_error_msg(l_api_name, 'rule_package_missing');
17413                  log_error(l_api_name, 'Rule missing in the list pkg', 'l_rule_id ' || l_rule_id);
17414               END IF;
17415               RAISE fnd_api.g_exc_unexpected_error;
17416             ELSIF l_return_status  <> -1 THEN
17417                EXIT;
17418             END IF;
17419       END LOOP;
17420 
17421       IF l_return_status > 0 THEN -- the rule matches the label request
17422         -- update wms_label_requests table with label_format_id
17423 
17424 
17425         UPDATE wms_label_requests wlr
17426            SET wlr.label_format_id = l_label_format_id
17427              , wlr.rule_id = l_rule_id
17428              , wlr.strategy_id = l_strategy_id
17429              , wlr.rule_weight = l_rule_weight
17430          WHERE wlr.label_request_id = p_label_request_id;
17431         IF l_debug = 1 THEN
17432            TRACE('Rule Match.Update Label Request with format ID :'|| l_label_format_id || ' ' || l_label_format_name);
17433         END IF;
17434 
17435         EXIT; -- label retrieved, jump out of the rule loop
17436       ELSIF (l_return_status = 0) THEN
17437         IF l_debug = 1 THEN
17438           trace('no rows found from procedure execute_label_rule()');
17439         END IF;
17440       END IF;
17441     END LOOP;
17442 
17443     CLOSE c_rules; --close the rule cursor
17444 
17445     -- ===================================================================
17446     -- Retrieve default label if there is no rule match the label request
17447     -- ===================================================================
17448     IF l_debug = 1 THEN
17449       trace('l_return_status : '|| l_return_status);
17450     END IF;
17451 
17452     IF (l_return_status = 0) THEN
17453       IF l_debug = 1 THEN
17454          TRACE('No rule match retrieve the default format ');
17455       END IF;
17456       --Bug: 2646648 Patchset I label cleanup
17457       --Reset l_label_format_id(name) to null
17458       -- before retrieving default format
17459         -- so that if no default format, it will have value null
17460       -- instead of the value from cursor c_rules
17461       l_label_format_id    := NULL;
17462       l_label_format_name  := NULL;
17463       OPEN l_default_label_curs;
17464       FETCH l_default_label_curs INTO l_label_format_id, l_label_format_name;
17465       CLOSE l_default_label_curs;
17466     END IF;
17467 
17468     -- update wms_label_requests table with label_format_id
17469 
17470 
17471     UPDATE wms_label_requests wlr
17472        SET wlr.label_format_id = l_label_format_id
17473      WHERE wlr.label_request_id = p_label_request_id;
17474 
17475     IF l_debug = 1 THEN
17476        TRACE('Update Label Request with label ID :'|| l_label_format_id || '.(' || SQL%ROWCOUNT || ')');
17477     END IF;
17478 
17479     --
17480     -- Assign x_label_format_id with l_label_format_id
17481     --
17482     x_label_format_id    := l_label_format_id;
17483     x_label_format_name  := l_label_format_name;
17484 
17485     -- Standard check of p_commit
17486     IF fnd_api.to_boolean(p_commit) THEN
17487       COMMIT WORK;
17488     END IF;
17489   EXCEPTION
17490     WHEN fnd_api.g_exc_error THEN
17491       -- if the rule package not created yet, close the rule cursor
17492       IF c_rules%ISOPEN THEN
17493         CLOSE c_rules;
17494       END IF;
17495 
17496       ROLLBACK TO assignlabelsp;
17497       freeglobals;
17498       x_return_status  := fnd_api.g_ret_sts_error;
17499       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
17500     WHEN OTHERS THEN
17501       l_msg_data       := SQLERRM;
17502       IF l_debug = 1 THEN
17503          TRACE('EXCEPTION OTHERS: '|| l_msg_data);
17504       END IF;
17505       ROLLBACK TO assignlabelsp;
17506       freeglobals;
17507       x_return_status  := fnd_api.g_ret_sts_unexp_error;
17508       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
17509   END applylabel;
17510 
17511   PROCEDURE get_wms_sys_task_type(
17512     p_move_order_type            IN            NUMBER
17513   , p_transaction_action_id      IN            NUMBER
17514   , p_transaction_source_type_id IN            NUMBER
17515   , x_wms_sys_task_type          OUT NOCOPY    NUMBER
17516   ) IS
17517   BEGIN
17518     IF p_move_order_type = 2 THEN -- replenishment
17519       x_wms_sys_task_type  := 4; -- replenishment
17520     ELSIF p_move_order_type IN (3,5) THEN -- Bug 2666620: BackFlush MO Type Removed
17521       x_wms_sys_task_type  := 1; -- pick
17522     ELSIF p_move_order_type = 6 THEN -- put away
17523       x_wms_sys_task_type  := 2;
17524     ELSIF (p_move_order_type = 1
17525            AND p_transaction_action_id = 1
17526            AND p_transaction_source_type_id = 4
17527           ) THEN -- MO Issue
17528       x_wms_sys_task_type  := 6;
17529     ELSIF (p_move_order_type = 1
17530            AND p_transaction_action_id = 2
17531            AND p_transaction_source_type_id = 4
17532           ) THEN -- MO Xfer
17533       x_wms_sys_task_type  := 5;
17534     END IF;
17535   END get_wms_sys_task_type;
17536 
17537   --Compile_All_Rule_Packages
17538   --  Concurrent program which generates rule packages
17539   -- for all rules with enabled flag = Y
17540   PROCEDURE compile_all_rule_packages(errbuf OUT NOCOPY VARCHAR2, retcode OUT NOCOPY NUMBER) IS
17541     l_return_status VARCHAR2(1);
17542     l_msg_count     NUMBER;
17543     l_msg_data      VARCHAR2(240);
17544     l_rule_id       NUMBER;
17545     l_error_string  VARCHAR2(240);
17546     l_errbuf        VARCHAR2(240);
17547     l_return_code   NUMBER;
17548 
17549     CURSOR l_enabled_rules IS
17550       SELECT   rule_id
17551           FROM wms_rules_b
17552          WHERE enabled_flag = 'Y'
17553       ORDER BY rule_id;
17554   BEGIN
17555     --fnd_file.put_names('genall.log', 'genall.out', '/home/jcearley/work/');
17556     retcode  := 0;
17557 
17558     /* Adding for bug#13565649*/
17559 	IF ad_zd.get_edition('PATCH') IS NOT NULL THEN
17560 	    -- an online patch is in progress, return error
17561 	    fnd_message.set_name('FND', 'AD_ZD_DISABLED_FEATURE');
17562 		retcode  := 2;
17563 		errbuf   := errbuf || 'Error: ' || fnd_message.get;
17564         --inv_log_util.trace( 'errbuf : '||errbuf ,'compile_all_rule_packages' , 9);
17565 	    RETURN;
17566 	END IF;
17567 
17568    BEGIN
17569     --fnd_file.put_line(fnd_file.LOG, '===Compiling All Rule Packages===');
17570     OPEN l_enabled_rules;
17571 
17572     LOOP
17573       FETCH l_enabled_rules INTO l_rule_id;
17574       EXIT WHEN l_enabled_rules%NOTFOUND;
17575       --fnd_file.put_line(fnd_file.LOG, 'Compiling Rule ID= ' || l_rule_id);
17576       wms_rule_pvt.generaterulepackage(
17577         p_api_version                => 1.0
17578       , p_init_msg_list              => fnd_api.g_true
17579       , p_validation_level           => fnd_api.g_valid_level_full
17580       , x_return_status              => l_return_status
17581       , x_msg_count                  => l_msg_count
17582       , x_msg_data                   => l_msg_data
17583       , p_rule_id                    => l_rule_id
17584       );
17585 
17586      --
17587      -- kkoothan  Bug Fix:2561401
17588      -- Used FND APIs to check the return status of the called procedure
17589      -- instead of using hard coded values.
17590      --
17591      IF (l_return_status = fnd_api.g_ret_sts_success) THEN
17592         FND_FILE.put_line(FND_FILE.LOG, 'Success from GenerateRulePackage');
17593      ELSE
17594         FND_FILE.put_line(FND_FILE.LOG, 'Error from GenerateRulePackage:');
17595         retcode  := 1;
17596 
17597         FOR i IN 1 .. l_msg_count LOOP
17598           --fnd_file.put_line(fnd_file.LOG, 'Error:');
17599           l_error_string  := fnd_message.get;
17600           --fnd_file.put_line(fnd_file.LOG, l_error_string);
17601           errbuf          := errbuf || ' Error: Rule ' || l_rule_id || '
17602           ' || l_error_string;
17603         END LOOP;
17604       END IF;
17605     END LOOP;
17606 
17607     --- Calling procedure to generate all rule list packages
17608     --- this package should be called stand alone .
17609     buildrulespkg(l_errbuf, l_return_code, l_return_status);
17610 
17611     IF (l_return_status = fnd_api.g_ret_sts_success) THEN
17612       FND_FILE.put_line(FND_FILE.LOG, 'Success from BuildRulesPkg');
17613     ELSE
17614       FND_FILE.put_line(FND_FILE.LOG, 'Error from BuildRulesPkg:');
17615       retcode  := 1;
17616 
17617       FOR i IN 1 .. l_msg_count LOOP
17618         --fnd_file.put_line(fnd_file.LOG, 'Error:');
17619         l_error_string  := fnd_message.get;
17620         --fnd_file.put_line(fnd_file.LOG, l_error_string);
17621         errbuf          := errbuf || ' Error: Creating WMS Rule List Package ' || l_error_string;
17622       END LOOP;
17623     END IF;
17624   EXCEPTION
17625     WHEN OTHERS THEN
17626       retcode  := 2;
17627       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17628         fnd_msg_pub.add_exc_msg(g_pkg_name, 'Compile All Rule Packages');
17629       END IF;
17630 
17631       fnd_msg_pub.count_and_get(p_count => l_msg_count, p_data => l_msg_data);
17632       --fnd_file.put_line(fnd_file.LOG, 'Exception in compile_all_rule_packages');
17633       --fnd_file.put_line(fnd_file.LOG, l_msg_data);
17634       errbuf   := errbuf || 'Error: ' || l_msg_data;
17635 	END;
17636   END compile_all_rule_packages;
17637 
17638     --
17639     --
17640     PROCEDURE QuickPick
17641       (p_api_version                  IN   NUMBER                              ,
17642        p_init_msg_list                IN   VARCHAR2 DEFAULT fnd_api.g_false           ,
17643        p_commit                       IN   VARCHAR2 DEFAULT fnd_api.g_false           ,
17644        p_validation_level             IN   NUMBER   DEFAULT fnd_api.g_valid_level_full ,
17645        x_return_status                OUT  NOCOPY   VARCHAR2                            ,
17646        x_msg_count                    OUT  NOCOPY   NUMBER                                    ,
17647        x_msg_data                     OUT  NOCOPY   VARCHAR2                            ,
17648        p_type_code                    IN   NUMBER   DEFAULT NULL ,
17649        p_transaction_temp_id          IN   NUMBER   DEFAULT NULL ,
17650        p_organization_id              IN   NUMBER   DEFAULT NULL ,
17651        p_inventory_item_id            IN   NUMBER   DEFAULT NULL ,
17652        p_transaction_uom              IN   VARCHAR2 DEFAULT NULL,
17653        p_primary_uom                  IN   VARCHAR2 DEFAULT NULL,
17654        p_secondary_uom                IN   VARCHAR2 DEFAULT NULL,                  -- new
17655        p_grade_code                   IN   VARCHAR2 DEFAULT NULL,                  -- new
17656        p_transaction_type_id          IN   NUMBER   DEFAULT NULL ,
17657        p_tree_id                      IN   NUMBER   DEFAULT NULL ,
17658        x_finished                     OUT  NOCOPY   VARCHAR2                            ,
17659        p_detail_serial                IN   BOOLEAN  DEFAULT FALSE                    ,
17660        p_from_serial                  IN   VARCHAR2 DEFAULT NULL                    ,
17661        p_to_serial                    IN   VARCHAR2 DEFAULT NULL                    ,
17662        p_detail_any_serial            IN   NUMBER   DEFAULT NULL,
17663        p_unit_volume                  IN   NUMBER   DEFAULT NULL,
17664        p_volume_uom_code              IN   VARCHAR2 DEFAULT NULL,
17665        p_unit_weight                  IN   NUMBER   DEFAULT NULL,
17666        p_weight_uom_code              IN   VARCHAR2 DEFAULT NULL,
17667        p_base_uom_code                IN   VARCHAR2 DEFAULT NULL,
17668        p_lpn_id                       IN   NUMBER   DEFAULT NULL,
17669        p_unit_number                  IN   VARCHAR2 DEFAULT NULL,
17670        p_simulation_mode              IN   NUMBER   DEFAULT -1,
17671        p_project_id                   IN   NUMBER   DEFAULT NULL,
17672        p_task_id                      IN   NUMBER   DEFAULT NULL
17673        )
17674         IS
17675 
17676           -- API standard variables
17677             l_api_version   CONSTANT NUMBER              := 1.0;
17678             l_api_name      CONSTANT VARCHAR2(30)        := 'QuickPick';
17679             l_debug_on               BOOLEAN;
17680 
17681             --  input variables
17682 
17683             l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE; --
17684             l_revision               wms_transactions_temp.revision%TYPE;               --
17685             l_lot_number             wms_transactions_temp.lot_number%TYPE;             --
17686             l_lot_expiration_date    wms_transactions_temp.lot_expiration_date%TYPE;    --
17687             l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE; --
17688             l_to_subinventory_code   wms_transactions_temp.to_subinventory_code%TYPE;   --
17689             l_subinventory_code      wms_transactions_temp.to_subinventory_code%TYPE;
17690             l_from_locator_id        wms_transactions_temp.from_locator_id%TYPE;        --
17691             l_to_locator_id          wms_transactions_temp.to_locator_id%TYPE;          --
17692             l_locator_id             wms_transactions_temp.to_locator_id%TYPE;
17693             l_from_cost_group_id     wms_transactions_temp.from_cost_group_id%TYPE;     --
17694             l_to_cost_group_id       wms_transactions_temp.to_cost_group_id%TYPE;       --
17695             l_cost_group_id          wms_transactions_temp.to_cost_group_id%TYPE;
17696             l_lpn_id                 wms_transactions_temp.lpn_id%TYPE;                 --
17697             l_initial_pri_quantity   wms_transactions_temp.primary_quantity%TYPE;
17698 
17699             l_reservation_id         NUMBER; --
17700             l_needed_quantity        NUMBER; --
17701             l_sec_needed_quantity    NUMBER; --           -- new
17702             l_grade_code             VARCHAR2(150); --           -- new
17703             l_cur_rec                NUMBER;
17704 
17705             -- variables needed for qty tree
17706             l_qoh                    NUMBER;
17707             l_rqoh                   NUMBER;
17708             l_qr                     NUMBER;
17709             l_qs                     NUMBER;
17710             l_att                    NUMBER;
17711             l_atr                    NUMBER;
17712             l_tree_mode              NUMBER;
17713             l_tree_id                NUMBER;
17714             l_sqoh                    NUMBER;           -- new
17715             l_srqoh                   NUMBER;           -- new
17716             l_sqr                     NUMBER;           -- new
17717             l_sqs                     NUMBER;           -- new
17718             l_satt                    NUMBER;           -- new
17719             l_satr                    NUMBER;           -- new
17720 
17721             l_inserted_record        BOOLEAN;
17722             l_allocated_quantity     NUMBER;
17723             l_remaining_quantity     NUMBER;
17724             l_finished               VARCHAR2(1);
17725             l_sec_allocated_quantity     NUMBER;           -- new
17726             l_sec_remaining_quantity     NUMBER;           -- new
17727 
17728            --   Variables to check if Item is Lot and serial contriled
17729 
17730             l_lot_status_enabled      VARCHAR2(1);
17731             l_default_lot_status_id   NUMBER := NULL;
17732             l_serial_status_enabled   VARCHAR2(1);
17733             l_default_serial_status_id NUMBER;
17734 
17735 
17736             l_serial_control_code     NUMBER;
17737             l_is_serial_control       NUMBER;
17738 
17739             l_unit_number             VARCHAR2(30);
17740             l_allowed                 VARCHAR2(1) := 'Y';
17741             l_serial_allowed          VARCHAR2(1) := 'Y';
17742 
17743             g_trace_recs              wms_search_order_globals_pvt.pre_suggestions_record_tbl;
17744 
17745             l_debug                  NUMBER;         -- 1 for debug is on , 0 for debug is off
17746             l_progress               VARCHAR2(10);   -- local variable to track program progress,
17747 
17748                                                      -- especially useful when exception occurs
17749             l_serial_number          NUMBER;         -- [ new code ]
17750 
17751           -- LPN Status Project
17752              l_onhand_status_trx_allowed VARCHAR2(1);
17753              l_default_status_id        NUMBER ;
17754           -- LPN Status Project
17755 
17756           cursor lpn_serial_cur(l_lpn_id NUMBER ) is
17757           SELECT STATUS_ID FROM MTL_SERIAL_NUMBERS
17758           WHERE INVENTORY_ITEM_ID = P_INVENTORY_ITEM_ID
17759           AND LPN_ID = l_lpn_id;
17760 
17761 
17762   BEGIN
17763 
17764      IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
17765         g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
17766      END IF;
17767      l_debug := g_debug;
17768      l_progress := 10;
17769 
17770      l_tree_id := p_tree_id;
17771 
17772      IF l_debug = 1 THEN
17773         log_procedure(l_api_name, 'QuickPick', 'enter '|| g_pkg_name || '.' || l_api_name);
17774      END IF;
17775      -- end of debugging section
17776      --
17777      -- Standard start of API savepoint
17778      SAVEPOINT  QuickPicksp;
17779 
17780      -- Standard call to check for call compatibility
17781      IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
17782        RAISE fnd_api.g_exc_unexpected_error;
17783      END IF;
17784      -- Initialize message list if p_init_msg_list is set to TRUE
17785      IF fnd_api.to_boolean(p_init_msg_list) THEN
17786        fnd_msg_pub.initialize;
17787      END IF;
17788      -- Initialize API return status to success
17789      x_return_status  := fnd_api.g_ret_sts_success;
17790      -- Initialize functional return status to completed
17791      x_finished       := fnd_api.g_true;
17792      -- Validate input parameters and pre-requisites, if validation level
17793      -- requires this
17794 
17795      IF p_validation_level <> fnd_api.g_valid_level_none THEN
17796        IF l_debug = 1 THEN
17797           log_statement(l_api_name, 'Quick Pick',
17798         'p_validation_level <> fnd_api.g_valid_level_none ');
17799        END IF;
17800 
17801      IF p_type_code IS NULL
17802         OR p_type_code = fnd_api.g_miss_num
17803         OR p_type_code = 1 THEN
17804         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17805            fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
17806            log_error_msg(l_api_name, 'type_code_missing');
17807            fnd_msg_pub.ADD;
17808         END IF;
17809         RAISE fnd_api.g_exc_error;
17810      END IF;
17811 
17812      IF l_debug = 1 THEN
17813         log_statement(l_api_name, 'Quick Pick',
17814                  'p_transaction_temp_id  ' || p_transaction_temp_id );
17815      END IF;
17816 
17817      IF p_transaction_temp_id IS NULL
17818         OR p_transaction_temp_id = fnd_api.g_miss_num THEN
17819         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17820            fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
17821            log_error_msg(l_api_name, 'trx_req_line_id_missing');
17822            fnd_msg_pub.ADD;
17823         END IF;
17824 
17825         RAISE fnd_api.g_exc_error;
17826      END IF;
17827 
17828      IF l_debug = 1 THEN
17829         log_statement(l_api_name, 'Quick Pick',
17830            'p_organization_id   ' ||  p_organization_id  );
17831      END IF;
17832 
17833                IF p_organization_id IS NULL
17834                   OR p_organization_id = fnd_api.g_miss_num THEN
17835                   IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17836                      fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
17837                      log_error_msg(l_api_name, 'org_id_missing');
17838                      fnd_msg_pub.ADD;
17839                   END IF;
17840 
17841                   RAISE fnd_api.g_exc_error;
17842                END IF;
17843 
17844              IF l_debug = 1 THEN
17845                 log_statement(l_api_name, 'Quick Pick',
17846                                    'p_Inventory_item_id_id   ' ||  p_inventory_item_id );
17847               END IF;
17848 
17849                IF p_inventory_item_id IS NULL
17850                   OR p_inventory_item_id = fnd_api.g_miss_num THEN
17851                   IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17852                      fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
17853                      log_error_msg(l_api_name, 'item_id_missing');
17854                      fnd_msg_pub.ADD;
17855                   END IF;
17856 
17857                   RAISE fnd_api.g_exc_error;
17858                 END IF;
17859 
17860             /**  Commented for bug 4006426
17861               IF l_debug = 1 THEN
17862                  log_statement(l_api_name, 'Quick Pick', 'qty Tree =>' || p_tree_id );
17863               END IF;
17864 
17865                 IF  (p_tree_id IS NULL
17866                    OR p_tree_id = fnd_api.g_miss_num
17867                   ) THEN
17868                   IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
17869                      fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
17870                      log_error_msg(l_api_name, 'qty_tree_id_missing');
17871                      fnd_msg_pub.ADD;
17872                    END IF;
17873 
17874                    RAISE fnd_api.g_exc_error;
17875                   END IF;
17876 
17877                 IF l_debug = 1 THEN
17878                     log_statement(l_api_name, 'Quick Pick', 'finished validations and qty tree init' );
17879                 END IF;
17880                 */
17881             END IF;
17882 
17883    -- LPN Status Project
17884             if (inv_cache.set_org_rec(p_organization_id)) then
17885                l_default_status_id :=  nvl(inv_cache.org_rec.default_status_id,-1);
17886             end if;
17887   -- LPN Status Project
17888              --
17889              -- backup qty tree
17890            If p_tree_id IS NOT NULL  THEN  -- Added for bug # 4006426
17891 
17892             IF l_debug = 1 THEN
17893               log_statement(l_api_name, 'backup_tree',
17894                 'Calling inv_quantity_tree_pvt.backup_tree');
17895             END IF;
17896 
17897            inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
17898 
17899            IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
17900               IF l_debug = 1 THEN
17901                  log_statement(l_api_name, 'backup_tree_unexp_err',
17902                 'Unexpected error from inv_quantity_tree_pvt.backup_tree');
17903               END IF;
17904               RAISE fnd_api.g_exc_unexpected_error;
17905            ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
17906               IF l_debug = 1 THEN
17907                  log_statement(l_api_name, 'backup_tree_err',
17908                 'Error from inv_quantity_tree_pvt.backup_tree');
17909               END IF;
17910               RAISE fnd_api.g_exc_error;
17911            END IF;
17912         END IF;   --- Added for bug # 4006426
17913 
17914            g_locs_index               := 0;
17915            g_locs.DELETE;
17916            l_cur_rec              := 0;          --initialize pointer to next rec
17917 
17918            IF l_debug = 1 THEN
17919                log_statement(l_api_name, 'Quick Pick',
17920                              'Check if item is lot  status / Serial Status  enabled');
17921            END IF;
17922 
17923            --Check if item is lot  status / Serial Status  enabled --
17924            inv_material_status_grp.get_lot_serial_status_control(
17925                    p_organization_id                 => p_organization_id
17926                   ,p_inventory_item_id                 => p_inventory_item_id
17927                   ,x_return_status                 => x_return_status
17928                   ,x_msg_count                         => x_msg_count
17929                   ,x_msg_data                         => x_msg_data
17930                   ,x_lot_status_enabled            => l_lot_status_enabled
17931                   ,x_default_lot_status_id            => l_default_lot_status_id
17932                   ,x_serial_status_enabled            => l_serial_status_enabled
17933                   ,x_default_serial_status_id         => l_default_serial_status_id);
17934 
17935            wms_re_common_pvt.initinputpointer; -- Initialize the pointer
17936                                                   -- to the first trx detail input line
17937 
17938            IF l_debug = 1 THEN
17939                log_statement(l_api_name, 'Quick Pick',
17940                             'Initialize the pointer to the first trx detail input line');
17941                log_statement(l_api_name, 'Quick Pick',
17942                             'Loop through all the trx detail input lines');
17943            END IF;
17944 
17945                -- Loop through all the trx detail input lines
17946                WHILE TRUE LOOP
17947                   IF l_debug = 1 THEN
17948                      log_statement(l_api_name, 'Quick Pick',
17949                             'Get the next trx detail input line ');
17950                   END IF;
17951 
17952                   -- Get the next trx detail input line
17953                   wms_re_common_pvt.getnextinputline(
17954                          l_pp_transaction_temp_id
17955                        , l_revision
17956                        , l_lot_number
17957                        , l_lot_expiration_date
17958                        , l_from_subinventory_code
17959                        , l_from_locator_id
17960                        , l_from_cost_group_id
17961                        , l_to_subinventory_code
17962                        , l_to_locator_id
17963                        , l_to_cost_group_id
17964                        , l_needed_quantity
17965                        , l_sec_needed_quantity
17966                        , l_grade_code
17967                        , l_reservation_id
17968                        , l_serial_number -- [ new code ]
17969                        , l_lpn_id
17970                   );
17971                  EXIT WHEN l_pp_transaction_temp_id IS NULL;
17972                  IF l_debug = 1 THEN
17973                     log_statement(l_api_name, 'Quick Pick',
17974                                     'Get sub/Locator /Lot / serial status allowed'  || l_needed_quantity );
17975                  END IF;
17976               -- Get sub/Locator /Lot / serial status allowed  --
17977 
17978          --LPN Status Project
17979                    IF l_debug = 1 THEN
17980                         log_statement(l_api_name, 'Came to LPN Status Project ', l_onhand_status_trx_allowed);
17981                     END IF;
17982 
17983 
17984                 l_onhand_status_trx_allowed := 'Y';
17985 
17986                IF l_default_status_id = -1 THEN
17987                     l_onhand_status_trx_allowed:='N';
17988 
17989                    -- Get sub/Locator /Lot / serial status allowed  --
17990                   l_allowed  := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
17991                                   p_transaction_type_id        => p_transaction_type_id
17992                                 , p_organization_id            => p_organization_id
17993                                 , p_inventory_item_id          => p_inventory_item_id
17994                                 , p_subinventory_code          => l_from_subinventory_code
17995                                 , p_locator_id                 => l_from_locator_id
17996                                 , p_lot_number                 => l_lot_number );
17997                          IF (  l_allowed =  'N') then
17998                                     WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SUB_STATUS_NA';
17999                               fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
18000                               fnd_msg_pub.ADD;
18001                               fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18002                                IF l_debug = 1 THEN
18003                                         log_error_msg(l_api_name, x_msg_data);
18004                                END IF;
18005                         END IF;
18006 
18007 
18008                ELSE
18009                      l_allowed:='N';
18010                      if (inv_cache.item_rec.serial_number_control_code in (1,6)) then
18011                             l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
18012                                          p_transaction_type_id
18013                                         ,p_organization_id
18014                                         ,p_inventory_item_id
18015                                         ,l_from_subinventory_code
18016                                         ,l_from_locator_id
18017                                         ,l_lot_number
18018                                         , l_lpn_id);
18019 
18020                                IF l_debug = 1 THEN
18021                                  log_statement(l_api_name, 'l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
18022                               END IF;
18023 
18024                            IF (l_onhand_status_trx_allowed =  'N') then
18025                                         WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_DISALLOW_TRANSACTION';
18026                                   fnd_message.set_name('WMS', 'WMS_DISALLOW_TRANSACTION');
18027                                   fnd_msg_pub.ADD;
18028                                   fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18029                                       IF l_debug = 1 THEN
18030                                                    log_error_msg(l_api_name, x_msg_data);
18031                                        END IF;
18032                             END IF;
18033                           end if; -- if (inv_cache.item_rec.serial_number_control_code in (1,6))
18034 
18035                  END IF;  -- IF l_default_status_id = -1
18036 
18037              --LPN Status Project
18038 
18039                  IF ( l_serial_status_enabled = 'Y') then
18040                       IF l_debug = 1 THEN
18041                           log_statement(l_api_name, 'Quick Pick',
18042                               'inside If l_serial_status_enabled =  y ') ;
18043                           log_statement(l_api_name, 'Quick Pick',
18044                              'Calling inv_detail_util_pvt.is_serial_trx_allowed');
18045                       END IF;
18046                       --bug 7171840 changed the code to check the status at serial level rather than item defualt status
18047                       FOR L_LPN_CUR IN lpn_serial_cur(l_lpn_id) LOOP
18048                               l_serial_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
18049                               p_transaction_type_id   => p_transaction_type_id
18050                             ,p_organization_id       => p_organization_id
18051                             ,p_inventory_item_id     => p_inventory_item_id
18052                             ,p_serial_status         => L_LPN_CUR.STATUS_ID ) ;
18053 
18054                         IF L_SERIAL_ALLOWED = 'N' THEN
18055                            log_statement(l_api_name, 'Quick Pick',
18056                                                      'inside If l_serial_status_enabled =  N ') ;
18057                           EXIT;
18058                        END IF;
18059                        L_SERIAL_ALLOWED := 'Y';
18060                    END LOOP ;
18061                       /* commented out for bug 7171840
18062                       l_serial_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
18063                                 p_transaction_type_id   => p_transaction_type_id
18064                                ,p_organization_id       => p_organization_id
18065                                ,p_inventory_item_id     => p_inventory_item_id
18066                                  ,p_serial_status         => l_default_serial_status_id ) ;
18067                          end of bug 7171848*/
18068 
18069                  ELSIF ( l_serial_status_enabled = 'N') then
18070                      IF l_debug = 1 THEN
18071                         log_statement(l_api_name, 'Quick Pick',
18072                                                      'inside If l_serial_status_enabled =  N ') ;
18073                      END IF;
18074                      l_serial_allowed :=  'Y' ;
18075                  END IF;
18076 
18077                  l_cur_rec := l_cur_rec + 1 ;
18078 
18079                  -- Bug # 5512287
18080                  g_locs(l_cur_rec).quantity            :=  l_needed_quantity;
18081                  g_locs(l_cur_rec).secondary_quantity  :=  l_sec_needed_quantity;
18082 
18083                      g_locs(l_cur_rec).revision                 :=  l_revision;
18084                    g_locs(l_cur_rec).lot_number                 :=  l_lot_number;
18085                    g_locs(l_cur_rec).subinventory_code        :=  l_from_subinventory_code;
18086                    g_locs(l_cur_rec).locator_id                :=  l_from_locator_id;
18087                    g_locs(l_cur_rec).cost_group_id        :=  l_from_cost_group_id;
18088                    g_locs(l_cur_rec).lpn_id                :=  l_lpn_id;
18089 
18090                    --add record to table
18091                        g_locs_index            := g_locs_index + 1;
18092 
18093                        IF l_debug = 1 THEN
18094                           log_statement(l_api_name, 'loc_index', 'loc index: ' || g_locs_index);
18095                  END IF;
18096 
18097                       IF l_debug = 1 THEN
18098                      log_statement(l_api_name, 'QuickPick', 'Calling  validate_and_insert');
18099                      log_statement(l_api_name, 'QuickPick', 'p_record_id         '||  l_cur_rec);
18100                      log_statement(l_api_name, 'QuickPick', 'p_needed_quantity         '||  l_needed_quantity);
18101                      log_statement(l_api_name, 'QuickPick', 'p_needed_sec_quantity         '||  l_sec_needed_quantity);
18102                      log_statement(l_api_name, 'QuickPick', 'p_organization_id         '||  p_organization_id);
18103                      log_statement(l_api_name, 'QuickPick', 'p_inventory_item_id'||  p_inventory_item_id);
18104                      log_statement(l_api_name, 'QuickPick', 'p_to_subinventory_code'|| l_to_subinventory_code);
18105                      log_statement(l_api_name, 'QuickPick', 'p_to_locator_id         '||  l_to_locator_id);
18106                      log_statement(l_api_name, 'QuickPick', 'p_to_cost_group_id '||   l_to_cost_group_id );
18107                      log_statement(l_api_name, 'QuickPick', 'p_primary_uom         '||   p_primary_uom);
18108                      log_statement(l_api_name, 'QuickPick', 'p_transaction_uom         '||   p_transaction_uom);
18109                      log_statement(l_api_name, 'QuickPick', 'p_transaction_temp_id'|| p_transaction_temp_id );
18110                      log_statement(l_api_name, 'QuickPick', 'p_type_code         '||   p_type_code );
18111                      log_statement(l_api_name, 'QuickPick', 'p_reservation_id          '||   l_reservation_id  );
18112                      log_statement(l_api_name, 'QuickPick', 'p_tree_id                 '||   l_tree_id);
18113                      log_statement(l_api_name, 'QuickPick', 'Insert an Output record into WTT if status allowed');
18114                    END IF;
18115                    --  Insert an Output record into WTT if status allowed
18116                    --
18117           --LPN Status Project
18118 
18119                 IF l_debug = 1 THEN
18120                          log_statement(l_api_name, 'l_onhand_status_trx_allowed: ', l_onhand_status_trx_allowed);
18121                          log_statement(l_api_name, 'l_allowed: ', l_allowed);
18122                          log_statement(l_api_name, 'l_serial_allowed: ', l_serial_allowed);
18123                  END IF;
18124 
18125 
18126               IF ( ( nvl(l_allowed, 'Y') =  'Y' OR l_onhand_status_trx_allowed='Y') and  nvl(l_serial_allowed, 'Y')  =  'Y') then
18127         --LPN Status Project
18128                  IF p_tree_id IS NOT NULL THEN  -- Added for bug #4006426
18129 
18130                     IF l_debug = 1 THEN
18131                        log_statement(l_api_name, 'Calling validate_and_insert', '');
18132                     END IF;
18133                       validate_and_insert(
18134                        x_return_status              => x_return_status
18135                      , x_msg_count                  => x_msg_count
18136                      , x_msg_data                   => x_msg_data
18137                      , p_record_id                  => l_cur_rec
18138                      , p_needed_quantity            => l_needed_quantity
18139                      , p_use_pick_uom               => FALSE
18140                      , p_organization_id            => p_organization_id
18141                      , p_inventory_item_id          => p_inventory_item_id
18142                      , p_to_subinventory_code       => l_to_subinventory_code
18143                      , p_to_locator_id              => l_to_locator_id
18144                      , p_to_cost_group_id           => l_to_cost_group_id
18145                      , p_primary_uom                => p_primary_uom
18146                      , p_transaction_uom            => p_transaction_uom
18147                      , p_transaction_temp_id        => p_transaction_temp_id
18148                      , p_type_code                  => p_type_code
18149                      , p_rule_id                    => 0
18150                      , p_reservation_id             => l_reservation_id
18151                      , p_tree_id                    => l_tree_id
18152                      , p_debug_on                   => l_debug_on
18153                      , p_needed_sec_quantity        => l_sec_needed_quantity
18154                      , p_secondary_uom              => p_secondary_uom
18155                      , p_grade_code                 => p_grade_code
18156                      , x_inserted_record            => l_inserted_record
18157                      , x_allocated_quantity         => l_allocated_quantity
18158                      , x_remaining_quantity         => l_remaining_quantity
18159                      , x_sec_allocated_quantity     => l_sec_allocated_quantity
18160                      , x_sec_remaining_quantity     => l_sec_remaining_quantity
18161                      );
18162                  ELSIF p_tree_id is NULL THEN  -- Call the new local procedure validate_and_insert_noqtytree() for bug #4006426
18163 
18164                        IF l_debug = 1 THEN
18165                           log_statement(l_api_name, 'Calling validateNinsert', '');
18166                        END IF;
18167 
18168                          ValidNinsert(
18169                              x_return_status              => x_return_status
18170                            , x_msg_count                  => x_msg_count
18171                            , x_msg_data                   => x_msg_data
18172                            , p_record_id                  => l_cur_rec
18173                            , p_needed_quantity            => l_needed_quantity
18174                            , p_use_pick_uom               => FALSE
18175                            , p_organization_id            => p_organization_id
18176                            , p_inventory_item_id          => p_inventory_item_id
18177                            , p_to_subinventory_code       => l_to_subinventory_code
18178                            , p_to_locator_id              => l_to_locator_id
18179                            , p_to_cost_group_id           => l_to_cost_group_id
18180                            , p_primary_uom                => p_primary_uom
18181                            , p_transaction_uom            => p_transaction_uom
18182                            , p_transaction_temp_id        => p_transaction_temp_id
18183                            , p_type_code                  => p_type_code
18184                            , p_rule_id                    => 0
18185                            , p_reservation_id             => l_reservation_id
18186                            , p_tree_id                    => l_tree_id
18187                            , p_debug_on                   => l_debug_on
18188                            , x_inserted_record            => l_inserted_record
18189                            , x_allocated_quantity         => l_allocated_quantity
18190                            , x_remaining_quantity         => l_remaining_quantity
18191                            );
18192                  END IF;
18193 
18194                    IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
18195                       IF l_debug = 1 THEN
18196                                 log_statement(l_api_name, 'uerr_validate_insert',
18197                                         'Unexpected error in validate_and_insert');
18198                          END IF;
18199                          RAISE fnd_api.g_exc_unexpected_error;
18200                       ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
18201                          IF l_debug = 1 THEN
18202                             log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
18203                          END IF;
18204                          RAISE fnd_api.g_exc_error;
18205                       END IF;
18206 
18207                       --IF l_inserted_record = FALSE   OR l_allocated_quantity < l_needed_quantity THEN
18208                       IF l_inserted_record = FALSE  OR ABS(l_allocated_quantity - l_needed_quantity) > 0.00005
18209                       THEN     -- made by when testing 13591755
18210                          fnd_message.set_name('WMS', 'WMS_LPN_UNAVAILABLE');  --- to be Added to Mesg Dict
18211                          fnd_msg_pub.ADD;
18212                          fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18213                          IF l_debug = 1 THEN
18214                           log_error_msg(l_api_name, x_msg_data);
18215                          END IF;
18216 
18217                          WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_LPN_UNAVAILABLE';
18218                          IF p_tree_id IS NOT NULL THEN  -- Bug# 4006426
18219 
18220                              IF l_debug = 1 THEN
18221                                 log_statement(l_api_name, 'insert_failed', 'Record failed to allocation.  Rolling back and ' || 'invalidating LPN');
18222                                 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
18223                              END IF;
18224                              inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
18225                          END IF; -- Bug # 4006426
18226 
18227                             IF l_debug = 1 THEN   --13965992
18228                                 log_statement(l_api_name, 'insert_failed', 'Rolling back');
18229                             END IF;
18230                             RAISE fnd_api.g_exc_unexpected_error;    --13965992
18231                        END IF;
18232 
18233                          IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
18234                             IF l_debug = 1 THEN
18235                                log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
18236                             END IF;
18237                             RAISE fnd_api.g_exc_unexpected_error;
18238                          ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
18239                             IF l_debug = 1 THEN
18240                                log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
18241                             END IF;
18242                             RAISE fnd_api.g_exc_error;
18243                          END IF;
18244                       ELSE
18245 
18246                          IF (  l_allowed =  'N') then
18247                                WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SUB_STATUS_NA';
18248                                fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
18249                                fnd_msg_pub.ADD;
18250 
18251                                fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18252                                IF l_debug = 1 THEN
18253                                   log_error_msg(l_api_name, x_msg_data);
18254                                END IF;
18255 
18256                          ELSIF l_serial_allowed =  'N' then
18257                                WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SERIAL_STATUS_NA' ;
18258                                fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
18259                                fnd_msg_pub.ADD;
18260                                fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18261 
18262                                IF l_debug = 1 THEN
18263                                   log_error_msg(l_api_name, x_msg_data);
18264                                END IF;
18265                          END IF;
18266                       END IF;
18267 
18268                    -- <<nextoutputrecord>>
18269                    l_cur_rec  := g_locs(l_cur_rec).next_rec;
18270 
18271                 END LOOP;
18272       EXCEPTION
18273           WHEN fnd_api.g_exc_error THEN
18274 
18275                 ROLLBACK TO QuickPicksp;
18276                 freeglobals;
18277                 x_return_status  := fnd_api.g_ret_sts_error;
18278                 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18279 
18280                 IF l_debug = 1 THEN
18281                    log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
18282                 END IF;
18283 
18284           WHEN fnd_api.g_exc_unexpected_error THEN
18285                 ROLLBACK TO QuickPicksp;
18286                 freeglobals;
18287                 x_return_status  := fnd_api.g_ret_sts_unexp_error;
18288                 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18289 
18290                 IF l_debug = 1 THEN
18291                    log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
18292                 END IF;
18293 
18294           WHEN OTHERS THEN
18295                 ROLLBACK TO QuickPicksp;
18296                 freeglobals;
18297                 x_return_status  := fnd_api.g_ret_sts_unexp_error;
18298                 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
18299                   fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
18300                 END IF;
18301                 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
18302 
18303                 IF l_debug = 1 THEN
18304                    log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
18305                 END IF;
18306       END QuickPick;
18307 
18308   -- LG convergence
18309   --
18310   -- API name    : get_available_inventory
18311   -- Type        : Private
18312   -- Function    : Applies a wms rule to the given transaction
18313   --               input parameters and creates recommendations
18314   -- Pre-reqs    : Record in WMS_STRATEGY_MAT_TXN_TMP_V uniquely
18315   --               identified by parameters p_transaction_temp_id and
18316   --               p_type_code ( base table for the view is
18317   --               MTL_MATERIAL_TRANSACTIONS_TEMP );
18318   --               At least one transaction detail record in
18319   --               WMS_TRX_DETAILS_TMP_V identified by line type code = 1
18320   --               and parameters p_transaction_temp_id and p_type_code
18321   --               ( base tables are MTL_MATERIAL_TRANSACTIONS_TEMP and
18322   --               WMS_TRANSACTIONS_TEMP, respectively );
18323   --               Rule record has to exist in WMS_RULES_B uniquely
18324   --               identified by parameter p_rule_id;
18325   --     Package WMS_RULE_(RULEID) must exist;
18326   --               If picking, quantity tree has to exist, created through
18327   --               INV_Quantity_Tree_PVT.Create_Tree and uniquely identified
18328   --               by parameter p_tree_id
18329   -- Parameters  :
18330   --   p_api_version          Standard Input Parameter
18331   --   p_init_msg_list        Standard Input Parameter
18332   --   p_commit               Standard Input Parameter
18333   --   p_validation_level     Standard Input Parameter
18334   --   p_rule_id              Identifier of the rule to apply
18335   --   p_type_code            Type code of the rule
18336   --   p_partial_success_allowed_flag
18337   --            'Y' or 'N'
18338   --   p_transaction_temp_id  Identifier for the record in view
18339   --            wms_strategy_mat_txn_tmp_v that represents
18340   --            the request for detailing
18341   --   p_organization_id      Organization identifier
18342   --   p_inventory_item_id    Inventory item identifier
18343   --   p_transaction_uom      Transaction UOM code
18344   --   p_primary_uom          Primary UOM code
18345   --   p_tree_id              Identifier for the quantity tree
18346   --
18347   -- Output Parameters
18348   --   x_return_status        Standard Output Parameter
18349   --   x_msg_count            Standard Output Parameter
18350   --   x_msg_data             Standard Output Parameter
18351   --   x_finished             whether the rule has found enough quantity to
18352   --                          find a location that completely satisfy
18353   --                          the requested quantity (value is 'Y' or 'N')
18354   --
18355   -- Version
18356   --   Currently version is 1.0
18357   --
18358   -- Notes       : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
18359   --               This API must be called internally by
18360   --               WMS_Strategy_PVT.Apply only !
18361   --APPLY
18362   PROCEDURE get_available_inventory(
18363     p_api_version                  IN            NUMBER
18364   , p_init_msg_list                IN            VARCHAR2
18365   , p_commit                       IN            VARCHAR2
18366   , p_validation_level             IN            NUMBER
18367   , x_return_status                OUT NOCOPY    VARCHAR2
18368   , x_msg_count                    OUT NOCOPY    NUMBER
18369   , x_msg_data                     OUT NOCOPY    VARCHAR2
18370   , p_rule_id                      IN            NUMBER
18371   , p_type_code                    IN            NUMBER
18372   , p_partial_success_allowed_flag IN            VARCHAR2
18373   , p_transaction_temp_id          IN            NUMBER
18374   , p_organization_id              IN            NUMBER
18375   , p_inventory_item_id            IN            NUMBER
18376   , p_transaction_uom              IN            VARCHAR2
18377   , p_primary_uom                  IN            VARCHAR2
18378   , p_transaction_type_id          IN            NUMBER
18379   , p_tree_id                      IN            NUMBER
18380   , x_finished                     OUT NOCOPY    VARCHAR2
18381   , p_detail_serial                IN            BOOLEAN
18382   , p_from_serial                  IN            VARCHAR2
18383   , p_to_serial                    IN            VARCHAR2
18384   , p_detail_any_serial            IN            NUMBER
18385   , p_unit_volume                  IN            NUMBER
18386   , p_volume_uom_code              IN            VARCHAR2
18387   , p_unit_weight                  IN            NUMBER
18388   , p_weight_uom_code              IN            VARCHAR2
18389   , p_base_uom_code                IN            VARCHAR2
18390   , p_lpn_id                       IN            NUMBER
18391   , p_unit_number                  IN            VARCHAR2
18392   , p_simulation_mode              IN            NUMBER
18393   , p_project_id                   IN            NUMBER
18394   , p_task_id                      IN            NUMBER
18395   ) IS
18396     -- API standard variables
18397     l_api_version   CONSTANT NUMBER                                              := 1.0;
18398     l_api_name      CONSTANT VARCHAR2(30)                                        := 'Apply';
18399     -- variables needed for dynamic SQL
18400     l_cursor                 INTEGER;
18401     l_rows                   INTEGER;
18402     -- rule dynamic SQL input variables
18403     l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE;
18404     l_revision               wms_transactions_temp.revision%TYPE  := null;
18405     l_lot_number             wms_transactions_temp.lot_number%TYPE  := null;
18406     l_lot_expiration_date    wms_transactions_temp.lot_expiration_date%TYPE;
18407     l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
18408     l_to_subinventory_code   wms_transactions_temp.to_subinventory_code%TYPE;
18409     l_subinventory_code      wms_transactions_temp.to_subinventory_code%TYPE;
18410     l_from_locator_id        wms_transactions_temp.from_locator_id%TYPE;
18411     l_to_locator_id          wms_transactions_temp.to_locator_id%TYPE;
18412     l_locator_id             wms_transactions_temp.to_locator_id%TYPE;
18413     l_from_cost_group_id     wms_transactions_temp.from_cost_group_id%TYPE;
18414     l_to_cost_group_id       wms_transactions_temp.to_cost_group_id%TYPE;
18415     l_cost_group_id          wms_transactions_temp.to_cost_group_id%TYPE;
18416     l_lpn_id                 wms_transactions_temp.lpn_id%TYPE  := null;
18417     l_initial_pri_quantity   wms_transactions_temp.primary_quantity%TYPE;
18418     -- rule dynamic SQL output variables
18419     l_orevision              wms_transactions_temp.revision%TYPE;
18420     l_olot_number            wms_transactions_temp.lot_number%TYPE;
18421     l_olot_expiration_date   wms_transactions_temp.lot_expiration_date%TYPE;
18422     l_osubinventory_code     wms_transactions_temp.from_subinventory_code%TYPE;
18423     l_olocator_id            wms_transactions_temp.from_locator_id%TYPE;
18424     l_olocator_id_prev       wms_transactions_temp.from_locator_id%TYPE;
18425     l_olocator_id_new        wms_transactions_temp.from_locator_id%TYPE;
18426     l_ocost_group_id         wms_transactions_temp.from_cost_group_id%TYPE;
18427     l_olpn_id                wms_transactions_temp.lpn_id%TYPE;
18428     l_possible_quantity      wms_transactions_temp.primary_quantity%TYPE;
18429     l_possible_trx_qty       wms_transactions_temp.transaction_quantity%TYPE;
18430     l_reservation_id         wms_transactions_temp.reservation_id%TYPE;
18431     -- variables needed for qty tree
18432     l_qoh                    NUMBER;
18433     l_rqoh                   NUMBER;
18434     l_qr                     NUMBER;
18435     l_qs                     NUMBER;
18436     l_att                    NUMBER;
18437     l_atr                    NUMBER;
18438     --
18439     l_rule_func_sql          LONG;
18440     l_rule_result            NUMBER;
18441     l_dummy                  NUMBER;
18442     l_pack_exists            NUMBER;
18443     l_serial_control_code    NUMBER;
18444     l_is_serial_control      NUMBER;
18445     l_package_name           VARCHAR2(128);
18446     l_msg_data               VARCHAR2(240);
18447     l_msg_count              NUMBER;
18448     l_rule_id                NUMBER;
18449     l_unit_number            VARCHAR2(30);
18450     --variables related to pick by UOM
18451     l_uom_code               VARCHAR2(3);
18452     l_order_by_string        VARCHAR2(1000);
18453     l_consist_string         VARCHAR2(1000);
18454     l_cur_order_by_string    VARCHAR2(1000)                                      := '-9999999';
18455     l_default_pick_rule      NUMBER;
18456     l_default_put_rule       NUMBER;
18457     l_allowed                VARCHAR2(1);
18458     l_loc_avail_units        NUMBER;
18459     l_capacity_updated       BOOLEAN;
18460     l_consider_staging_capacity   BOOLEAN; --Added bug3237702
18461     l_return_status          VARCHAR2(1);
18462     l_consist_exists         BOOLEAN;
18463     l_comingle               VARCHAR2(1);
18464     l_serial_number          VARCHAR2(30);
18465     l_detail_serial          NUMBER;
18466     l_found                  BOOLEAN;
18467     l_first_serial           NUMBER;
18468     l_locs_index             NUMBER; --index to v_locs table
18469     l_debug_on               BOOLEAN;
18470     l_uom_index              NUMBER;
18471     l_lpn_controlled_flag    NUMBER;
18472     l_check_cg               BOOLEAN;
18473     l_restrict_subs_code     NUMBER;
18474     l_restrict_locs_code     NUMBER;
18475     l_quantity_function      NUMBER;
18476     v_current_row            t_location_rec;
18477     --added to support allocation mode
18478     l_cur_lpn_group          NUMBER;
18479     l_cur_lpn_rec            NUMBER;
18480     l_needed_quantity        NUMBER;
18481     l_inserted_record        BOOLEAN;
18482     l_expected_quantity      NUMBER;
18483     l_allocated_quantity     NUMBER;
18484     l_remaining_quantity     NUMBER;
18485     l_sec_inserted_record    BOOLEAN;                   -- new
18486     l_sec_expected_quantity  NUMBER;                    -- new
18487     l_sec_allocated_quantity NUMBER;                    -- new
18488     l_sec_remaining_quantity NUMBER;                    -- new
18489     l_sec_needed_quantity    NUMBER;                    -- new
18490     l_grade_code             VARCHAR2(150);             -- new
18491     l_allocation_mode        NUMBER;
18492     l_cur_uom_rec            NUMBER;
18493     l_first_uom_rec          NUMBER;
18494     l_last_uom_rec           NUMBER;
18495     l_finished               BOOLEAN;
18496     l_cur_consist_group      NUMBER;
18497     l_use_pick_uom           BOOLEAN;
18498     l_order_by_rank          NUMBER                                              := 0;
18499     l_cur_rec                NUMBER;
18500     l_prev_rec               NUMBER;
18501     l_next_rec               NUMBER;
18502     l_hash_size              NUMBER;
18503     l_sub_rsv_type             NUMBER;
18504 
18505     --added to support pjm
18506     l_project_id             NUMBER;
18507     l_oproject_id            NUMBER;
18508     l_task_id                NUMBER;
18509     l_otask_id               NUMBER;
18510     l_input_lpn_id           NUMBER;
18511     --- Initilization of Ref cursors for Pick and putaway rules
18512 -- Added to pass into DoProjectCheck new parameter used in other apply procedure  Bug3237702
18513     l_dummy_loc                NUMBER;
18514 
18515     v_pick_cursor            wms_rule_pvt.cv_pick_type;
18516     v_put_cursor             wms_rule_pvt.cv_put_type;
18517 
18518     l_debug                  NUMBER;   -- 1 for debug is on , 0 for debug is off
18519     l_progress                      VARCHAR2(10);  -- local variable to track program progress,
18520                                             -- especially useful when exception occurs
18521 
18522     l_default_inv_pick_rule    NUMBER;      --added for bug8310188
18523     l_wms_enabled_flag         VARCHAR2(1); --added for bug8310188
18524     l_rule_override_flag       inv_cache.org_rec.rules_override_lot_reservation%TYPE; -- 8809951
18525     l_return_value             BOOLEAN;     -- 8809951
18526 
18527     --cursor used to determine if suggestions should be minimized
18528     -- for this rule.  This flag affects how the Pick UOM functionality
18529     -- works.
18530     CURSOR c_allocation_mode IS
18531       SELECT allocation_mode_id
18532            , qty_function_parameter_id
18533         FROM wms_rules_b
18534        WHERE rule_id = l_rule_id;
18535 
18536     --cursor used to determine if rule has any consistency requirements
18537     CURSOR l_consist IS
18538       SELECT consistency_id
18539         FROM wms_rule_consistencies
18540        WHERE rule_id = l_rule_id;
18541 
18542     --cursor to get the total quantity for the LPN
18543     CURSOR c_lpn_quantity IS
18544       SELECT SUM(primary_transaction_quantity)
18545         FROM mtl_onhand_quantities_detail
18546        WHERE lpn_id = v_current_row.lpn_id;
18547 
18548 
18549   BEGIN
18550     --
18551     l_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
18552     l_progress := 10;
18553     -- debugging portion
18554     -- can be commented ut for final code
18555     if nvl(inv_cache.is_pickrelease, FALSE) THEN
18556       If (l_debug = 1) then
18557        log_event(l_api_name, 'Check if Pick Release', 'True');
18558       End if;
18559       l_consider_staging_capacity := FALSE;
18560     else
18561       If (l_debug = 1) then
18562        log_event(l_api_name, 'Check if Pick Release', 'False');
18563       End if;
18564       l_consider_staging_capacity := TRUE;
18565     end if;
18566     IF inv_pp_debug.is_debug_mode THEN
18567       inv_pp_debug.send_message_to_pipe('enter '|| g_pkg_name || '.'
18568               || l_api_name);
18569     END IF;
18570     IF l_debug = 1 THEN
18571        log_procedure(l_api_name, 'start', 'Start Apply');
18572     END IF;
18573     -- end of debugging section
18574     --
18575     -- Standard start of API savepoint
18576     SAVEPOINT applyrulesp;
18577 
18578     -- Standard call to check for call compatibility
18579     IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
18580       RAISE fnd_api.g_exc_unexpected_error;
18581     END IF;
18582 
18583     -- Initialize message list if p_init_msg_list is set to TRUE
18584     IF fnd_api.to_boolean(p_init_msg_list) THEN
18585       fnd_msg_pub.initialize;
18586     END IF;
18587 
18588     --
18589     -- Initialize API return status to success
18590     x_return_status  := fnd_api.g_ret_sts_success;
18591     --
18592     -- Initialize functional return status to completed
18593     x_finished       := fnd_api.g_true;
18594 
18595     --
18596     -- Validate input parameters and pre-requisites, if validation level
18597     -- requires this
18598     IF p_validation_level <> fnd_api.g_valid_level_none THEN
18599       IF p_type_code IS NULL
18600          OR p_type_code = fnd_api.g_miss_num THEN
18601         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
18602           fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
18603           fnd_msg_pub.ADD;
18604           IF l_debug = 1 THEN
18605              log_error_msg(l_api_name, 'type_code_missing');
18606           END IF;
18607         END IF;
18608         RAISE fnd_api.g_exc_error;
18609     END IF;
18610 
18611     -- init variables
18612     l_revision      := null;
18613     l_lot_number    := null;
18614     l_lpn_id        := null;
18615 
18616       --changed by jcearley on 11/22/99, b/c a null rule_id is now allowed
18617       --  if rule_id is null, use default rule (0 for put away, 1 for pick)
18618 
18619       IF p_rule_id IS NULL OR p_rule_id = fnd_api.g_miss_num THEN
18620            --query org parameters to get user's default rule
18621            IF l_debug = 1 THEN
18622               log_statement(l_api_name,'no_rule','Getting default rule at org level');
18623            END IF;
18624            -- 8809951 removed cursor and using INV CACHE
18625            IF (INV_CACHE. set_org_rec(p_organization_id) ) THEN
18626                                 l_default_pick_rule         := inv_cache.org_rec.default_wms_picking_rule_id;
18627                                 l_default_put_rule          := inv_cache.org_rec.default_put_away_rule_id;
18628                                 l_rule_override_flag        := inv_cache.org_rec.rules_override_lot_reservation;
18629                                 l_default_inv_pick_rule   := inv_cache.org_rec.default_picking_rule_id;
18630                                 l_wms_enabled_flag       := inv_cache.org_rec.wms_enabled_flag;
18631             END If;
18632 
18633            --if default rule not defined, use default seeded rule
18634            IF p_type_code = 1 THEN --put away
18635              l_rule_id  := l_default_put_rule;
18636 
18637              IF l_rule_id IS NULL THEN
18638                 IF l_debug = 1 THEN
18639                    log_statement(l_api_name, 'no_org_rule_put',
18640                        'Did not find org default put away rule');
18641                 END IF;
18642                 l_rule_id  := 10;
18643              END IF;
18644             ELSE --pick
18645              --start adding for bug8310188
18646               IF l_wms_enabled_flag ='Y' THEN
18647                l_rule_id  := l_default_pick_rule;
18648               ELSE
18649                l_rule_id  := l_default_inv_pick_rule;
18650               END IF ;
18651             --End adding for bug8310188
18652              IF l_rule_id IS NULL THEN
18653                 IF l_debug = 1 THEN
18654                    log_statement(l_api_name, 'no_org_rule_put',
18655                        'Did not find org default put away rule');
18656                 END IF;
18657                 l_rule_id  := 2;
18658              END IF;
18659            END IF;
18660            IF l_debug = 1 THEN
18661               log_statement(l_api_name, 'default_rule',
18662                  'Rule being used: ' || l_rule_id);
18663            END IF;
18664       ELSE
18665         l_rule_id  := p_rule_id;
18666       END IF;
18667 
18668       /* Lgao, Bug 5141737 select available will not check this flag, not used */
18669       /*IF p_partial_success_allowed_flag IS NULL
18670          OR p_partial_success_allowed_flag = fnd_api.g_miss_char THEN
18671         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
18672           fnd_message.set_name('WMS', 'WMS_PARTIAL_SUCC_FLAG_MISS');
18673 
18674            IF l_debug = 1 THEN
18675               log_error_msg(l_api_name, 'partial_succ_flag_missing');
18676            END IF;
18677           fnd_msg_pub.ADD;
18678         END IF;
18679 
18680         RAISE fnd_api.g_exc_error;
18681       END IF;
18682       */
18683 
18684       IF p_transaction_temp_id IS NULL
18685          OR p_transaction_temp_id = fnd_api.g_miss_num THEN
18686         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
18687           fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
18688           fnd_msg_pub.ADD;
18689            IF l_debug = 1 THEN
18690               log_error_msg(l_api_name, 'trx_req_line_id_missing');
18691            END IF;
18692 
18693         END IF;
18694 
18695         RAISE fnd_api.g_exc_error;
18696       END IF;
18697 
18698       IF p_organization_id IS NULL
18699          OR p_organization_id = fnd_api.g_miss_num THEN
18700         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
18701           fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
18702           fnd_msg_pub.ADD;
18703           IF l_debug = 1 THEN
18704              log_error_msg(l_api_name, 'org_id_missing');
18705           END IF;
18706         END IF;
18707 
18708         RAISE fnd_api.g_exc_error;
18709       END IF;
18710 
18711       IF p_inventory_item_id IS NULL
18712          OR p_inventory_item_id = fnd_api.g_miss_num THEN
18713         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
18714           fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
18715           fnd_msg_pub.ADD;
18716           IF l_debug = 1 THEN
18717              log_error_msg(l_api_name, 'item_id_missing');
18718           END IF;
18719         END IF;
18720 
18721         RAISE fnd_api.g_exc_error;
18722       END IF;
18723 
18724       IF  p_type_code = 2
18725           AND (p_tree_id IS NULL
18726                OR p_tree_id = fnd_api.g_miss_num
18727               ) THEN
18728         IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
18729           fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
18730           fnd_msg_pub.ADD;
18731 
18732           IF l_debug = 1 THEN
18733              log_error_msg(l_api_name, 'qty_tree_id_missing');
18734           END IF;
18735         END IF;
18736 
18737         RAISE fnd_api.g_exc_error;
18738       END IF;
18739     END IF;
18740 
18741     --inv_pp_debug.send_message_to_pipe('finished validations and qty tree init');
18742 
18743     --
18744     -- backup qty tree
18745     IF p_type_code = 2 THEN
18746        IF l_debug = 1 THEN
18747           log_statement(l_api_name, 'backup_tree',
18748                  'Calling inv_quantity_tree_pvt.backup_tree');
18749        END IF;
18750        inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
18751 
18752        IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
18753            IF l_debug = 1 THEN
18754               log_statement(l_api_name, 'backup_tree_unexp_err',
18755                  'Unexpected error from inv_quantity_tree_pvt.backup_tree');
18756            END IF;
18757 
18758            RAISE fnd_api.g_exc_unexpected_error;
18759         ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
18760            IF l_debug = 1 THEN
18761                  log_statement(l_api_name, 'backup_tree_err',
18762                        'Error from inv_quantity_tree_pvt.backup_tree');
18763            END IF;
18764            RAISE fnd_api.g_exc_error;
18765         END IF;
18766 
18767         --does the rule have any consistency restrictions?
18768         OPEN l_consist;
18769         FETCH l_consist INTO l_dummy;
18770 
18771         IF l_consist%NOTFOUND THEN
18772            l_consist_exists  := FALSE;
18773 
18774            IF l_debug = 1 THEN
18775               log_statement(l_api_name, 'consist_exist_false',
18776                     'Consistencies do not exist');
18777            END IF;
18778         ELSE
18779            l_consist_exists  := TRUE;
18780 
18781            IF l_debug = 1 THEN
18782               log_statement(l_api_name, 'consist_exist_true', 'Consistencies exist');
18783            END IF;
18784 
18785         END IF;
18786         CLOSE l_consist;
18787     END IF;
18788 
18789     --
18790 
18791     --Get allocation mode
18792     OPEN c_allocation_mode;
18793     FETCH c_allocation_mode INTO l_allocation_mode, l_quantity_function;
18794 
18795     IF c_allocation_mode%NOTFOUND
18796        OR l_allocation_mode IS NULL THEN
18797       --by default, make allocation mode 3
18798       l_allocation_mode  := 3;
18799     END IF;
18800 
18801     CLOSE c_allocation_mode;
18802 
18803     IF l_allocation_mode IN (3, 4, 5) THEN
18804       l_use_pick_uom  := TRUE;
18805     ELSE
18806       l_use_pick_uom  := FALSE;
18807     END IF;
18808 
18809     -- make sure, everything is clean
18810     freeglobals;
18811     wms_parameter_pvt.clearcache;
18812     --
18813     g_trace_recs.DELETE;
18814     l_debug_on       := isruledebugon(p_simulation_mode);
18815     --query items table to see if item is serial controlled (picking) or if it
18816     -- restricts subs or locators (putaway)
18817     -- 8809951 start removed cursor and using INV CACHE
18818       l_return_value := INV_CACHE.set_item_rec(
18819                                    p_organization_id,
18820                                    p_inventory_item_id);
18821       If NOT l_return_value Then
18822         If l_debug = 1 then
18823            log_statement(l_api_name, '-', 'Error setting from sub cache');
18824         end if;
18825         RAISE fnd_api.g_exc_unexpected_error;
18826       End If;
18827 
18828       l_serial_control_code         := NVL(inv_cache.item_rec.serial_number_control_code,1);
18829       l_restrict_subs_code          := NVL(inv_cache.item_rec.restrict_subinventories_code, 2);
18830       l_restrict_locs_code          := NVL(inv_cache.item_rec.restrict_locators_code, 2);
18831       -- 8809951 end
18832 
18833     -- Only detail serial numbers if they are prespecified or entered
18834     -- at inventory receipt for this item.
18835     IF p_type_code = 2 THEN --pick
18836       IF l_serial_control_code IN (2, 5) THEN
18837         l_is_serial_control  := 1;
18838       ELSE
18839         l_is_serial_control  := 0;
18840       END IF;
18841     ELSE
18842       l_is_serial_control  := 0;
18843     END IF;
18844 
18845     IF p_detail_serial = TRUE THEN
18846       l_detail_serial  := 1;
18847     ELSE
18848       l_detail_serial  := 0;
18849     END IF;
18850 
18851     IF l_debug = 1 THEN
18852        log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
18853        log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
18854     END IF;
18855 
18856     --get the name of the rule package
18857     getpackagename(l_rule_id, l_package_name);
18858     -- Initialize the pointer to the first trx detail input line
18859     wms_re_common_pvt.initinputpointer;
18860     --
18861     IF l_debug = 1 THEN
18862        log_statement(l_api_name, 'get line ', 'get line input');
18863     END IF;
18864       wms_re_common_pvt.getnextinputline(
18865         l_pp_transaction_temp_id
18866       , l_revision
18867       , l_lot_number
18868       , l_lot_expiration_date
18869       , l_from_subinventory_code
18870       , l_from_locator_id
18871       , l_from_cost_group_id
18872       , l_to_subinventory_code
18873       , l_to_locator_id
18874       , l_to_cost_group_id
18875       , l_needed_quantity
18876       , l_sec_needed_quantity
18877       , l_grade_code
18878       , l_reservation_id
18879       , l_serial_number -- [ new code ]
18880       , l_lpn_id
18881       );
18882 
18883     -- Loop through all the trx detail input lines
18884       IF l_debug = 1 THEN
18885               log_statement(l_api_name, 'input_rec', 'Got next input line');
18886               log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
18887               log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
18888               log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
18889               log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
18890               log_statement(l_api_name, 'input_cg', 'cg:' || l_from_cost_group_id);
18891               log_statement(l_api_name, 'input_tsub', 'tsub:' || l_to_subinventory_code);
18892               log_statement(l_api_name, 'input_tloc', 'tloc:' || l_to_locator_id);
18893               log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
18894               log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
18895               log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
18896               log_statement(l_api_name, 'input_qty', 'sec qty:' || l_sec_needed_quantity);
18897 
18898       END IF;
18899 
18900       IF ((p_project_id IS NOT NULL) AND (l_to_locator_id IS NOT NULL) AND (p_type_code = 1)) THEN
18901         --bug 2400549 - for WIP backflush transfer putaway,
18902         --always use the locator specified on the move order line, even
18903         --if that locator is from common stock (not project)
18904         -- Bug 2666620: BackFlush MO Type Removed. It is now 5. Moreover Txn Action ID is 2 which is
18905         --              already handled.
18906         IF NOT (wms_engine_pvt.g_move_order_type = 5 AND wms_engine_pvt.g_transaction_action_id = 2) THEN
18907 
18908            IF l_debug = 1 THEN
18909               log_statement(l_api_name, 'do_project1', 'Calling do project check');
18910            END IF;
18911 
18912           IF doprojectcheck(l_return_status, l_to_locator_id, p_project_id, p_task_id, l_to_locator_id, l_dummy_loc) THEN
18913 
18914             IF l_debug = 1 THEN
18915                log_statement(l_api_name, 'do_project1_success', 'Do Project Check passed');
18916             END IF;
18917 
18918             NULL;
18919           END IF;
18920         END IF;
18921       END IF;
18922 
18923       --
18924       -- Save the initial input qty for later usage
18925       l_initial_pri_quantity  := l_needed_quantity;
18926       --
18927       l_input_lpn_id          := l_lpn_id;
18928 
18929       IF p_type_code = 2 THEN
18930         --check for null values.  NULL produces error in stored procedure,
18931         --  so we treat -9999 as NULL;
18932         -- since revision is varchar(3), use -99
18933         -- we only want to overwrite revision and lot for pick rules, since
18934         -- we use these values in putaway.
18935         IF (l_revision IS NULL) THEN
18936           --gmi_reservation_util.println('l_revision is null');
18937           l_revision  := '-99';
18938         END IF;
18939 
18940         IF (l_lot_number IS NULL) THEN
18941           l_lot_number  := '-9999';
18942         END IF;
18943       END IF;
18944 
18945       IF (p_type_code = 2) THEN --pick
18946         l_subinventory_code  := l_from_subinventory_code;
18947         l_locator_id         := l_from_locator_id;
18948         l_cost_group_id      := l_from_cost_group_id;
18949       ELSE --put away
18950         l_subinventory_code  := l_to_subinventory_code;
18951         l_locator_id         := l_to_locator_id;
18952         l_cost_group_id      := l_to_cost_group_id;
18953       END IF;
18954 
18955       IF (l_subinventory_code IS NULL) THEN
18956         l_subinventory_code  := '-9999';
18957       END IF;
18958 
18959       IF (l_locator_id IS NULL) THEN
18960         l_locator_id  := -9999;
18961       END IF;
18962 
18963       IF (l_cost_group_id IS NULL) THEN
18964         l_cost_group_id  := -9999;
18965       END IF;
18966 
18967       IF (l_lpn_id IS NULL) THEN
18968         l_lpn_id  := -9999;
18969       END IF;
18970 
18971       IF (p_project_id IS NULL) THEN
18972         l_project_id  := -9999;
18973       ELSE
18974         l_project_id  := p_project_id;
18975       END IF;
18976 
18977       IF (p_task_id IS NULL) THEN
18978         l_task_id  := -9999;
18979       ELSE
18980         l_task_id  := p_task_id;
18981       END IF;
18982 
18983       IF (p_unit_number IS NULL) THEN
18984         l_unit_number  := '-9999';
18985       ELSE
18986         l_unit_number  := p_unit_number;
18987       END IF;
18988 
18989       IF l_debug = 1 THEN
18990          log_statement(l_api_name, 'calling_open_curs', 'Calling open_curs');
18991       END IF;
18992 
18993       -- Bug# 2430429
18994       -- The call to open_curs was not using bind variables.
18995       -- This was causing performance problems
18996 
18997       -- l_cursor := dbms_sql.open_cursor;
18998       --build dynamic PL/SQL for call to stored procedure;
18999       -- open_curs opens the appropriate cursor for the rule;
19000       -- this call has to be dynamic because of the name of the rule package
19001       IF p_type_code = 2 THEN
19002          --pick_open_curs
19003          --inv_pp_debug.send_message_to_pipe('Calling **pick_open_curs ** wms_rule_pick_pkg1.execute');
19004          IF (l_revision IS NULL) THEN
19005            --gmi_reservation_util.println('l_revision is null');
19006            l_revision  := '-99';
19007          END IF;
19008 
19009          IF (l_lot_number IS NULL) THEN
19010            l_lot_number  := '-9999';
19011          END IF;
19012          IF (l_lpn_id IS NULL) THEN
19013             l_lpn_id  := -9999;
19014          END IF;
19015          IF l_debug = 1 THEN
19016                 log_statement(l_api_name, 'pick_open_rule :l_rule_id ', l_rule_id);
19017                 log_statement(l_api_name, 'pick_open_rule :p_organization_id ', p_organization_id);
19018                 log_statement(l_api_name, 'pick_open_rule :p_inventory_item_id ',  p_inventory_item_id);
19019                 log_statement(l_api_name, 'pick_open_rule :p_transaction_type_id ',  p_transaction_type_id);
19020                 log_statement(l_api_name, 'pick_open_rule :l_revision ',  l_revision);
19021                 log_statement(l_api_name, 'pick_open_rule :l_lot_number ',  l_lot_number);
19022                 log_statement(l_api_name, 'pick_open_rule :l_from_subinventory_code ',  l_subinventory_code);
19023                 log_statement(l_api_name, 'pick_open_rule :l_locator_id ',  l_locator_id);
19024                 log_statement(l_api_name, 'pick_open_rule :l_cost_group_id ',  l_cost_group_id);
19025                 log_statement(l_api_name, 'pick_open_rule :l_pp_transaction_temp_id ',  l_pp_transaction_temp_id);
19026                 log_statement(l_api_name, 'pick_open_rule :l_is_serial_control ', l_is_serial_control);
19027                 log_statement(l_api_name, 'pick_open_rule :l_detail_serial ',  l_detail_serial);
19028                 log_statement(l_api_name, 'pick_open_rule :p_detail_any_serial ',  p_detail_any_serial);
19029                 log_statement(l_api_name, 'pick_open_rule :p_from_serial ', p_from_serial);
19030                 log_statement(l_api_name, 'pick_open_rule :p_to_serial ', p_to_serial);
19031                 log_statement(l_api_name, 'pick_open_rule :l_unit_number ',  l_unit_number);
19032                 log_statement(l_api_name, 'pick_open_rule :l_lpn_id ',  l_lpn_id);
19033                 log_statement(l_api_name, 'pick_open_rule :l_project_id ',  l_project_id);
19034                 log_statement(l_api_name, 'pick_open_rule :l_task_id ',  l_task_id);
19035                 log_statement(l_api_name, 'pick_open_rule  :l_rule_result ',l_rule_result);
19036           END IF;
19037           pick_open_rule(
19038             v_pick_cursor
19039           , l_rule_id
19040           , p_organization_id
19041           , p_inventory_item_id
19042           , p_transaction_type_id
19043           , l_revision
19044           , l_lot_number
19045           , l_subinventory_code
19046           , l_locator_id
19047           , l_cost_group_id
19048           , l_pp_transaction_temp_id
19049           , l_is_serial_control
19050           , l_detail_serial
19051           , p_detail_any_serial
19052           , p_from_serial
19053           , p_to_serial
19054           , l_unit_number
19055           , l_lpn_id
19056           , l_project_id
19057           , l_task_id
19058           , l_rule_result
19059           );
19060         --gmi_reservation_util.println('after open rule');
19061           fetchcursorrows(
19062               x_return_status
19063             , x_msg_count
19064             , x_msg_data
19065             , v_pick_cursor
19066             , l_rule_id
19067             );
19068         close_pick_rule(l_rule_id, v_pick_cursor);
19069 
19070         /*FETCH v_pick_cursor bulk collect INTO
19071         WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl;
19072         */
19073         /*FOR i IN 1..WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT
19074         LOOP
19075             WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).organization_id := p_organization_id;
19076             WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).inventory_item_id := p_inventory_item_id;
19077         END LOOP;
19078         gmi_reservation_util.println('fetch the rows, return rows number'
19079                       ||WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT);
19080         FOR i IN 1..WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT
19081         LOOP
19082           gmi_reservation_util.println('fetch the rows, 2nd qty '
19083                       ||WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).secondary_onhand_qty);
19084         end loop;
19085         */
19086      END IF;
19087   EXCEPTION
19088     /*WHEN INVALID_PKG_STATE THEN
19089       x_return_status  := fnd_api.g_ret_sts_unexp_error;
19090       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
19091       fnd_message.set_token('LIST_PKG',  l_list_pkg);
19092       fnd_message.set_token('RULE_NAME', l_package_name);
19093       fnd_msg_pub.ADD;
19094       log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
19095                             || l_list_pkg || ' / ' || l_package_name);
19096      */
19097     WHEN OTHERS THEN
19098       x_return_status  := fnd_api.g_ret_sts_unexp_error;
19099 
19100       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
19101         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
19102       END IF;
19103 
19104       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
19105       --
19106       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
19107 
19108       -- debugging portion
19109       -- can be commented ut for final code
19110       IF inv_pp_debug.is_debug_mode THEN
19111         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
19112         -- the message retrieved here since it is no longer on the stack
19113         inv_pp_debug.set_last_error_message(SQLERRM);
19114         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
19115         inv_pp_debug.send_last_error_message;
19116       END IF;
19117   -- end of debugging section
19118   END get_available_inventory;
19119 
19120   PROCEDURE FetchCursorRows(
19121     x_return_status       OUT NOCOPY    VARCHAR2
19122   , x_msg_count           OUT NOCOPY    NUMBER
19123   , x_msg_data            OUT NOCOPY    VARCHAR2
19124   , p_cursor              IN            wms_rule_pvt.cv_pick_type
19125   , p_rule_id             IN            NUMBER
19126   ) IS
19127     invalid_pkg_state  exception;
19128     Pragma Exception_Init(invalid_pkg_state, -6508);
19129 
19130     l_list_pkg     VARCHAR2(30);
19131 
19132     l_api_name     VARCHAR2(30)  := 'FetchCursor';
19133     l_rows         NUMBER;
19134     l_func_sql     VARCHAR(1000);
19135     l_cursor       NUMBER;
19136     l_dummy        NUMBER;
19137     l_package_name VARCHAR2(128);
19138     l_ctr          NUMBER        := 0;
19139 
19140 
19141   BEGIN
19142     -- Initialize API return status to success
19143     x_return_status  := fnd_api.g_ret_sts_success;
19144 
19145     --
19146     -- debugging portion
19147     -- can be commented ut for final code
19148     IF inv_pp_debug.is_debug_mode THEN
19149       inv_pp_debug.send_message_to_pipe('enter '|| g_pkg_name || '.' || l_api_name);
19150     END IF;
19151 
19152     log_procedure(l_api_name, 'start', 'Start FetchCursorrows');
19153     -- end of debugging section
19154     --
19155 
19156     --get package name based on rule id
19157     getpackagename(p_rule_id, l_package_name);
19158     log_statement(l_package_name,  'package_name ', l_package_name);
19159     --- calling the static fetch cursor. The name of the rule package will be
19160     --- determined based on the rule_id
19161     --- If the ctr is 1 then there is no subscript ,
19162     --- if ctr = 2 then subscript = 1
19163     --- and if ctr = 3 then subscript = 2, this script is added to the package
19164     --- name.
19165     l_ctr        := wms_rule_gen_pkgs.get_count_no_lock('PICK');
19166     l_list_pkg   :=  'wms_rule_pick_pkg' || l_ctr ;
19167     log_statement(l_package_name,  'l_ctr ', l_ctr);
19168     --log_statement(l_package_name,  'p_cursor ', p_cursor);
19169 
19170     IF (l_ctr = 1) THEN
19171 
19172       wms_rule_pick_pkg1.execute_fetch_available_inv(
19173         p_cursor
19174       , p_rule_id
19175       , x_return_status
19176       );
19177     ELSIF (l_ctr = 2) THEN
19178 
19179       wms_rule_pick_pkg2.execute_fetch_available_inv(
19180         p_cursor
19181       , p_rule_id
19182       , x_return_status
19183       );
19184     ELSIF (l_ctr = 3) THEN
19185       wms_rule_pick_pkg3.execute_fetch_available_inv(
19186         p_cursor
19187       , p_rule_id
19188       , x_return_status
19189       );
19190     END IF;
19191 
19192     IF inv_pp_debug.is_debug_mode THEN
19193       inv_pp_debug.send_message_to_pipe('exit '|| g_pkg_name || '.' || l_api_name);
19194     END IF;
19195     -- end of debugging section
19196     log_procedure(l_api_name, 'end', 'End FetchCursorrows');
19197   --
19198   EXCEPTION
19199     WHEN INVALID_PKG_STATE THEN
19200       x_return_status  := fnd_api.g_ret_sts_unexp_error;
19201       fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
19202       fnd_message.set_token('LIST_PKG',  l_list_pkg);
19203       fnd_message.set_token('RULE_NAME', l_package_name);
19204       fnd_msg_pub.ADD;
19205       log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
19206                             || l_list_pkg || ' / ' || l_package_name);
19207 
19208     WHEN OTHERS THEN
19209       x_return_status  := fnd_api.g_ret_sts_unexp_error;
19210 
19211       IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
19212         fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
19213       END IF;
19214 
19215       fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
19216       --
19217       log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
19218 
19219       -- debugging portion
19220       -- can be commented ut for final code
19221       IF inv_pp_debug.is_debug_mode THEN
19222         -- Note: in debug mode, later call to fnd_msg_pub.get will not get
19223         -- the message retrieved here since it is no longer on the stack
19224         inv_pp_debug.set_last_error_message(SQLERRM);
19225         inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
19226         inv_pp_debug.send_last_error_message;
19227       END IF;
19228   -- end of debugging section
19229   END FetchCursorRows;
19230   -- end LG convergence
19231 
19232   --Added for Bug9669364
19233 FUNCTION match_planning_group(p_organization_id  IN NUMBER,
19234           p_locator_id   IN NUMBER,
19235           p_g_project_id     IN NUMBER,
19236           p_mo_project_id       IN NUMBER DEFAULT NULL,
19237           p_mo_task_id          IN NUMBER DEFAULT NULL,
19238           p_transaction_type_id IN NUMBER DEFAULT NULL,-- Added for Bug 10379126
19239           p_inventory_item_id   IN NUMBER DEFAULT NULL,-- Added for Bug 10379126
19240           p_moqd_project_id     IN NUMBER DEFAULT NULL,-- Added for Bug 10379126
19241           p_moqd_task_id        IN NUMBER DEFAULT NULL -- Added for Bug 10379126
19242 ) RETURN NUMBER IS
19243 
19244 
19245 l_api_name     VARCHAR2(30)  := 'Match_Planning_Group';
19246 l_result    BOOLEAN;
19247 l_g_project_id   NUMBER := p_g_project_id;
19248 l_mo_task_id    NUMBER;
19249 l_proj_ref_enabled NUMBER;
19250 l_wms_enabled_flag VARCHAR2(1); --Added for Bug 12585446
19251 --Added for Bug 12571993
19252 l_organization_id NUMBER;
19253 l_update BOOLEAN := FALSE;
19254 
19255 BEGIN
19256 
19257   IF inv_cache.set_org_rec(p_organization_id) THEN
19258    l_proj_ref_enabled := inv_cache.org_rec.project_reference_enabled;
19259    l_wms_enabled_flag := inv_cache.org_rec.wms_enabled_flag; -- Added for Bug 12585446
19260   END IF;
19261 
19262 
19263  IF l_proj_ref_enabled is null or l_proj_ref_enabled <> 1 THEN
19264   RETURN 1;
19265  END IF;
19266 
19267  IF (p_mo_task_id = -9999 OR p_mo_task_id = -7777) THEN
19268     l_mo_task_id := NULL;
19269   ELSE
19270   l_mo_task_id :=  p_mo_task_id;
19271 END IF;
19272 
19273 -- Added for Bug 12571993
19274  fnd_profile.get('MFG_ORGANIZATION_ID',l_organization_id );
19275  IF(Nvl(l_organization_id,-9999) <> p_organization_id) THEN
19276   fnd_profile.put('MFG_ORGANIZATION_ID',p_organization_id);
19277   l_update := TRUE;
19278  END IF;
19279 
19280  -- Added for Bug 10379126
19281  IF (p_transaction_type_id = INV_GLOBALS.G_TYPE_XFER_ORDER_WIP_ISSUE
19282  or p_transaction_type_id = INV_GLOBALS.G_TYPE_XFER_ORDER_REPL_SUBXFR) THEN
19283  l_result := pjm_project_locator.Check_Project_References(
19284                                          p_organization_id,
19285                                          p_locator_id,
19286                                          'SPECIFIC',
19287                                          'N',
19288                                          p_mo_project_id ,
19289                                          l_mo_task_id,
19290                                          p_inventory_item_id);
19291 
19292  ELSIF (((l_g_project_id = -9999 OR l_g_project_id = -7777 OR l_g_project_id IS NULL) AND p_mo_project_id IS NOT NULL)
19293          OR (p_mo_project_id IS NOT NULL AND p_moqd_project_id = p_mo_project_id AND p_moqd_task_id = l_mo_task_id)) THEN
19294   -- This is the case when allow cross project issue is Yes
19295   l_result := FALSE;
19296   l_result := pjm_project_locator.Check_Project_References(
19297                                          p_organization_id,
19298                                          p_locator_id,
19299                                          'SPECIFIC',
19300                                          'N',
19301                                          p_mo_project_id ,
19302                                          l_mo_task_id  );
19303 
19304  -- Added for Bug 12585446
19305  ELSIF (l_g_project_id = -7777 AND p_moqd_project_id IS NOT NULL AND l_wms_enabled_flag='N') THEN
19306    l_result := FALSE;
19307 
19308  ELSE
19309   RETURN 1;
19310  END IF;
19311 
19312  -- Added for Bug 12571993
19313   IF(l_update) THEN
19314    fnd_profile.put('MFG_ORGANIZATION_ID',l_organization_id);
19315   END IF;
19316 
19317   IF l_result THEN
19318       RETURN 1;
19319    ELSE
19320     RETURN 0;
19321  END IF;
19322 
19323 -- End of Changes for Bug 10379126
19324 
19325 EXCEPTION
19326 WHEN OTHERS THEN
19327      log_error(l_api_name, 'other_error', 'Exception in match_planning_group: ' || SQLERRM);
19328 END match_planning_group;
19329 
19330 
19331  -- Added for 14699845 (Flexible lot allocation)
19332  FUNCTION get_allocate_lot_flag( p_organization_id     IN NUMBER
19333                                , p_move_order_line_id  IN NUMBER DEFAULT NULL
19334                                , p_transaction_temp_id IN NUMBER DEFAULT NULL
19335                                , p_inventory_item_id   IN NUMBER DEFAULT NULL
19336                                , p_subinventory_code   IN VARCHAR2 DEFAULT NULL
19337                                , p_locator_id          IN NUMBER DEFAULT NULL
19338                                , p_revision            IN VARCHAR2 DEFAULT NULL
19339                                , p_lpn_id              IN NUMBER DEFAULT NULL
19340  ) RETURN VARCHAR2 IS
19341    l_allocate_lot_flag  VARCHAR2(1) := 'Y';
19342    l_api_name           VARCHAR2(30) := 'get_allocate_lot_flag';
19343    l_debug              NUMBER := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
19344  BEGIN
19345    IF l_debug = 1 THEN
19346       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_organization_id: '|| p_organization_id);
19347       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_move_order_line_id: '|| p_move_order_line_id);
19348       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_transaction_temp_id: '|| p_transaction_temp_id);
19349       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_inventory_item_id: '|| p_inventory_item_id);
19350       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_subinventory_code: '|| p_subinventory_code);
19351       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_locator_id: '|| p_locator_id);
19352       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_revision: '|| p_revision);
19353       log_statement(l_api_name, 'get_allocate_lot_flag', 'p_lpn_id: '|| p_lpn_id);
19354    END IF;
19355 
19356    IF inv_cache.set_org_rec(p_organization_id) THEN
19357       l_allocate_lot_flag := NVL (inv_flex_lot_allocation_pub.get_allocate_lot_flag
19358                                        ( p_organization_id     => p_organization_id
19359                                        , p_move_order_line_id  => p_move_order_line_id
19360                                        , p_transaction_temp_id => p_transaction_temp_id
19361                                        , p_inventory_item_id   => p_inventory_item_id
19362                                        , p_subinventory_code   => p_subinventory_code
19363                                        , p_locator_id          => p_locator_id
19364                                        , p_revision            => p_revision
19365                                        , p_lpn_id              => p_lpn_id)
19366                                  ,'Y');
19367    END IF;
19368 
19369    IF l_debug = 1 THEN
19370       log_statement(l_api_name, 'get_allocate_lot_flag', 'l_allocate_lot_flag: '|| l_allocate_lot_flag);
19371    END IF;
19372 
19373    RETURN l_allocate_lot_flag;
19374 
19375  EXCEPTION
19376     WHEN OTHERS THEN
19377        log_error(l_api_name, 'other_error', 'Exception in get_allocate_lot_flag: ' || SQLERRM);
19378        RETURN l_allocate_lot_flag;
19379 
19380  END get_allocate_lot_flag;
19381 
19382 END wms_rule_pvt;