[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;