[Home] [Help]
PACKAGE BODY: APPS.WMS_RULE_PVT
Source
1 PACKAGE BODY wms_rule_pvt AS
2 /* $Header: WMSVPPRB.pls 120.39.12010000.6 2009/01/21 10:32:10 avuppala ship $ */
3 --
4 -- File : WMSVPPRB.pls
5 -- Content : WMS_Rule_PVT package body
6 -- Description : wms rule private API's
7 -- Notes :
8 -- Modified : 02/08/99 mzeckzer created
9 -- 03/29/99 bitang modified
10 -- 01/17/99 jcearley added GenerateRulePackage function,
11 -- changed Apply to call stored function
12 -- 02/11/00 lezhang added AssignTT procedures for task type
13 -- assignment. Added CalcRuleWeight for this
14 -- functionality. Also modified GenerateRulePackage and
15 -- BuildRuleSQL.
16 --
17 -- 06/30/02 grao added procedures to call pick, putaway, task,
18 -- label rules statically. open cursor, fetch cursor and
19 -- cursor calls affected. All the current dynamic calls
20 -- to handle rules are disabled and not used any more.
21 -- APPLY(), AssignTT(), ASSIGNLABEL()
22 -- fetchcursor(), fetchPutaway() are modified.
23 --
24 -- 07/11/02 grao Modified the Rules package generating code to
25 -- conver all global variables in the rules packages to
26 -- local variables and defined Pick and Putaway cursors
27 -- as ref cursor, which is passed from the
28 -- WMS_RULE_PVT as a ref Cursor. Also modified the open,
29 -- fetch and close calls for Pick and Putaway rules
30
31 --
32 -- Package global variable that stores the package name
33 g_pkg_name CONSTANT VARCHAR2(30) := 'WMS_Rule_PVT';
34 --
35 -- API versions used within this API
36 g_qty_tree_api_version CONSTANT NUMBER := 1.0; -- INV_Quantity_Tree_PVT
37 --
38 -- Caching locator record in DoProjectCheck
39 g_locator_id NUMBER;
40 g_locator INV_VALIDATE.locator;
41 g_transaction_type_id NUMBER;
42 g_organization_id NUMBER;
43 g_inventory_item_id NUMBER;
44 g_subinventory_code WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
45 g_allowed VARCHAR2(1);
46 g_st_locator_id NUMBER;
47 g_lpn_controlled_flag NUMBER;
48
49 --g_serial_objects_used NUMBER ;
50
51 -- Caching in function getconversionrate
52 g_gcr_organization_id NUMBER;
53 g_gcr_inventory_item_id NUMBER;
54 g_gcr_uom_code VARCHAR2(3);
55 g_gcr_conversion_rate NUMBER;
56
57 g_debug NUMBER;
58 --
59 -- constants and global variables needed for dynamic SQL
60 --
61
62 /* LG. need to talk to gopal, for all the non restircted loc, should do an outter join*/
63 g_put_base_no_restrict LONG
64 := '
65 select msei.secondary_inventory_name subinventory_code --changed
66 ,mil.inventory_location_id locator_id
67 ,msei.organization_id organization_id --changed
68 ,mil.project_id project_id
69 ,mil.task_id task_id
70 ,g_inventory_item_id inventory_item_id
71 ,mil.location_current_units location_current_units
72 ,mil.inventory_item_id locator_inventory_item_id
73 ,mil.empty_flag empty_flag
74 ,mil.mixed_items_flag mixed_items_flag
75 ,mil.LAST_UPDATE_DATE
76 ,mil.LAST_UPDATED_BY
77 ,mil.CREATION_DATE
78 ,mil.CREATED_BY
79 ,mil.LAST_UPDATE_LOGIN
80 ,mil.DESCRIPTION
81 ,mil.DESCRIPTIVE_TEXT
82 ,mil.DISABLE_DATE
83 ,mil.INVENTORY_LOCATION_TYPE
84 ,mil.PICKING_ORDER
85 ,mil.PHYSICAL_LOCATION_CODE
86 ,mil.LOCATION_MAXIMUM_UNITS
87 ,mil.LOCATION_WEIGHT_UOM_CODE
88 ,mil.MAX_WEIGHT
89 ,mil.VOLUME_UOM_CODE
90 ,mil.MAX_CUBIC_AREA
91 ,mil.X_COORDINATE
92 ,mil.Y_COORDINATE
93 ,mil.Z_COORDINATE
94 ,mil.INVENTORY_ACCOUNT_ID
95 ,mil.SEGMENT1
96 ,mil.SEGMENT2
97 ,mil.SEGMENT3
98 ,mil.SEGMENT4
99 ,mil.SEGMENT5
100 ,mil.SEGMENT6
101 ,mil.SEGMENT7
102 ,mil.SEGMENT8
103 ,mil.SEGMENT9
104 ,mil.SEGMENT10
105 ,mil.SEGMENT11
106 ,mil.SEGMENT12
107 ,mil.SEGMENT13
108 ,mil.SEGMENT14
109 ,mil.SEGMENT15
110 ,mil.SEGMENT16
111 ,mil.SEGMENT17
112 ,mil.SEGMENT18
113 ,mil.SEGMENT19
114 ,mil.SEGMENT20
115 ,mil.SUMMARY_FLAG
116 ,mil.ENABLED_FLAG
117 ,mil.START_DATE_ACTIVE
118 ,mil.END_DATE_ACTIVE
119 ,mil.ATTRIBUTE_CATEGORY
120 ,mil.ATTRIBUTE1
121 ,mil.ATTRIBUTE2
122 ,mil.ATTRIBUTE3
123 ,mil.ATTRIBUTE4
124 ,mil.ATTRIBUTE5
125 ,mil.ATTRIBUTE6
126 ,mil.ATTRIBUTE7
127 ,mil.ATTRIBUTE8
128 ,mil.ATTRIBUTE9
129 ,mil.ATTRIBUTE10
130 ,mil.ATTRIBUTE11
131 ,mil.ATTRIBUTE12
132 ,mil.ATTRIBUTE13
133 ,mil.ATTRIBUTE14
134 ,mil.ATTRIBUTE15
135 ,mil.REQUEST_ID
136 ,mil.PROGRAM_APPLICATION_ID
137 ,mil.PROGRAM_ID
138 ,mil.PROGRAM_UPDATE_DATE
139 ,mil.PHYSICAL_LOCATION_ID
140 ,mil.PICK_UOM_CODE
141 ,mil.DIMENSION_UOM_CODE
142 ,mil.LENGTH
143 ,mil.WIDTH
144 ,mil.HEIGHT
145 ,mil.LOCATOR_STATUS
146 ,mil.STATUS_ID
147 ,mil.CURRENT_CUBIC_AREA
148 ,mil.AVAILABLE_CUBIC_AREA
149 ,mil.CURRENT_WEIGHT
150 ,mil.AVAILABLE_WEIGHT
151 ,mil.LOCATION_AVAILABLE_UNITS
152 ,mil.SUGGESTED_CUBIC_AREA
153 ,mil.SUGGESTED_WEIGHT
154 ,mil.LOCATION_SUGGESTED_UNITS
155 ,mil.rowid
156 from MTL_ITEM_LOCATIONS mil
157 ,MTL_SECONDARY_INVENTORIES msei
158 where mil.organization_id(+) = msei.organization_id
159 and mil.subinventory_code(+) = msei.secondary_inventory_name
160 and NVL(msei.disable_date, sysdate+1) > sysdate
161 and NVL(mil.disable_date, sysdate+1) > sysdate
162 ';
163 g_put_base_sub_restrict LONG
164 := '
165 select msei.secondary_inventory_name subinventory_code -- changed
166 ,mil.inventory_location_id locator_id
167 ,msei.organization_id organization_id -- changed
168 ,mil.project_id project_id
169 ,mil.task_id task_id
170 ,g_inventory_item_id inventory_item_id
171 ,mil.location_current_units location_current_units
172 ,mil.inventory_item_id locator_inventory_item_id
173 ,mil.empty_flag empty_flag
174 ,mil.mixed_items_flag mixed_items_flag
175 ,mil.LAST_UPDATE_DATE
176 ,mil.LAST_UPDATED_BY
177 ,mil.CREATION_DATE
178 ,mil.CREATED_BY
179 ,mil.LAST_UPDATE_LOGIN
180 ,mil.DESCRIPTION
181 ,mil.DESCRIPTIVE_TEXT
182 ,mil.DISABLE_DATE
183 ,mil.INVENTORY_LOCATION_TYPE
184 ,mil.PICKING_ORDER
185 ,mil.PHYSICAL_LOCATION_CODE
186 ,mil.LOCATION_MAXIMUM_UNITS
187 ,mil.LOCATION_WEIGHT_UOM_CODE
188 ,mil.MAX_WEIGHT
189 ,mil.VOLUME_UOM_CODE
190 ,mil.MAX_CUBIC_AREA
191 ,mil.X_COORDINATE
192 ,mil.Y_COORDINATE
193 ,mil.Z_COORDINATE
194 ,mil.INVENTORY_ACCOUNT_ID
195 ,mil.SEGMENT1
196 ,mil.SEGMENT2
197 ,mil.SEGMENT3
198 ,mil.SEGMENT4
199 ,mil.SEGMENT5
200 ,mil.SEGMENT6
201 ,mil.SEGMENT7
202 ,mil.SEGMENT8
203 ,mil.SEGMENT9
204 ,mil.SEGMENT10
205 ,mil.SEGMENT11
206 ,mil.SEGMENT12
207 ,mil.SEGMENT13
208 ,mil.SEGMENT14
209 ,mil.SEGMENT15
210 ,mil.SEGMENT16
211 ,mil.SEGMENT17
212 ,mil.SEGMENT18
213 ,mil.SEGMENT19
214 ,mil.SEGMENT20
215 ,mil.SUMMARY_FLAG
216 ,mil.ENABLED_FLAG
217 ,mil.START_DATE_ACTIVE
218 ,mil.END_DATE_ACTIVE
219 ,mil.ATTRIBUTE_CATEGORY
220 ,mil.ATTRIBUTE1
221 ,mil.ATTRIBUTE2
222 ,mil.ATTRIBUTE3
223 ,mil.ATTRIBUTE4
224 ,mil.ATTRIBUTE5
225 ,mil.ATTRIBUTE6
226 ,mil.ATTRIBUTE7
227 ,mil.ATTRIBUTE8
228 ,mil.ATTRIBUTE9
229 ,mil.ATTRIBUTE10
230 ,mil.ATTRIBUTE11
231 ,mil.ATTRIBUTE12
232 ,mil.ATTRIBUTE13
233 ,mil.ATTRIBUTE14
234 ,mil.ATTRIBUTE15
235 ,mil.REQUEST_ID
236 ,mil.PROGRAM_APPLICATION_ID
237 ,mil.PROGRAM_ID
238 ,mil.PROGRAM_UPDATE_DATE
239 ,mil.PHYSICAL_LOCATION_ID
240 ,mil.PICK_UOM_CODE
241 ,mil.DIMENSION_UOM_CODE
242 ,mil.LENGTH
243 ,mil.WIDTH
244 ,mil.HEIGHT
245 ,mil.LOCATOR_STATUS
246 ,mil.STATUS_ID
247 ,mil.CURRENT_CUBIC_AREA
248 ,mil.AVAILABLE_CUBIC_AREA
249 ,mil.CURRENT_WEIGHT
250 ,mil.AVAILABLE_WEIGHT
251 ,mil.LOCATION_AVAILABLE_UNITS
252 ,mil.SUGGESTED_CUBIC_AREA
253 ,mil.SUGGESTED_WEIGHT
254 ,mil.LOCATION_SUGGESTED_UNITS
255 ,mil.rowid
256 from MTL_ITEM_LOCATIONS mil
257 ,MTL_SECONDARY_INVENTORIES msei
258 ,MTL_ITEM_SUB_INVENTORIES misi
259 where mil.organization_id(+) = msei.organization_id
260 and mil.subinventory_code(+) = msei.secondary_inventory_name
261 and NVL(msei.disable_date, sysdate+1) > sysdate
262 and NVL(mil.disable_date, sysdate+1) > sysdate
263 and mil.organization_id = misi.organization_id
264 and mil.subinventory_code = misi.secondary_inventory
265 and misi.inventory_item_id = g_inventory_item_id
266 ';
267 g_put_base_loc_restrict LONG
268 := '
269 select mil.subinventory_code subinventory_code
270 ,mil.inventory_location_id locator_id
271 ,mil.organization_id organization_id
272 ,mil.project_id project_id
273 ,mil.task_id task_id
274 ,g_inventory_item_id inventory_item_id
275 ,mil.location_current_units location_current_units
276 ,mil.inventory_item_id locator_inventory_item_id
277 ,mil.empty_flag empty_flag
278 ,mil.mixed_items_flag mixed_items_flag
279 ,mil.LAST_UPDATE_DATE
280 ,mil.LAST_UPDATED_BY
281 ,mil.CREATION_DATE
282 ,mil.CREATED_BY
283 ,mil.LAST_UPDATE_LOGIN
284 ,mil.DESCRIPTION
285 ,mil.DESCRIPTIVE_TEXT
286 ,mil.DISABLE_DATE
287 ,mil.INVENTORY_LOCATION_TYPE
288 ,mil.PICKING_ORDER
289 ,mil.PHYSICAL_LOCATION_CODE
290 ,mil.LOCATION_MAXIMUM_UNITS
291 ,mil.LOCATION_WEIGHT_UOM_CODE
292 ,mil.MAX_WEIGHT
293 ,mil.VOLUME_UOM_CODE
294 ,mil.MAX_CUBIC_AREA
295 ,mil.X_COORDINATE
296 ,mil.Y_COORDINATE
297 ,mil.Z_COORDINATE
298 ,mil.INVENTORY_ACCOUNT_ID
299 ,mil.SEGMENT1
300 ,mil.SEGMENT2
301 ,mil.SEGMENT3
302 ,mil.SEGMENT4
303 ,mil.SEGMENT5
304 ,mil.SEGMENT6
305 ,mil.SEGMENT7
306 ,mil.SEGMENT8
307 ,mil.SEGMENT9
308 ,mil.SEGMENT10
309 ,mil.SEGMENT11
310 ,mil.SEGMENT12
311 ,mil.SEGMENT13
312 ,mil.SEGMENT14
313 ,mil.SEGMENT15
314 ,mil.SEGMENT16
315 ,mil.SEGMENT17
316 ,mil.SEGMENT18
317 ,mil.SEGMENT19
318 ,mil.SEGMENT20
319 ,mil.SUMMARY_FLAG
320 ,mil.ENABLED_FLAG
321 ,mil.START_DATE_ACTIVE
322 ,mil.END_DATE_ACTIVE
323 ,mil.ATTRIBUTE_CATEGORY
324 ,mil.ATTRIBUTE1
325 ,mil.ATTRIBUTE2
326 ,mil.ATTRIBUTE3
327 ,mil.ATTRIBUTE4
328 ,mil.ATTRIBUTE5
329 ,mil.ATTRIBUTE6
330 ,mil.ATTRIBUTE7
331 ,mil.ATTRIBUTE8
332 ,mil.ATTRIBUTE9
333 ,mil.ATTRIBUTE10
334 ,mil.ATTRIBUTE11
335 ,mil.ATTRIBUTE12
336 ,mil.ATTRIBUTE13
337 ,mil.ATTRIBUTE14
338 ,mil.ATTRIBUTE15
339 ,mil.REQUEST_ID
340 ,mil.PROGRAM_APPLICATION_ID
341 ,mil.PROGRAM_ID
342 ,mil.PROGRAM_UPDATE_DATE
343 ,mil.PHYSICAL_LOCATION_ID
344 ,mil.PICK_UOM_CODE
345 ,mil.DIMENSION_UOM_CODE
346 ,mil.LENGTH
347 ,mil.WIDTH
348 ,mil.HEIGHT
349 ,mil.LOCATOR_STATUS
350 ,mil.STATUS_ID
351 ,mil.CURRENT_CUBIC_AREA
352 ,mil.AVAILABLE_CUBIC_AREA
353 ,mil.CURRENT_WEIGHT
354 ,mil.AVAILABLE_WEIGHT
355 ,mil.LOCATION_AVAILABLE_UNITS
356 ,mil.SUGGESTED_CUBIC_AREA
357 ,mil.SUGGESTED_WEIGHT
358 ,mil.LOCATION_SUGGESTED_UNITS
359 ,mil.rowid
360 from MTL_ITEM_LOCATIONS mil
361 ,MTL_SECONDARY_INVENTORIES msei
362 ,MTL_ITEM_SUB_INVENTORIES misi
363 ,MTL_SECONDARY_LOCATORS msl
364 where mil.organization_id = msei.organization_id
365 and mil.subinventory_code = msei.secondary_inventory_name
366 and NVL(msei.disable_date, sysdate+1) > sysdate
367 and NVL(mil.disable_date, sysdate+1) > sysdate
368 and mil.organization_id = misi.organization_id
369 and mil.subinventory_code = misi.secondary_inventory
370 and misi.inventory_item_id = g_inventory_item_id
371 and mil.organization_id = msl.organization_id
372 and mil.inventory_location_id = msl.secondary_locator
373 and msl.inventory_item_Id = g_inventory_item_id
374 ';
375 g_put_base CONSTANT LONG
376 := '
377 select x.organization_id
378 ,x.inventory_item_id
379 ,x.subinventory_code
380 ,x.locator_id
381 from (
382 -- subs not restricted and locator controlled
383 select msi.ORGANIZATION_ID ORGANIZATION_ID
384 ,msi.INVENTORY_ITEM_ID INVENTORY_ITEM_ID
385 ,msei.SECONDARY_INVENTORY_NAME SUBINVENTORY_CODE
386 ,mil.INVENTORY_LOCATION_ID LOCATOR_ID
387 ,mil.PROJECT_ID PROJECT_ID
388 ,mil.TASK_ID TASK_ID
389 from MTL_ITEM_LOCATIONS mil
390 ,MTL_SECONDARY_INVENTORIES msei
391 ,MTL_PARAMETERS mp
392 ,MTL_SYSTEM_ITEMS msi
393 where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 2
394 and nvl(msi.RESTRICT_LOCATORS_CODE,2) = 2
395 and mp.ORGANIZATION_ID = msi.ORGANIZATION_ID
396 and msei.ORGANIZATION_ID = msi.ORGANIZATION_ID
397 and nvl(msei.DISABLE_DATE,sysdate+1) > sysdate
398 and decode(mp.STOCK_LOCATOR_CONTROL_CODE,
399 4,decode(msei.LOCATOR_TYPE,
400 5,nvl(msi.LOCATION_CONTROL_CODE,1),
401 nvl(msei.LOCATOR_TYPE,1)),
402 mp.STOCK_LOCATOR_CONTROL_CODE) > 1
403 and mil.INVENTORY_LOCATION_ID > 0 -- force U1 to be used
404 and mil.ORGANIZATION_ID = msei.ORGANIZATION_ID
405 and mil.SUBINVENTORY_CODE = msei.SECONDARY_INVENTORY_NAME
406 and nvl(mil.DISABLE_DATE,sysdate+1) > sysdate
407 union all
408 -- subs restricted and locator controlled
409 select msi.ORGANIZATION_ID
410 ,msi.INVENTORY_ITEM_ID
411 ,misi.SECONDARY_INVENTORY
412 ,mil.INVENTORY_LOCATION_ID
413 ,mil.PROJECT_ID
414 ,mil.TASK_ID
415 from MTL_ITEM_LOCATIONS mil
416 ,MTL_SECONDARY_INVENTORIES msei
417 ,MTL_ITEM_SUB_INVENTORIES misi
418 ,MTL_PARAMETERS mp
419 ,MTL_SYSTEM_ITEMS msi
420 where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 1
421 and nvl(msi.RESTRICT_LOCATORS_CODE,2) = 2
422 and mp.ORGANIZATION_ID = msi.ORGANIZATION_ID
423 and misi.ORGANIZATION_ID = msi.ORGANIZATION_ID
424 and misi.INVENTORY_ITEM_ID = msi.INVENTORY_ITEM_ID
425 and msei.ORGANIZATION_ID = misi.ORGANIZATION_ID
426 and msei.SECONDARY_INVENTORY_NAME = misi.SECONDARY_INVENTORY
427 and nvl(msei.DISABLE_DATE,sysdate+1) > sysdate
428 and decode(mp.STOCK_LOCATOR_CONTROL_CODE,
429 4,decode(msei.LOCATOR_TYPE,
430 5,nvl(msi.LOCATION_CONTROL_CODE,1),
431 nvl(msei.LOCATOR_TYPE,1)),
432 mp.STOCK_LOCATOR_CONTROL_CODE) > 1
433 and mil.INVENTORY_LOCATION_ID > 0 -- force U1 to be used
434 and mil.ORGANIZATION_ID = misi.ORGANIZATION_ID
435 and mil.SUBINVENTORY_CODE = misi.SECONDARY_INVENTORY
436 and nvl(mil.DISABLE_DATE,sysdate+1) > sysdate
437 union all
438 -- locators restricted
439 select msi.ORGANIZATION_ID
440 ,msi.INVENTORY_ITEM_ID
441 ,misi.SECONDARY_INVENTORY
442 ,msl.SECONDARY_LOCATOR
443 ,mil.PROJECT_ID
444 ,mil.TASK_ID
445 from MTL_ITEM_LOCATIONS mil
446 ,MTL_SECONDARY_LOCATORS msl
447 ,MTL_SECONDARY_INVENTORIES msei
448 ,MTL_ITEM_SUB_INVENTORIES misi
449 ,MTL_PARAMETERS mp
450 ,MTL_SYSTEM_ITEMS msi
451 where nvl(msi.RESTRICT_SUBINVENTORIES_CODE,2) = 1
452 and nvl(msi.RESTRICT_LOCATORS_CODE,2) = 1
453 and mp.ORGANIZATION_ID = msi.ORGANIZATION_ID
454 and misi.ORGANIZATION_ID = msi.ORGANIZATION_ID
455 and misi.INVENTORY_ITEM_ID = msi.INVENTORY_ITEM_ID
456 and msei.ORGANIZATION_ID = misi.ORGANIZATION_ID
457 and msei.SECONDARY_INVENTORY_NAME = misi.SECONDARY_INVENTORY
458 and nvl(msei.DISABLE_DATE,sysdate+1) > sysdate
459 and msl.ORGANIZATION_ID = misi.ORGANIZATION_ID
460 and msl.INVENTORY_ITEM_ID = misi.INVENTORY_ITEM_ID
461 and msl.SUBINVENTORY_CODE = misi.SECONDARY_INVENTORY
462 and mil.ORGANIZATION_ID = msl.ORGANIZATION_ID
463 and mil.INVENTORY_LOCATION_ID = msl.SECONDARY_LOCATOR
464 and nvl(mil.DISABLE_DATE,sysdate+1) > sysdate
465 ) x
466 group by x.organization_id
467 , x.inventory_item_id
468 , x.subinventory_code
469 , x.locator_id
470 ';
471 -- /*LPN Status Project*/
472 g_pick_base_serial_detail LONG
473 := '
474 select msn.current_organization_id organization_id
475 ,msn.inventory_item_id
476 ,msn.revision
477 ,msn.lot_number
478 ,lot.expiration_date lot_expiration_date
479 ,msn.current_subinventory_code subinventory_code
480 ,msn.current_locator_id locator_id
481 ,msn.cost_group_id
482 ,msn.status_id --added status_id
483 ,msn.serial_number
484 ,msn.initialization_date date_received
485 ,1 primary_quantity
486 ,null secondary_quantity -- new
487 ,lot.grade_code grade_code -- new
488 ,sub.reservable_type
489 ,nvl(loc.reservable_type,1) locreservable -- Bug 6719290
490 ,nvl(lot.reservable_type,1) lotreservable -- Bug 6719290
491 ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
492 ,WMS_Rule_PVT.GetConversionRate(
493 nvl(loc.pick_uom_code, sub.pick_uom_code)
494 ,msn.current_organization_id
495 ,msn.inventory_item_id) conversion_rate
496 ,msn.lpn_id lpn_id
497 ,loc.project_id project_id
498 ,loc.task_id task_id
499 ,NULL locator_inventory_item_id
500 ,NULL empty_flag
501 ,NULL location_current_units
502 from mtl_serial_numbers msn
503 ,mtl_secondary_inventories sub
504 ,mtl_item_locations loc
505 ,mtl_lot_numbers lot
506 where msn.current_status = 3
507 and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
508 decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
509 and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
510 --and (g_detail_serial IN ( 1,2)
511 and ( g_detail_any_serial = 2 or (g_detail_any_serial = 1
512 and g_from_serial_number <= msn.serial_number
513 and lengthb(g_from_serial_number) = lengthb(msn.serial_number)
514 and g_to_serial_number >= msn.serial_number
515 and lengthb(g_to_serial_number) = lengthb(msn.serial_number))
516 or ( g_from_serial_number is null or g_to_serial_number is null)
517 )
518 and sub.organization_id = msn.current_organization_id
519 and sub.secondary_inventory_name = msn.current_subinventory_code
520 and loc.organization_id (+)= msn.current_organization_id
521 and loc.inventory_location_id (+)= msn.current_locator_id
522 and lot.organization_id (+)= msn.current_organization_id
523 and lot.inventory_Item_id (+)= msn.inventory_item_id
524 and lot.lot_number (+)= msn.lot_number
525 ';
526
527 /*LPN Status Project*/
528 g_pick_base_serial LONG
529 := '
530 select msn.current_organization_id organization_id
531 ,msn.inventory_item_id
532 ,msn.revision
533 ,msn.lot_number
534 ,lot.expiration_date lot_expiration_date
535 ,msn.current_subinventory_code subinventory_code
536 ,msn.current_locator_id locator_id
537 ,msn.cost_group_id
538 ,msn.status_id --added status_id
539 ,msn.serial_number
540 ,msn.initialization_date date_received
541 ,1 primary_quantity
542 ,null secondary_quantity -- new
543 ,lot.grade_code grade_code -- new
544 ,sub.reservable_type
545 ,nvl(loc.reservable_type,1) locreservable -- Bug 6719290
546 ,nvl(lot.reservable_type,1) lotreservable -- Bug 6719290
547 ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
548 ,WMS_Rule_PVT.GetConversionRate(
549 nvl(loc.pick_uom_code, sub.pick_uom_code)
550 ,msn.current_organization_id
551 ,msn.inventory_item_id) conversion_rate
552 ,msn.lpn_id lpn_id
553 ,loc.project_id project_id
554 ,loc.task_id task_id
555 ,NULL locator_inventory_item_id
556 ,NULL empty_flag
557 ,NULL location_current_units
558 from mtl_serial_numbers msn
559 ,mtl_secondary_inventories sub
560 ,mtl_item_locations loc
561 ,mtl_lot_numbers lot
562 where msn.current_status = 3
563 and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
564 decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
565 and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
566 and (g_detail_serial = 4
567 OR(g_detail_any_serial = 1
568 OR (g_from_serial_number <= msn.serial_number
569 AND lengthb(g_from_serial_number) = lengthb(msn.serial_number)
570 AND g_to_serial_number >= msn.serial_number
571 AND lengthb(g_to_serial_number) = lengthb(msn.serial_number)
572 )))
573 and sub.organization_id = msn.current_organization_id
574 and sub.secondary_inventory_name = msn.current_subinventory_code
575 and loc.organization_id (+)= msn.current_organization_id
576 and loc.inventory_location_id (+)= msn.current_locator_id
577 and lot.organization_id (+)= msn.current_organization_id
578 and lot.inventory_Item_id (+)= msn.inventory_item_id
579 and lot.lot_number (+)= msn.lot_number
580 ';
581 -------------------------------------------------
582 /*LPN Status Project*/
583 --- Added the following query to validate the serial status inside the rules package
584 g_pick_base_serial_v LONG
585 := '
586 select msn.current_organization_id organization_id
587 ,msn.inventory_item_id
588 ,msn.revision
589 ,msn.lot_number
590 ,lot.expiration_date lot_expiration_date
591 ,msn.current_subinventory_code subinventory_code
592 ,msn.current_locator_id locator_id
593 ,msn.cost_group_id
594 ,msn.status_id --added status_id
595 ,msn.serial_number
596 ,msn.initialization_date date_received
597 ,1 primary_quantity
598 ,null secondary_quantity -- new
599 ,lot.grade_code grade_code -- new
600 ,sub.reservable_type
601 ,nvl(loc.reservable_type,1) locreservable -- Bug 6719290
602 ,nvl(lot.reservable_type,1) lotreservable -- Bug 6719290
603 ,nvl(loc.pick_uom_code, sub.pick_uom_code) uom_code
604 ,WMS_Rule_PVT.GetConversionRate(
605 nvl(loc.pick_uom_code, sub.pick_uom_code)
606 ,msn.current_organization_id
607 ,msn.inventory_item_id) conversion_rate
608 ,msn.lpn_id lpn_id
609 ,loc.project_id project_id
610 ,loc.task_id task_id
611 ,NULL locator_inventory_item_id
612 ,NULL empty_flag
613 ,NULL location_current_units
614 from mtl_serial_numbers msn
615 ,mtl_secondary_inventories sub
616 ,mtl_item_locations loc
617 ,mtl_lot_numbers lot
618 where msn.current_status = 3
619 and decode(g_unit_number, ''-9999'', ''a'', ''-7777'', nvl(msn.end_item_unit_number, ''-7777''), msn.end_item_unit_number) =
620 decode(g_unit_number, ''-9999'', ''a'', g_unit_number)
621 and (msn.group_mark_id IS NULL or msn.group_mark_id = -1)
622 and (g_detail_serial = 3
623 OR(g_detail_any_serial = 1
624 OR (g_from_serial_number <= msn.serial_number
625 AND lengthb(g_from_serial_number) = lengthb(msn.serial_number)
626 AND g_to_serial_number >= msn.serial_number
627 AND lengthb(g_to_serial_number) = lengthb(msn.serial_number)
628 )))
629 and sub.organization_id = msn.current_organization_id
630 and sub.secondary_inventory_name = msn.current_subinventory_code
631 and loc.organization_id (+)= msn.current_organization_id
632 and loc.inventory_location_id (+)= msn.current_locator_id
633 and lot.organization_id (+)= msn.current_organization_id
634 and lot.inventory_Item_id (+)= msn.inventory_item_id
635 and lot.lot_number (+)= msn.lot_number
636 and inv_detail_util_pvt.is_serial_trx_allowed(
637 g_transaction_type_id
638 ,msn.current_organization_id
639 ,msn.inventory_item_id
640 ,msn.status_id) = ''Y'' ';
641 /*LPN Status Project*/
642 -- Bug #3697741 modified the base query to get the project_id and task_id from mtl_inventory_locations
643 g_pick_base_lpn_only CONSTANT LONG
644 := '
645 select x.organization_id
646 ,x.inventory_item_id
647 ,x.revision
648 ,x.lot_number
649 ,lot.expiration_date lot_expiration_date
650 ,x.subinventory_code
651 ,sub.reservable_type
652 ,nvl(x.reservable_type,1) locreservable -- Bug 6719290
653 ,nvl(lot.reservable_type,1) lotreservable -- Bug 6719290
654 ,x.locator_id
655 ,x.cost_group_id
656 ,x.status_id --added status_id
657 ,x.date_received date_received
658 ,x.primary_quantity primary_quantity
659 ,x.secondary_quantity secondary_quantity -- new
660 ,lot.grade_code grade_code -- new
661 ,x.lpn_id lpn_id
662 ,x.project_id project_id
663 ,x.task_id task_id
664 from
665 (SELECT
666 moq.organization_id
667 ,moq.inventory_item_id
668 ,moq.revision
669 ,moq.lot_number
670 ,moq.subinventory_code
671 ,moq.locator_id
672 ,moq.cost_group_id
673 ,moq.status_id --added status_id
674 ,mils.reservable_type -- Bug 6719290
675 ,min(NVL(moq.orig_date_received,
676 moq.date_received)) date_received
677 ,sum(moq.primary_transaction_quantity) primary_quantity
678 ,sum(moq.secondary_transaction_quantity) secondary_quantity -- new
679 ,moq.lpn_id lpn_id
680 ,mils.project_id project_id
681 ,mils.task_id task_id
682 FROM
683 mtl_onhand_quantities_detail moq
684 , mtl_item_locations mils
685 WHERE
686 moq.organization_id = g_organization_id
687 AND moq.inventory_item_id = g_inventory_item_id
688 AND moq.organization_id = mils.organization_id
689 AND moq.subinventory_code = mils.subinventory_code
690 AND moq.locator_id = mils.inventory_location_id
691 AND moq.lpn_id IS NOT NULL
692 AND NOT EXISTS(
693 select lpn_id
694 from wms_license_plate_numbers wlpn1
695 where wlpn1.parent_lpn_id = moq.lpn_id)
696 AND
697 1 = (select count(distinct(moq1.inventory_item_id))
698 from mtl_onhand_quantities_detail moq1
699 where moq1.organization_id = moq.organization_id
700 and moq1.subinventory_code = moq.subinventory_code
701 and moq1.locator_id = moq.locator_id
702 and moq1.lpn_id = moq.lpn_id)
703 GROUP BY
704 moq.organization_id, moq.inventory_item_id
705 ,moq.revision, moq.lot_number
706 ,moq.subinventory_code, moq.locator_id --added status_id
707 ,moq.cost_group_id,moq.status_id,mils.reservable_type,moq.lpn_id -- Bug 6719290
708 ,mils.project_id, mils.task_id
709 ) x
710 ,mtl_secondary_inventories sub
711 ,mtl_lot_numbers lot
712 where x.primary_quantity > 0
713 and x.organization_id = sub.organization_id
714 and x.subinventory_code = sub.secondary_inventory_name
715 and x.organization_id = lot.organization_id (+)
716 and x.inventory_item_id = lot.inventory_item_id (+)
717 and x.lot_number = lot.lot_number (+)
718 ';
719 /*LPN Status Project*/
720 -- Bug #3697741 modified the base query to get the project_id and task_id from mtl_inventory_locations
721 -- LG convergence, for this bug, an item is not locator controlled may not have
722 -- any records in mils. so the join will fail. put decode and outter join
723 -- need to talk to grao about this.
724 g_pick_base_lpn_loose CONSTANT LONG
725 := '
726 select x.organization_id
727 ,x.inventory_item_id
728 ,x.revision
729 ,x.lot_number
730 ,lot.expiration_date lot_expiration_date
731 ,x.subinventory_code
732 ,sub.reservable_type
733 ,nvl(x.reservable_type,1) locreservable -- Bug 6719290
734 ,nvl(lot.reservable_type,1) lotreservable -- Bug 6719290
735 ,x.locator_id
736 ,x.cost_group_id
737 ,x.status_id --added status_id
738 ,x.date_received date_received
739 ,x.primary_quantity primary_quantity
740 ,x.secondary_quantity secondary_quantity -- new
741 ,lot.grade_code grade_code -- new
742 ,x.lpn_id lpn_id
743 ,x.project_id project_id
744 ,x.task_id task_id
745 from
746 (SELECT
747 moq.organization_id
748 ,moq.inventory_item_id
749 ,moq.revision
750 ,moq.lot_number
751 ,moq.subinventory_code
752 ,moq.locator_id
753 ,moq.cost_group_id
754 ,moq.status_id --added status_id
755 ,mils.reservable_type -- Bug 6719290
756 ,min(NVL(moq.orig_date_received,
757 moq.date_received)) date_received
758 ,sum(moq.primary_transaction_quantity) primary_quantity
759 ,sum(moq.secondary_transaction_quantity) secondary_quantity -- new
760 ,moq.lpn_id lpn_id
761 ,decode(mils.project_id, mils.project_id, moq.project_id) project_id
762 ,decode(mils.task_id, mils.task_id, moq.task_id) task_id
763 FROM
764 mtl_onhand_quantities_detail moq,mtl_item_locations mils
765 WHERE
766 moq.organization_id = g_organization_id
767 AND moq.inventory_item_id = g_inventory_item_id
768 AND moq.organization_id = mils.organization_id (+)
769 AND moq.subinventory_code = mils.subinventory_code (+)
770 AND moq.locator_id = mils.inventory_location_id (+)
771 GROUP BY
772 moq.organization_id, moq.inventory_item_id
773 ,moq.revision, moq.lot_number
774 ,moq.subinventory_code, moq.locator_id --added status_id
775 ,moq.cost_group_id,moq.status_id, mils.reservable_type, moq.lpn_id -- Bug 6719290
776 ,decode(mils.project_id, mils.project_id, moq.project_id)
777 ,decode(mils.task_id, mils.task_id, moq.task_id)
778 ) x
779 ,mtl_secondary_inventories sub
780 ,mtl_lot_numbers lot
781 where x.primary_quantity > 0
782 and x.organization_id = sub.organization_id
783 and x.subinventory_code = sub.secondary_inventory_name
784 and x.organization_id = lot.organization_id (+)
785 and x.inventory_item_id = lot.inventory_item_id (+)
786 and x.lot_number = lot.lot_number (+)
787 ';
788 g_pick_base LONG;
789 --
790 g_base_table_alias wms_db_objects.table_alias%TYPE;
791 g_input_table_alias wms_db_objects.table_alias%TYPE;
792 g_base_select LONG;
793 g_base_group_by LONG;
794 g_rule_select LONG;
795 g_rule_select_serial LONG;
796 g_rule_group_by LONG;
797 g_base_from LONG;
798 g_base_from_serial LONG; --used if item is lot controlled
799 g_base_from_serial_v LONG; --used for serial controlled item / Validation required
800 g_base_from_serial_detail LONG; -- New
801 g_rule_from LONG;
802 g_input_where LONG;
803 g_rule_where LONG;
804 g_rule_order LONG;
805 g_stmt LONG;
806 g_stmt_task_type LONG; --used for task type assignment TTA
807 g_stmt_serial LONG;
808 g_stmt_serial_validate LONG;
809 g_stmt_serial_detail LONG;
810 g_stmt_serial_detail_new LONG;
811 g_build_package_row NUMBER;
812 g_build_package_tbl DBMS_SQL.varchar2s;
813 g_default_pick_task_type_id NUMBER;
814 g_default_putaway_task_type_id NUMBER;
815 g_default_cc_task_type_id NUMBER;
816 g_default_repl_task_type_id NUMBER;
817 g_default_moxfer_task_type_id NUMBER;
818 g_default_moissue_task_type_id NUMBER;
819 g_default_operation_plan_id NUMBER;
820 g_current_organization_id NUMBER;
821 --
822 g_line_feed CONSTANT VARCHAR2(1) := '
823 ';
824 --global values for allocation mode
825 g_alloc_lpn_only NUMBER := 1;
826 g_alloc_lpn_loose NUMBER := 2;
827 g_alloc_no_lpn NUMBER := 3;
828 g_alloc_pick_uom NUMBER := 4;
829
830 -- Added for R12.1 Replenishment Project - 6681109
831 g_alloc_strict_pick_uom NUMBER := 5;
832
833 --Used for storing both the current record being dealt with and a
834 -- a variety of stored records. This represents a single row returned
835 -- by the FetchCursor function, which gets the row from the Rule.
836 -- This records are stored in an array, but are accessed like linked
837 -- lists. Each record contains the index of the next record
838 -- that should be looked at (next_rec).
839 TYPE t_location_rec IS RECORD(
840 revision wms_transactions_temp.revision%TYPE
841 , lot_number wms_transactions_temp.lot_number%TYPE
842 , lot_expiration_date wms_transactions_temp.lot_expiration_date%TYPE
843 , subinventory_code wms_transactions_temp.from_subinventory_code%TYPE
844 , locator_id wms_transactions_temp.from_locator_id%TYPE
845 , cost_group_id wms_transactions_temp.from_cost_group_id%TYPE
846 , uom_code VARCHAR2(3)
847 , lpn_id NUMBER
848 , serial_number VARCHAR2(30)
849 , quantity wms_transactions_temp.primary_quantity%TYPE
850 , secondary_quantity wms_transactions_temp.secondary_quantity%TYPE
851 , grade_code wms_transactions_temp.grade_code%TYPE
852 , secondary_uom_code VARCHAR2(3)
853 , consist_string VARCHAR2(1000)
854 , order_by_string VARCHAR2(1000)
855 , next_rec NUMBER);
856
857 TYPE t_location_table IS TABLE OF t_location_rec
858 INDEX BY BINARY_INTEGER;
859
860 --these arrays store location recs in sequential order. However, when
861 -- the records are read from the array, they are read in the order
862 -- dictated by the pointer in the location_rec (next_rec)
863 g_locs t_location_table; -- array of all locators read from cursor
864 g_locs_index NUMBER := 0;
865
866 -- This record is used to store information about a consistency group.
867 -- A consistency group consists of all records which share the same
868 -- consist_string. The consist_string is the concatenation of each
869 -- record's values for the columns which are defined as a rule's
870 -- consistencies. For example, if a rule's consistency restrictions
871 -- are lot number and locator_id, then the consist string would
872 -- lot_number||locator_id. Each record could have different
873 -- values for the consist string, like LOTA123, or LOTB1000.
874 -- For creating pick suggestions for rules that have consistency
875 -- restrictions, we need to keep track of the quantity available
876 -- for each consistency group.
877 -- 2/26/02
878 -- Group record altered to support LPNs
879 TYPE t_group_rec IS RECORD(
880 consist_string VARCHAR2(1000)
881 , lpn_id NUMBER
882 , quantity NUMBER
883 , total_quantity NUMBER
884 , secondary_quantity NUMBER -- new
885 , secondary_total_quantity NUMBER -- new
886 , grade_code VARCHAR2(150) -- new
887 , order_by_rank NUMBER
888 , first_rec NUMBER
889 , last_rec NUMBER
890 , prev_group NUMBER
891 , next_group NUMBER
892 , prev_consist_lpn_id NUMBER
893 , next_consist_lpn_id NUMBER
894 , parent_consist_group NUMBER);
895
896 TYPE t_group_table IS TABLE OF t_group_rec
897 INDEX BY BINARY_INTEGER;
898
899 g_consists t_group_table;
900 g_lpns t_group_table;
901 g_first_order_by_rank NUMBER := NULL;
902 g_first_consist_group NUMBER := 0;
903 g_last_consist_group NUMBER;
904 g_first_lpn_group NUMBER;
905 g_last_lpn_group NUMBER;
906 g_trace_recs wms_search_order_globals_pvt.pre_suggestions_record_tbl;
907
908 PROCEDURE FetchCursorRows(
909 x_return_status OUT NOCOPY VARCHAR2
910 , x_msg_count OUT NOCOPY NUMBER
911 , x_msg_data OUT NOCOPY VARCHAR2
912 , p_cursor IN wms_rule_pvt.cv_pick_type
913 , p_rule_id IN NUMBER
914 );
915
916 -- =============================================
917 -- Procedure to log message for Label Printing
918 -- =============================================
919 PROCEDURE TRACE(p_message IN VARCHAR2) IS
920 BEGIN
921 inv_log_util.TRACE(p_message, 'RULE_ENGINE', 4);
922 END TRACE;
923
924 --Procedures for logging messages
925 PROCEDURE log_event(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
926 l_module VARCHAR2(255);
927 BEGIN
928 l_module := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
929 inv_log_util.trace(p_message, l_module, 9);
930 /* fnd_log.STRING(log_level => fnd_log.level_event, module => l_module, message => p_message);
931 inv_log_util.trace(p_message, l_module, 9);
932 gmi_reservation_util.println(p_message); */
933 END log_event;
934
935 PROCEDURE log_error(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
936 l_module VARCHAR2(255);
937 BEGIN
938 l_module := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
939 inv_log_util.trace(p_message, l_module, 9); /*
940 fnd_log.STRING(log_level => fnd_log.level_error, module => l_module, message => p_message);
941 inv_log_util.trace(p_message, l_module, 9);
942 gmi_reservation_util.println(p_message); */
943 END log_error;
944
945 PROCEDURE log_error_msg(p_api_name VARCHAR2, p_label VARCHAR2) IS
946 l_module VARCHAR2(255);
947 BEGIN
948 l_module := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
949 inv_log_util.trace('err:', l_module, 9); /*
950 fnd_log.message(log_level => fnd_log.level_error, module => l_module, pop_message => FALSE);
951 inv_log_util.trace('err:', l_module, 9);
952 gmi_reservation_util.println(p_label); */
953 END log_error_msg;
954
955 PROCEDURE log_procedure(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
956 l_module VARCHAR2(255);
957 BEGIN
958 l_module := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
959 inv_log_util.trace(p_message, l_module, 9);/*
960 fnd_log.STRING(log_level => fnd_log.level_procedure, module => l_module, message => p_message);
961 inv_log_util.trace(p_message, l_module, 9);
962 gmi_reservation_util.println(p_message); */
963 END log_procedure;
964
965 PROCEDURE log_statement(p_api_name VARCHAR2, p_label VARCHAR2, p_message VARCHAR2) IS
966 l_module VARCHAR2(255);
967 BEGIN
968 l_module := 'wms.plsql.' || g_pkg_name || '.' || p_api_name || '.' || p_label;
969 inv_log_util.trace(p_message, l_module, 9);/*
970 fnd_log.STRING(log_level => fnd_log.level_statement, module => l_module, message => p_message);
971 inv_log_util.trace(p_message, l_module, 9);
972 gmi_reservation_util.println(p_label||' '||p_message);*/
973 END log_statement;
974 ----
975 ---- Function to check if Restriction , Sort-criteria and Consistency was defined for a given picking rule
976 ---- using serial object
977
978 FUNCTION IsSerialObjectUsed( p_organization_id NUMBER )
979 RETURN BOOLEAN IS
980 l_serial_object_used NUMBER ;
981 BEGIN
982 /* Trace( ' Start IsSerialObjectUsed');
983 Trace( ' Start IsSerialObjectUsed p_organization_id '|| to_char(p_organization_id));
984 Trace( ' Start IsSerialObjectUsed g_serial_objects_used ' || to_char( g_serial_objects_used));
985 */
986
987 l_serial_object_used := 0 ;
988 IF ( wms_rule_pvt.g_serial_objects_used IS NULL ) THEN
989 --Trace( ' IsSerialObjectUsed -- If condition is true ');
990 SELECT count( DISTINCT p.object_id)
991 INTO l_serial_object_used
992 FROM wms_selection_criteria_txn wsc,
993 wms_strategies_b wsb,
994 wms_strategy_members wsm,
995 wms_rules_b wrb,
996 wms_restrictions r,
997 wms_sort_criteria s,
998 wms_rule_consistencies c,
999 wms_parameters_b p
1000 WHERE wsc.rule_type_code = 2
1001 AND wsc.enabled_flag = 1
1002 AND wsc.return_type_code = 'S'
1003 AND wsc.from_organization_id = p_organization_id
1004 AND wsc.return_type_id = wsb.strategy_id
1005 AND wsb.strategy_id = wsm.strategy_id
1006 AND wsm.rule_id = wrb.rule_id
1007 AND (
1008 ( wrb.rule_id = r.rule_id AND ((r.parameter_id = p.parameter_id ) OR (r.operand_parameter_id = p.parameter_id)))
1009 OR (wrb.rule_id = s.rule_id AND s.parameter_id = p.parameter_id) OR (wrb.rule_id = c.rule_id AND c.parameter_id = p.parameter_id) )
1010 AND wrb.organization_id IN (p_organization_id, -1)
1011 AND p.object_id = 26; --- 26 is Serial object
1012
1013 wms_rule_pvt.g_serial_objects_used := l_serial_object_used;
1014
1015 --Trace( ' IsSerialObjectUsed -- l_serial_object_used ' || wms_rule_pvt.g_serial_object_used);
1016 ELSE
1017 l_serial_object_used := wms_rule_pvt.g_serial_objects_used;
1018 END IF;
1019
1020 If l_serial_object_used >= 1 THEN
1021 RETURN TRUE;
1022 ELSE
1023 RETURN FALSE;
1024 END IF;
1025
1026 EXCEPTION WHEN OTHERS THEN
1027 RETURN FALSE;
1028 END IsSerialObjectUsed;
1029
1030 --
1031 -- Name : FreeGlobals
1032 -- Function : Initializes global variables.
1033 -- Notes : privat procedure for internal use only
1034 --
1035 PROCEDURE freeglobals IS
1036 BEGIN
1037 g_base_select := NULL;
1038 g_rule_select := NULL;
1039 g_rule_select_serial := NULL;
1040 g_base_from := NULL;
1041 g_base_from_serial := NULL;
1042 g_base_from_serial_v := NULL;
1043 g_base_from_serial_detail := NULL;
1044 g_rule_from := NULL;
1045 g_input_where := NULL;
1046 g_rule_where := NULL;
1047 g_rule_order := NULL;
1048 g_base_group_by := NULL;
1049 g_rule_group_by := NULL;
1050 g_stmt := NULL;
1051 g_stmt_serial := NULL;
1052 g_stmt_serial_detail := NULL;
1053 g_stmt_serial_detail_new := NULL;
1054 g_pick_base := NULL;
1055 -- clean up the serial number detailing table
1056 -- Commenting out for Bug 5251221
1057 --inv_detail_util_pvt.init_output_serial_rows;
1058 -- clean up the bind variables table
1059 inv_sql_binding_pvt.initbindtables;
1060 END freeglobals;
1061
1062 ----
1063 ----
1064
1065 --------------
1066 --- Build Rules List
1067 --- Generate all static rule list package for diffrent rule types.
1068 ---- Total of 15 packages will be generated
1069 ---- WMS_RULE_PICK_PKG, WMS_RULE_PICK_PKG1, WMS_RULE_PICK_PKG2
1070 PROCEDURE buildrulespkg(errbuf OUT NOCOPY VARCHAR2, retcode OUT NOCOPY NUMBER, x_return_status OUT NOCOPY VARCHAR2) IS
1071 l_return_status VARCHAR2(1);
1072 l_msg_count NUMBER;
1073 l_msg_data VARCHAR2(240);
1074 l_rule_id NUMBER;
1075 l_error_string VARCHAR2(240);
1076 BEGIN
1077
1078 --
1079 -- kkoothan Bug Fix:2561401
1080 -- Initialized the value of X_RETURN_STATUS to Success
1081 -- at the start of the procedure and set its value accordingly
1082 -- when the procedure returns Failure/Error.
1083 --
1084 X_RETURN_STATUS := fnd_api.g_ret_sts_success;
1085
1086 --- Updates the table wms_rule_list_package ,
1087 --- for all rule type package counter with value 3
1088 --- so that all three "rules list packages" for all type of
1089 ----Rules will be generated.
1090
1091 UPDATE wms_rule_list_package
1092 SET package_name_count = 3;
1093
1094 wms_rule_gen_pkgs.generateruleexecpkgs(
1095 p_api_version => 1.0
1096 , p_init_msg_list => fnd_api.g_true
1097 , p_validation_level => fnd_api.g_valid_level_full
1098 , x_return_status => l_return_status
1099 , x_msg_count => l_msg_count
1100 , x_msg_data => l_msg_data
1101 , p_pick_code => 2
1102 , p_put_code => 1
1103 , p_task_code => 3
1104 , p_label_code => 4
1105 , p_cg_code => 5
1106 , p_op_code => 7
1107 , p_pkg_type => 'B'
1108 );
1109
1110 IF (l_return_status = fnd_api.g_ret_sts_success) THEN
1111 FND_FILE.put_line(FND_FILE.LOG, 'Success from GenerateRuleExecPkgs');
1112 ELSE
1113 FND_FILE.put_line(FND_FILE.LOG, 'Error from GenerateRuleExecPkgs:');
1114 X_RETURN_STATUS := fnd_api.g_ret_sts_error; -- Expected Error
1115 retcode := 1;
1116
1117 FOR i IN 1 .. l_msg_count LOOP
1118 --fnd_file.put_line(fnd_file.LOG, 'Error:');
1119 l_error_string := fnd_message.get;
1120 --fnd_file.put_line(fnd_file.LOG, l_error_string);
1121 errbuf := errbuf || ' Error: GenerateRuleExecPkgs ' || l_error_string;
1122 END LOOP;
1123 END IF;
1124 EXCEPTION
1125 WHEN OTHERS THEN
1126 X_RETURN_STATUS := fnd_api.g_ret_sts_unexp_error; -- Unexpecetd Error
1127 retcode := 2;
1128 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1129 fnd_msg_pub.add_exc_msg(g_pkg_name, 'BuildRulePkg');
1130 END IF;
1131
1132 fnd_msg_pub.count_and_get(p_count => l_msg_count, p_data => l_msg_data);
1133 --fnd_file.put_line(fnd_file.LOG, 'Exception');
1134 --fnd_file.put_line(fnd_file.LOG, l_msg_data);
1135 errbuf := errbuf || 'Error in BuildRulesPkg:' || l_msg_data;
1136 END buildrulespkg;
1137
1138 --
1139 -- Name : GetConversionRate
1140 -- Function : Finds the conversion rate between the given UOM and
1141 -- the base UOM of the class which contains the
1142 -- item's primary UOM. Support interclass and intraclass
1143 -- conversions.
1144 -- Notes : private procedure for internal use only;
1145 -- Similar to inv_convert.inv_um_converstion, but no
1146 -- Used to order locations returned from rule package
1147 FUNCTION getconversionrate(p_uom_code VARCHAR2, p_organization_id NUMBER, p_inventory_item_id NUMBER)
1148 RETURN NUMBER IS
1149 l_conversion_rate NUMBER;
1150 l_from_class VARCHAR2(10);
1151 l_to_class VARCHAR2(10);
1152 l_class_rate NUMBER;
1153
1154 --get conversion rate between given uom and that uom class's
1155 -- base uom
1156 CURSOR c_conversion_rate IS
1157 SELECT conversion_rate
1158 , uom_class
1159 FROM mtl_uom_conversions
1160 WHERE uom_code = p_uom_code
1161 AND inventory_item_id IN (p_inventory_item_id, 0)
1162 AND NVL(disable_date, TRUNC(SYSDATE) + 1) > TRUNC(SYSDATE)
1163 ORDER BY inventory_item_id DESC;
1164
1165 -- find the uom class for the item's primary uom
1166 CURSOR c_primary_uom_class IS
1167 SELECT uom_class
1168 FROM mtl_units_of_measure muom, mtl_system_items msi
1169 WHERE msi.organization_id = p_organization_id
1170 AND msi.inventory_item_id = p_inventory_item_id
1171 AND muom.uom_code = msi.primary_uom_code;
1172
1173 -- find the conversion rate between the base uoms of two classes
1174 CURSOR c_class_conversion_rate IS
1175 SELECT conversion_rate
1176 FROM mtl_uom_class_conversions
1177 WHERE from_uom_class = l_from_class
1178 AND to_uom_class = l_to_class
1179 AND inventory_item_id IN (p_inventory_item_id, 0)
1180 AND NVL(disable_date, TRUNC(SYSDATE) + 1) > TRUNC(SYSDATE)
1181 ORDER BY inventory_item_id DESC;
1182 BEGIN
1183 IF (p_uom_code IS NULL) THEN
1184 RETURN 0;
1185 END IF;
1186
1187 IF (nvl(g_gcr_organization_id,-1) = p_organization_id
1188 AND nvl(g_gcr_inventory_item_id,-1) = p_inventory_item_id
1189 AND nvl(g_gcr_uom_code,'-1') = p_uom_code) THEN
1190 l_conversion_rate := g_gcr_conversion_rate;
1191 ELSE
1192 OPEN c_conversion_rate;
1193 --Cursor returns 0, 1, or 2 records
1194 -- Because the results are ordered by item_id desc, the results
1195 -- are also ordered from specific (item_Id > 0) to default (item_id = 0);
1196 --So, we only have to fetch one record
1197 FETCH c_conversion_rate INTO l_conversion_rate, l_to_class;
1198
1199 IF (c_conversion_rate%NOTFOUND) THEN
1200 --don't raise error. Instead, just return 1
1201 l_conversion_rate := 0;
1202 END IF;
1203
1204 CLOSE c_conversion_rate;
1205
1206 IF l_conversion_rate <> 0 THEN
1207 OPEN c_primary_uom_class;
1208 FETCH c_primary_uom_class INTO l_from_class;
1209
1210 IF (c_primary_uom_class%NOTFOUND) THEN
1211 l_from_class := NULL;
1212 l_conversion_rate := 0;
1213 END IF;
1214
1215 CLOSE c_primary_uom_class;
1216
1217 -- check to see if interclass conversion - if so, get conversion
1218 -- between 2 classes
1219 IF l_from_class IS NOT NULL
1220 AND l_to_class IS NOT NULL
1221 AND l_from_class <> l_to_class THEN
1222 OPEN c_class_conversion_rate;
1223 FETCH c_class_conversion_rate INTO l_class_rate;
1224
1225 IF c_class_conversion_rate%NOTFOUND THEN
1226 l_class_rate := 0;
1227 END IF;
1228
1229 l_conversion_rate := l_conversion_rate * l_class_rate;
1230 END IF;
1231 END IF;
1232 g_gcr_organization_id := p_organization_id;
1233 g_gcr_inventory_item_id := p_inventory_item_id;
1234 g_gcr_uom_code := p_uom_code;
1235 g_gcr_conversion_rate := l_conversion_rate;
1236 END IF;
1237
1238 RETURN l_conversion_rate;
1239 END getconversionrate;
1240
1241 --
1242 -- Name : BuildBaseSQL
1243 -- Function : Builds the base part of a pick or put away rule representing
1244 -- dynamic SQL cursor text.
1245 -- Notes : privat procedure for internal use only
1246 --
1247 PROCEDURE buildbasesql(
1248 x_return_status OUT NOCOPY VARCHAR2
1249 , x_msg_count OUT NOCOPY NUMBER
1250 , x_msg_data OUT NOCOPY VARCHAR2
1251 , p_type_code IN NUMBER
1252 , p_allocation_mode_id IN NUMBER
1253 ) IS
1254 l_api_name VARCHAR2(30) := 'BuildBaseSQL';
1255 l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
1256 --
1257 -- variables needed for dynamic SQL
1258 l_identifier VARCHAR2(10);
1259 -- variables for the base and input representing DB objects
1260 l_input_table_name wms_db_objects.table_name%TYPE;
1261 l_type_dependent_alias wms_db_objects.table_alias%TYPE;
1262
1263 --
1264 -- cursor for the base and input representing DB objects
1265 CURSOR baseinp IS
1266 SELECT wdo1.table_alias
1267 , wdo2.table_name
1268 , wdo2.table_alias
1269 FROM wms_db_objects wdo1, wms_db_objects wdo2
1270 WHERE wdo1.db_object_id = 1
1271 AND wdo2.db_object_id = 2;
1272 --
1273 BEGIN
1274 --
1275 -- Initialize API return status to success
1276 x_return_status := fnd_api.g_ret_sts_success;
1277
1278 --
1279 -- debugging portion
1280 -- can be commented ut for final code
1281 log_procedure(l_api_name, 'start', 'Start BuildBaseSql');
1282 log_statement(l_api_name, 'type_code', 'type_code: ' || p_type_code);
1283 -- end of debugging section
1284 --
1285
1286
1287 -- get names and aliases of the base and input representing DB objects
1288 OPEN baseinp;
1289 FETCH baseinp INTO g_base_table_alias, l_input_table_name, g_input_table_alias;
1290
1291 IF baseinp%NOTFOUND THEN
1292 CLOSE baseinp;
1293 log_statement(l_api_name, 'no_base_input', 'No base input found');
1294 RAISE NO_DATA_FOUND;
1295 END IF;
1296
1297 CLOSE baseinp;
1298
1299 --
1300 -- Build 'select' skeleton
1301 IF p_type_code = 1 THEN -- put away:
1302 l_type_dependent_alias := g_input_table_alias; -- rev and lot from input
1303 ELSIF p_type_code = 2 THEN -- pick:
1304 l_type_dependent_alias := g_base_table_alias; -- rev and lot from basis
1305 END IF;
1306
1307 --
1308 --2/21/02 - remove all columns but sub and loc from picking query
1309 IF p_type_code = 2 THEN
1310 g_base_select := l_type_dependent_alias
1311 || '.REVISION'
1312 || g_line_feed
1313 || ','
1314 || l_type_dependent_alias
1315 || '.LOT_NUMBER'
1316 || g_line_feed
1317 || ','
1318 || l_type_dependent_alias
1319 || '.LOT_EXPIRATION_DATE'
1320 || g_line_feed
1321 || ','
1322 || g_base_table_alias
1323 || '.SUBINVENTORY_CODE'
1324 || g_line_feed
1325 || ','
1326 || g_base_table_alias
1327 || '.LOCATOR_ID'
1328 || g_line_feed;
1329 ELSE
1330 g_base_select := g_base_table_alias
1331 || '.SUBINVENTORY_CODE'
1332 || g_line_feed || ','
1333 || g_base_table_alias
1334 || '.LOCATOR_ID'
1335 || g_line_feed;
1336 END IF;
1337
1338 -- added to suport PJM
1339 IF p_type_code = 1 THEN
1340 g_base_select := g_base_select
1341 || ','
1342 || g_base_table_alias
1343 || '.PROJECT_ID'
1344 || g_line_feed;
1345 g_base_select := g_base_select
1346 || ','
1347 || g_base_table_alias
1348 || '.TASK_ID'
1349 || g_line_feed;
1350 END IF;
1351
1352 --added to support Picking by UOM.
1353 --UOM only matters in picking
1354 IF p_type_code = 2 THEN --pick
1355 g_base_select := g_base_select
1356 || ','
1357 || g_base_table_alias
1358 || '.COST_GROUP_ID'
1359 || g_line_feed;
1360 g_base_select := g_base_select
1361 || ','
1362 || g_base_table_alias
1363 || '.UOM_CODE'
1364 || g_line_feed;
1365
1366 IF p_allocation_mode_id IN (g_alloc_lpn_only, g_alloc_lpn_loose) THEN
1367 g_base_select := g_base_select
1368 || ','
1369 || g_base_table_alias
1370 || '.LPN_ID'
1371 || g_line_feed;
1372 ELSE
1373 g_base_select := g_base_select
1374 || ',decode(g_lpn_id, -9999, NULL, g_lpn_id) LPN_ID'
1375 || g_line_feed;
1376 END IF;
1377 /* 2/21/02 - no longer need these args, since put and pick packages
1378 * are not build differently
1379 * else --put away
1380 * --for put, get cost group from wms_transactions_temp,
1381 * -- not input table (wms_trx_details_tmp_v)
1382 * g_base_select := g_base_select ||',NULL cost_group_id'
1383 * || g_line_feed;
1384 * g_base_select := g_base_select ||',NULL uom_code'
1385 * || g_line_feed;
1386 */
1387 END IF;
1388
1389 --
1390 -- Build type code independent 'from' skeleton
1391 g_base_from := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1392 g_base_from_serial := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1393 g_base_from_serial_v := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1394 g_base_from_serial_detail := l_input_table_name || ' ' || g_input_table_alias || g_line_feed;
1395
1396 --
1397 -- Add type code dependent part to 'from' skeleton
1398 -- We need to build 9 different putaway cursors using 3 different put
1399 -- bases. So, here we insert a place holder (:g_put_base) which we will
1400 -- replace in GenerateRulePackage with the appropriate base
1401 IF p_type_code = 1 THEN -- put away
1402 g_base_from := g_base_from || ',(:g_put_base)' || g_base_table_alias || g_line_feed;
1403 ELSIF p_type_code = 2 THEN -- pick
1404 --need to generate 2 pick bases - one for non-serial controlled,
1405 --and one for serial control, since we won't know whether
1406 -- the inventory item is serial controlled until the stored
1407 -- procedure is run.
1408 IF p_allocation_mode_id = g_alloc_lpn_only THEN
1409 g_pick_base := g_pick_base_lpn_only;
1410 ELSIF p_allocation_mode_id = g_alloc_lpn_loose THEN
1411 g_pick_base := g_pick_base_lpn_loose;
1412 ELSE
1413 /**
1414 *Bug 2310403
1415 *Errors allocating for LPN putaway move orders.
1416 *The problem occurs because we should only pick material
1417 *from a certain LPN, but the base returned by build_sql
1418 *does not have an LPN_ID. So now, we'll use the lpn_loose
1419 *base, and add a group_by statement on the outermost query
1420 *so that we only get one rec per rev/lot/sub/loc when we
1421 *aren't allocating LPNs
1422 *--build non-serial controlled pick base
1423 *log_statement(l_api_name, 'build_sql_no_serial',
1424 * 'Calling inv_detail_util_pvt.build_sql for base');
1425 *inv_detail_util_pvt.build_sql
1426 *( x_return_status => l_return_status ,
1427 * x_sql_statement => g_pick_base
1428 * );
1429 *IF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
1430 * log_statement(l_api_name, 'err_build_sql',
1431 * 'Error in inv_detail_util_pvt.build_sql');
1432 * RAISE fnd_api.g_exc_unexpected_error;
1433 *ELSIF l_return_status = fnd_api.g_ret_sts_error THEN
1434 * log_statement(l_api_name, 'unexp_err_build_sql',
1435 * 'Unexp. error in inv_detail_util_pvt.build_sql');
1436 * RAISE fnd_api.g_exc_error;
1437 *END IF;
1438 *log_statement(l_api_name, 'success_build_sql',
1439 * 'Inv_detail_util_pvt.build_sql successful');
1440
1441 *-- replace the bind variables used in the base sql
1442 *-- with the global variables in the stored rule procedure
1443 *g_pick_base :=
1444 * REPLACE(g_pick_base,':organization_id','g_organization_id');
1445 *g_pick_base :=
1446 * REPLACE(g_pick_base,':inventory_item_id','g_inventory_item_id');
1447 */
1448 g_pick_base := g_pick_base_lpn_loose;
1449 END IF;
1450
1451 /*LPN Status Project*/
1452 -- The conversion_rate (found using GetConversionRate) is used
1453 -- to order picking locations from largest Pick UOM to smallest.
1454 -- The API call to is_sub_loc_lot_trx_allowed checks the status
1455 -- of the subinventory, locator, and lot to make sure that we can
1456 -- pick from this location
1457 g_pick_base := g_line_feed
1458 || 'SELECT x.organization_id organization_id '
1459 || g_line_feed
1460 || ' ,x.inventory_item_id inventory_item_id '
1461 || g_line_feed
1462 || ' ,x.revision revision '
1463 || g_line_feed
1464 || ' ,x.lot_number lot_number '
1465 || g_line_feed
1466 || ' ,x.lot_expiration_date lot_expiration_date '
1467 || g_line_feed
1468 || ' ,x.subinventory_code subinventory_code '
1469 || g_line_feed
1470 || ' ,x.locator_id locator_id '
1471 || g_line_feed
1472 || ' ,x.cost_group_id cost_group_id '
1473 || g_line_feed
1474 || ' ,x.status_id status_id ' --added status_id
1475 || g_line_feed
1476 || ' ,NULL serial_number '
1477 || g_line_feed
1478 || ' ,x.lpn_id lpn_id '
1479 || g_line_feed
1480 || ' ,x.project_id project_id '
1481 || g_line_feed
1482 || ' ,x.task_id task_id '
1483 || g_line_feed
1484 || ' ,x.date_received date_received '
1485 || g_line_feed
1486 || ' ,x.primary_quantity primary_quantity '
1487 || g_line_feed
1488 || ' ,x.secondary_quantity secondary_quantity ' -- new
1489 || g_line_feed -- new
1490 || ' ,x.grade_code grade_code ' -- new
1491 || g_line_feed -- new
1492 || ' ,x.reservable_type reservable_type '
1493 || g_line_feed
1494 || ' ,x.locreservable locreservable ' -- Bug 6719290 Start
1495 || g_line_feed
1496 || ' ,x.lotreservable lotreservable '
1497 || g_line_feed -- Bug 6719290 End
1498 || ' ,NVL(loc.pick_uom_code,sub.pick_uom_code) uom_code'
1499 || g_line_feed
1500 || ' ,WMS_Rule_PVT.GetConversionRate( '
1501 || g_line_feed
1502 || ' NVL(loc.pick_uom_code, sub.pick_uom_code) '
1503 || g_line_feed
1504 || ' ,x.organization_id '
1505 || g_line_feed
1506 || ' ,x.inventory_item_id) conversion_rate '
1507 || g_line_feed
1508 || ' ,NULL locator_inventory_item_id '
1509 || g_line_feed
1510 || ' ,NULL empty_flag '
1511 || g_line_feed
1512 || ' ,NULL location_current_units '
1513 || g_line_feed
1514 || 'FROM ('
1515 || g_pick_base
1516 --extra line feed? || g_line_feed
1517 || ' ) x '
1518 || g_line_feed
1519 || ' ,mtl_secondary_inventories sub '
1520 || g_line_feed
1521 || ' ,mtl_item_locations loc '
1522 || g_line_feed
1523 || 'WHERE x.organization_id = loc.organization_id (+) '
1524 || g_line_feed
1525 || ' AND x.locator_id = loc.inventory_location_id (+)'
1526 || g_line_feed
1527 || ' AND sub.organization_id = x.organization_id '
1528 || g_line_feed
1529 || ' AND sub.secondary_inventory_name = x.subinventory_code '
1530 || g_line_feed; /*
1531 || ' AND inv_detail_util_pvt.is_sub_loc_lot_trx_allowed('
1532 || g_line_feed
1533 || ' g_transaction_type_id, '
1534 || g_line_feed
1535 || ' x.organization_id, '
1536 || g_line_feed
1537 || ' x.inventory_item_id, '
1538 || g_line_feed
1539 || ' x.subinventory_code, '
1540 || g_line_feed
1541 || ' x.locator_id, '
1542 || g_line_feed
1543 || ' x.lot_number)=''Y'' '
1544 || g_line_feed; */
1545 --
1546
1547 -- finally apply the corrections to the basis SQL
1548 g_base_from := g_base_from || ',(' || g_pick_base || ') '
1549 || g_base_table_alias || g_line_feed;
1550 --Construct the base for the serial cursor
1551 g_base_from_serial := g_base_from_serial || ',(' || g_pick_base_serial;
1552 g_base_from_serial_v := g_base_from_serial_v || ',(' || g_pick_base_serial_v;
1553 g_base_from_serial_detail := g_base_from_serial_detail || ',(' || g_pick_base_serial_detail;
1554
1555 --need to add restrictions to serial base if we are allocating
1556 -- entire LPNs only
1557 --bug 2943552
1558 -- previoulsy, we were adding the new clause directly to
1559 -- g_pick_base_serial. However, g_pick_base_serial is a global
1560 -- constant string that never gets cleared. As a result, all
1561 -- subsequent serial sql statements would get this restriction.
1562 -- Now, we add the entire lpn only clause to g_base_from_serial.
1563 --bug 3064635 - after above fix, we were missing initial
1564 -- parantheses, because we were concatenating clause with
1565 -- g_pick_base_serial. Now, we concatenate clause with
1566 -- g_base_from_serial
1567 IF p_allocation_mode_id = g_alloc_lpn_only THEN
1568 g_base_from_serial := g_base_from_serial
1569 || 'and msn.lpn_id IS NOT NULL
1570 and not exists(
1571 select lpn_id
1572 from wms_license_plate_numbers wlpn1
1573 where wlpn1.parent_lpn_id = msn.lpn_id)
1574 and
1575 1 = (select count(distinct(moq1.inventory_item_id))
1576 from mtl_onhand_quantities_detail moq1
1577 where moq1.organization_id = msn.current_organization_id
1578 and moq1.subinventory_code = msn.current_subinventory_code
1579 and moq1.locator_id = msn.current_locator_id
1580 and moq1.lpn_id = msn.lpn_id)
1581 ';
1582 -- END IF;
1583 /* g_base_from_serial := g_base_from_serial || ')' || g_base_table_alias
1584 || g_line_feed; */
1585
1586 ---
1587 g_base_from_serial_v :=
1588 g_base_from_serial_v
1589 || ' and msn.lpn_id IS NOT NULL
1590 and not exists(
1591 select lpn_id
1592 from wms_license_plate_numbers wlpn1
1593 where wlpn1.parent_lpn_id = msn.lpn_id)
1594 and
1595 1 = (select count(distinct(moq1.inventory_item_id))
1596 from mtl_onhand_quantities_detail moq1
1597 where moq1.organization_id = msn.current_organization_id
1598 and moq1.subinventory_code = msn.current_subinventory_code
1599 and moq1.locator_id = msn.current_locator_id
1600 and moq1.lpn_id = msn.lpn_id)
1601 ';
1602
1603 ---
1604 g_base_from_serial_detail :=
1605 g_base_from_serial_detail
1606 || ' and msn.lpn_id IS NOT NULL
1607 and not exists(
1608 select lpn_id
1609 from wms_license_plate_numbers wlpn1
1610 where wlpn1.parent_lpn_id = msn.lpn_id)
1611 and
1612 1 = (select count(distinct(moq1.inventory_item_id))
1613 from mtl_onhand_quantities_detail moq1
1614 where moq1.organization_id = msn.current_organization_id
1615 and moq1.subinventory_code = msn.current_subinventory_code
1616 and moq1.locator_id = msn.current_locator_id
1617 and moq1.lpn_id = msn.lpn_id)
1618 ';
1619
1620 END IF;
1621
1622 g_base_from_serial := g_base_from_serial || ')' || g_base_table_alias
1623 || g_line_feed;
1624 g_base_from_serial_v := g_base_from_serial_v || ')' || g_base_table_alias
1625 || g_line_feed;
1626
1627 g_base_from_serial_detail := g_base_from_serial_detail || ')' || g_base_table_alias
1628 || g_line_feed;
1629
1630 --
1631 END IF;
1632
1633 --currently used only for serial controlled item, when you aren't
1634 -- detailing serial numbers
1635 g_base_group_by := g_base_table_alias
1636 || '.ORGANIZATION_ID'
1637 || g_line_feed
1638 || ','
1639 || g_base_table_alias
1640 || '.INVENTORY_ITEM_ID'
1641 || g_line_feed
1642 || ','
1643 || l_type_dependent_alias
1644 || '.REVISION'
1645 || g_line_feed
1646 || ','
1647 || l_type_dependent_alias
1648 || '.LOT_NUMBER'
1649 || g_line_feed
1650 || ','
1651 || g_base_table_alias
1652 || '.LOT_EXPIRATION_DATE'
1653 || g_line_feed
1654 || ','
1655 || g_base_table_alias
1656 || '.SUBINVENTORY_CODE'
1657 || g_line_feed
1658 || ','
1659 || g_base_table_alias
1660 || '.LOCATOR_ID'
1661 || g_line_feed
1662 || ','
1663 || g_base_table_alias
1664 || '.COST_GROUP_ID'
1665 || g_line_feed
1666 || ','
1667 || g_base_table_alias
1668 || '.PROJECT_ID'
1669 || g_line_feed
1670 || ','
1671 || g_base_table_alias
1672 || '.TASK_ID'
1673 || g_line_feed
1674 || ','
1675 || g_base_table_alias
1676 || '.UOM_CODE'
1677 || g_line_feed
1678 || ',' --new
1679 || g_base_table_alias --new
1680 || '.GRADE_CODE' --new
1681 || g_line_feed; --new
1682
1683 --
1684 -- group by the base lpn id only if the lpn id is in the select statement
1685 IF p_allocation_mode_id IN (g_alloc_lpn_only, g_alloc_lpn_loose) THEN
1686 g_base_group_by := g_base_group_by || ',' || g_base_table_alias || '.LPN_ID' || g_line_feed;
1687 END IF;
1688
1689 -- debugging portion
1690 -- can be commented ut for final code
1691 log_procedure(l_api_name, 'end', 'End BuildBaseSql');
1692 -- end of debugging section
1693 --
1694 EXCEPTION
1695 WHEN fnd_api.g_exc_error THEN
1696 x_return_status := fnd_api.g_ret_sts_error;
1697 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1698 --
1699 log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
1700 --
1701 WHEN fnd_api.g_exc_unexpected_error THEN
1702 x_return_status := fnd_api.g_ret_sts_unexp_error;
1703 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1704 --
1705 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
1706
1707 --
1708 WHEN OTHERS THEN
1709 x_return_status := fnd_api.g_ret_sts_unexp_error;
1710
1711 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
1712 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
1713 END IF;
1714
1715 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
1716 --
1717 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
1718
1719 END buildbasesql;
1720
1721 --
1722 -- Name : BuildRuleSQL
1723 -- Function : Builds the rule dependent part of the rule's sql statement
1724 -- Notes : private procedure for internal use only
1725 PROCEDURE buildrulesql(
1726 x_return_status OUT NOCOPY VARCHAR2
1727 , x_msg_count OUT NOCOPY NUMBER
1728 , x_msg_data OUT NOCOPY VARCHAR2
1729 , p_rule_id IN NUMBER
1730 , p_type_code IN NUMBER
1731 , p_allocation_mode_id IN NUMBER
1732 ) IS
1733 --
1734 l_api_name VARCHAR2(30) := 'BuildRuleSQL';
1735 -- variables needed for dynamic SQL
1736 l_identifier VARCHAR2(10);
1737 -- other variables
1738 l_db_object_id wms_db_objects.db_object_id%TYPE;
1739 l_table_name wms_db_objects.table_name%TYPE;
1740 l_table_alias wms_db_objects.table_alias%TYPE;
1741 l_context_dependent_flag wms_db_objects.context_dependent_flag%TYPE;
1742 l_parent_table_alias wms_db_objects.table_alias%TYPE;
1743 l_parameter_type_code wms_parameters_b.parameter_type_code%TYPE;
1744 l_column_name wms_parameters_b.column_name%TYPE;
1745 l_expression wms_parameters_b.expression%TYPE;
1746 l_data_type_code wms_parameters_b.data_type_code%TYPE;
1747 l_parent_parameter_type_code wms_parameters_b.parameter_type_code%TYPE;
1748 l_parent_column_name wms_parameters_b.column_name%TYPE;
1749 l_parent_expression wms_parameters_b.expression%TYPE;
1750 l_parent_data_type_code wms_parameters_b.data_type_code%TYPE;
1751 l_operand_type_code wms_restrictions.operand_type_code%TYPE;
1752 l_operand_constant_number wms_restrictions.operand_constant_number%TYPE;
1753 l_operand_constant_character wms_restrictions.operand_constant_character%TYPE;
1754 l_operand_constant_date wms_restrictions.operand_constant_date%TYPE;
1755 l_operand_expression wms_restrictions.operand_expression%TYPE;
1756 l_operand_flex_value_set_id wms_restrictions.operand_flex_value_set_id%TYPE;
1757 l_bracket_open wms_restrictions.bracket_open%TYPE;
1758 l_bracket_close wms_restrictions.bracket_close%TYPE;
1759 l_validation_type fnd_flex_value_sets.validation_type%TYPE;
1760 l_id_column_name fnd_flex_validation_tables.id_column_name%TYPE;
1761 l_value_column_name fnd_flex_validation_tables.value_column_name%TYPE;
1762 l_application_table_name fnd_flex_validation_tables.application_table_name%TYPE;
1763 l_additional_where_clause fnd_flex_validation_tables.additional_where_clause%TYPE;
1764 l_left_part_conv_fct VARCHAR2(40);
1765 l_right_part_conv_fct VARCHAR2(40);
1766 l_outer_join VARCHAR2(4);
1767 l_logical_operator mfg_lookups.meaning%TYPE;
1768 l_asc_desc mfg_lookups.meaning%TYPE;
1769 l_operator mfg_lookups.meaning%TYPE;
1770 l_restriction_exist BOOLEAN := FALSE;
1771 l_rule_id NUMBER;
1772 l_sequence_number NUMBER;
1773 l_flex_column_name fnd_flex_validation_tables.id_column_name%TYPE;
1774 l_order_by_string VARCHAR2(1000);
1775 l_new_constant_character VARCHAR2(500);
1776 --l_new_expression VARCHAR2(4100);
1777 l_consist_string VARCHAR2(1000);
1778
1779 -- cursor for all DB objects used within the rule.
1780 -- Most objects found using this query correspond to a database table
1781 -- which must be added to the from clause.
1782 -- DB Objects 1 and 2 are always included in the from clause, so
1783 -- we don't need to get them with this query.
1784 --
1785 -- 2/21/02 - remove quantity function objects from this query. For
1786 -- putaway, we check quantity function in the Apply function.
1787 -- For picking, the quantity function object is "base", which is always
1788 -- included
1789 CURSOR objects IS
1790 -- 1. all single referenced DB objects
1791 SELECT wdo.db_object_id
1792 , wdo.table_name
1793 , wdo.table_alias
1794 , wdo.context_dependent_flag
1795 FROM wms_db_objects wdo
1796 , wms_parameters_b wpb
1797 , (SELECT wsc.parameter_id
1798 FROM wms_sort_criteria wsc
1799 WHERE wsc.rule_id = p_rule_id
1800 UNION
1801 SELECT wr.parameter_id
1802 FROM wms_restrictions wr
1803 WHERE wr.rule_id = p_rule_id
1804 UNION
1805 SELECT wr.operand_parameter_id
1806 FROM wms_restrictions wr
1807 WHERE wr.rule_id = p_rule_id
1808 AND wr.operand_type_code = 4
1809 UNION
1810 SELECT wrc.parameter_id
1811 FROM wms_rule_consistencies wrc
1812 WHERE wrc.rule_id = p_rule_id) x
1813 WHERE wpb.parameter_id = x.parameter_id
1814 AND wpb.db_object_ref_type_code = 1
1815 AND wdo.db_object_id = wpb.db_object_id
1816 AND wdo.db_object_id NOT IN (1, 2)
1817 UNION
1818 -- 2. all parents of single referenced DB objects
1819 SELECT wdo.db_object_id
1820 , wdo.table_name
1821 , wdo.table_alias
1822 , wdo.context_dependent_flag
1823 FROM wms_db_objects wdo
1824 , (SELECT wdop.parent_db_object_id
1825 FROM wms_db_objects_parents wdop
1826 WHERE wdop.type_code = p_type_code
1827 CONNECT BY wdop.db_object_id = PRIOR wdop.parent_db_object_id
1828 START WITH wdop.db_object_id IN (SELECT wdod.db_object_id
1829 FROM wms_db_objects wdod
1830 , wms_parameters_b wpbd
1831 , (SELECT wscd.parameter_id
1832 FROM wms_sort_criteria wscd
1833 WHERE wscd.rule_id = p_rule_id
1834 UNION
1835 SELECT wrd.parameter_id
1836 FROM wms_restrictions wrd
1837 WHERE wrd.rule_id = p_rule_id
1838 UNION
1839 SELECT wrd.operand_parameter_id
1840 FROM wms_restrictions wrd
1841 WHERE wrd.rule_id = p_rule_id
1842 AND wrd.operand_type_code = 4
1843 UNION
1844 SELECT wrcd.parameter_id
1845 FROM wms_rule_consistencies wrcd
1846 WHERE wrcd.rule_id = p_rule_id) xd
1847 WHERE wpbd.parameter_id = xd.parameter_id
1848 AND wpbd.db_object_ref_type_code = 1
1849 AND wdod.db_object_id = wpbd.db_object_id)) x
1850 WHERE wdo.db_object_id = x.parent_db_object_id
1851 AND wdo.db_object_id NOT IN (1, 2)
1852 -- 3. all multi referenced DB objects
1853 UNION
1854 SELECT wdo.db_object_id
1855 , wdo.table_name
1856 , NVL(wdorm.table_alias, wdo.table_alias)
1857 , wdo.context_dependent_flag
1858 FROM wms_db_objects wdo
1859 , wms_db_obj_ref_members wdorm
1860 , wms_db_object_references wdor
1861 , wms_parameters_b wpb
1862 , (SELECT wsc.parameter_id
1863 FROM wms_sort_criteria wsc
1864 WHERE wsc.rule_id = p_rule_id
1865 UNION
1866 SELECT wr.parameter_id
1867 FROM wms_restrictions wr
1868 WHERE wr.rule_id = p_rule_id
1869 UNION
1870 SELECT wr.operand_parameter_id
1871 FROM wms_restrictions wr
1872 WHERE wr.rule_id = p_rule_id
1873 AND wr.operand_type_code = 4
1874 UNION
1875 SELECT wrc.parameter_id
1876 FROM wms_rule_consistencies wrc
1877 WHERE wrc.rule_id = p_rule_id) x
1878 WHERE wpb.parameter_id = x.parameter_id
1879 AND wpb.db_object_ref_type_code = 2
1880 AND wdor.db_object_reference_id = wpb.db_object_reference_id
1881 AND wdorm.db_object_reference_id = wdor.db_object_reference_id
1882 AND wdo.db_object_id = wdorm.db_object_id
1883 AND wdo.db_object_id NOT IN (1, 2)
1884 UNION
1885 -- 4. all parents of multi referenced DB objects
1886 SELECT wdo.db_object_id
1887 , wdo.table_name
1888 , wdo.table_alias
1889 , wdo.context_dependent_flag
1890 FROM wms_db_objects wdo
1891 , (SELECT wdop.parent_db_object_id
1892 FROM wms_db_objects_parents wdop
1893 WHERE wdop.type_code = p_type_code
1894 CONNECT BY wdop.db_object_id = PRIOR wdop.parent_db_object_id
1895 START WITH wdop.db_object_id IN (SELECT wdoi.db_object_id
1896 FROM wms_db_objects wdoi
1897 , wms_db_obj_ref_members wdormi
1898 , wms_db_object_references wdori
1899 , wms_parameters_b wpbi
1900 , (SELECT wsc.parameter_id
1901 FROM wms_sort_criteria wsc
1902 WHERE wsc.rule_id = p_rule_id
1903 UNION
1904 SELECT wr.parameter_id
1905 FROM wms_restrictions wr
1906 WHERE wr.rule_id = p_rule_id
1907 UNION
1908 SELECT wr.operand_parameter_id
1909 FROM wms_restrictions wr
1910 WHERE wr.rule_id = p_rule_id
1911 AND wr.operand_type_code = 4
1912 UNION
1913 SELECT wrc.parameter_id
1914 FROM wms_rule_consistencies wrc
1915 WHERE wrc.rule_id = p_rule_id) xi
1916 WHERE wpbi.parameter_id = xi.parameter_id
1917 AND wpbi.db_object_ref_type_code = 2
1918 AND wdori.db_object_reference_id = wpbi.db_object_reference_id
1919 AND wdormi.db_object_reference_id = wdori.db_object_reference_id
1920 AND wdoi.db_object_id = wdormi.db_object_id)) x
1921 WHERE wdo.db_object_id = x.parent_db_object_id
1922 AND wdo.db_object_id NOT IN (1, 2)
1923 ORDER BY 1;
1924
1925 --
1926 -- Finds the join conditions to join a DB object to it's parent
1927 -- DB object. This is used to build the where clause for the rule.
1928 CURSOR conditions IS
1929 SELECT wpb.parameter_type_code
1930 , wpb.column_name
1931 , wpb.expression
1932 , wpb.data_type_code
1933 , wpbp.parameter_type_code
1934 , wpbp.column_name
1935 , wpbp.expression
1936 , wpbp.data_type_code
1937 , wdop.table_alias -- alias n.a. for multi object based parameters
1938 FROM wms_db_objects wdop, wms_parameters_b wpbp, wms_parameters_b wpb, wms_db_object_joins wdoj
1939 WHERE wdoj.db_object_id = l_db_object_id
1940 AND wdoj.type_code = p_type_code
1941 AND wpb.parameter_id = wdoj.parameter_id
1942 AND wpbp.parameter_id = wdoj.parent_parameter_id
1943 AND wdop.db_object_id(+) = wpbp.db_object_id;
1944
1945 --
1946 -- cursor for the quantity function parameter of the actual rule.
1947 -- Used only for picking and putaway
1948 CURSOR qtyfnct IS
1949 SELECT wpb.parameter_type_code
1950 , wpb.column_name
1951 , wpb.expression
1952 , wpb.data_type_code
1953 , wdo.table_alias -- alias n.a. for multi object based parameters
1954 FROM wms_db_objects wdo, wms_parameters_b wpb, wms_rules_b wrb
1955 WHERE wrb.rule_id = p_rule_id
1956 AND wpb.parameter_id = wrb.qty_function_parameter_id
1957 AND wdo.db_object_id(+) = wpb.db_object_id;
1958
1959 --
1960 -- Finds the restrictions defined in the rule.
1961 -- Each restriction becomes part of the where clause.
1962 CURSOR RESTRICT IS
1963 SELECT wpbl.parameter_type_code
1964 , wpbl.column_name
1965 , wpbl.expression
1966 , wpbl.data_type_code
1967 , wdol.table_alias -- alias n.a. for multi object based parameters
1968 , DECODE(
1969 wr.operator_code
1970 , 1, '>'
1971 , 2, '<'
1972 , 3, '='
1973 , 4, '<>'
1974 , 5, '>='
1975 , 6, '<='
1976 , 7, 'IN'
1977 , 8, 'NOT IN'
1978 , 9, 'LIKE'
1979 , 10, 'NOT LIKE'
1980 , 11, 'IS NULL'
1981 , 12, 'IS NOT NULL'
1982 , NULL
1983 )
1984 , wr.operand_type_code
1985 , wr.operand_constant_number
1986 , wr.operand_constant_character
1987 , wr.operand_constant_date
1988 , wr.operand_expression
1989 , wr.operand_flex_value_set_id
1990 , DECODE(wr.logical_operator_code, 1, 'and', 2, 'or', NULL)
1991 , wr.bracket_open
1992 , wr.bracket_close
1993 , wpbr.parameter_type_code
1994 , wpbr.column_name
1995 , wpbr.expression
1996 , DECODE(
1997 wr.operand_type_code
1998 , 4, wpbr.data_type_code
1999 , 5, wpbl.data_type_code
2000 , 6, DECODE(ffvs.format_type, 'N', 1, 'C', 2, 3)
2001 , 7, NULL
2002 , wr.operand_type_code
2003 )
2004 , wdor.table_alias -- alias n.a. for multi object based parameters
2005 , ffvs.validation_type -- only 'independent' and 'table' are supported
2006 , ffvt.id_column_name
2007 , ffvt.value_column_name
2008 , ffvt.application_table_name
2009 , ffvt.additional_where_clause
2010 , wr.rule_id
2011 , wr.sequence_number
2012 FROM fnd_flex_validation_tables ffvt
2013 , fnd_flex_value_sets ffvs
2014 , wms_db_objects wdor
2015 , wms_parameters_b wpbr
2016 , wms_db_objects wdol
2017 , wms_parameters_b wpbl
2018 , wms_restrictions wr
2019 WHERE wr.rule_id = p_rule_id
2020 AND wpbl.parameter_id = wr.parameter_id
2021 AND wdol.db_object_id(+) = wpbl.db_object_id
2022 AND wpbr.parameter_id(+) = wr.operand_parameter_id
2023 AND wdor.db_object_id(+) = wpbr.db_object_id
2024 AND ffvs.flex_value_set_id(+) = wr.operand_flex_value_set_id
2025 AND ffvt.flex_value_set_id(+) = wr.operand_flex_value_set_id
2026 ORDER BY wr.rule_id, wr.sequence_number -- order is important
2027 ;
2028
2029 --
2030 -- Finds the Sort criteria entries for this rule. Each sort criterion
2031 -- becomes a part of the order by clause of the sql statement.
2032 CURSOR sortcrit IS
2033 SELECT wpb.parameter_type_code
2034 , wpb.column_name
2035 , wpb.expression
2036 , wpb.data_type_code
2037 , wdo.table_alias -- alias n.a. for multi object based parameters
2038 , wms_parameter_pvt.getflexdatatypecode(
2039 wpb.data_type_code
2040 , wpb.db_object_ref_type_code
2041 , wpb.parameter_type_code
2042 , wpb.flexfield_usage_code
2043 , wpb.flexfield_application_id
2044 , wpb.flexfield_name
2045 , wpb.column_name
2046 )
2047 , DECODE(wsc.order_code, 1, 'asc', 2, 'desc', NULL)
2048 , wsc.rule_id
2049 , wsc.sequence_number
2050 FROM wms_db_objects wdo, wms_parameters_b wpb, wms_sort_criteria wsc
2051 WHERE wsc.rule_id = p_rule_id
2052 AND wpb.parameter_id = wsc.parameter_id
2053 AND wdo.db_object_id(+) = wpb.db_object_id
2054 ORDER BY wsc.rule_id, wsc.sequence_number;
2055
2056 --
2057 -- Used to find all the consistency restrictions for the rule.
2058 -- Used to build portions of the Select and order by clauses.
2059 CURSOR consistencies IS
2060 SELECT wpb.parameter_type_code
2061 , wpb.column_name
2062 , wpb.expression
2063 , wdo.table_alias
2064 FROM wms_rule_consistencies wrc, wms_parameters_b wpb, wms_db_objects wdo
2065 WHERE wrc.rule_id = p_rule_id
2066 AND wpb.parameter_id = wrc.parameter_id
2067 AND wdo.db_object_id(+) = wpb.db_object_id;
2068 BEGIN
2069 -- Initialize API return status to success
2070 x_return_status := fnd_api.g_ret_sts_success;
2071
2072 log_procedure(l_api_name, 'start', 'Start BuildRuleSql');
2073 log_statement(l_api_name, 'rule_id', 'rule_id: ' || p_rule_id);
2074 log_statement(l_api_name, 'type_code', 'type_code: ' || p_type_code);
2075
2076 -- end of debugging section
2077 --
2078 --If no rule, build default rule
2079 IF p_rule_id IS NULL THEN
2080 log_statement(l_api_name, 'null_rule_id', 'Rule id is NULL');
2081
2082 -- if no rule and strategy is defined
2083 -- hardcoded this section
2084 IF p_type_code = 2 THEN
2085 g_rule_select := 'NULL serial_number
2086 ,nvl(base.primary_quantity,0)
2087 ,nvl(base.secondary_quantity,0) -- new
2088 ,base.grade_code, -- new
2089 ,NULL consist_string,
2090 ,NULL order_by_string';
2091 g_rule_from := ' mtl_system_items msi, ';
2092 g_rule_where :=
2093 ' and msi.ORGANIZATION_ID = mptdtv.FROM_ORGANIZATION_ID
2094 and msi.INVENTORY_ITEM_ID = mptdtv.inventory_item_id ';
2095 ELSE
2096 g_rule_select := 'NULL serial_number
2097 ,nvl(WMS_Parameter_PVT.GetAvailableUnitCapacity
2098 ( mptdtv.TO_ORGANIZATION_ID
2099 ,base.SUBINVENTORY_CODE
2100 ,base.LOCATOR_ID
2101 ,mil.LOCATION_MAXIMUM_UNITS
2102 )
2103 ,0)
2104 ,NULL consist_string
2105 ,NULL order_by_string';
2106 g_rule_from := ' mtl_item_locations mil , ';
2107 g_rule_where := ' and mil.ORGANIZATION_ID (+) = base.ORGANIZATION_ID
2108 and mil.INVENTORY_LOCATION_ID (+) = base.locator_id ';
2109 END IF;
2110
2111 g_rule_order := NULL;
2112 --
2113 x_return_status := fnd_api.g_ret_sts_success;
2114 RETURN;
2115 END IF;
2116
2117 -- Find all DB objects referenced within the rule and add them to the
2118 -- from clause.
2119 log_statement(l_api_name, 'start_objects', 'start objects loop');
2120 OPEN objects;
2121
2122 WHILE TRUE LOOP
2123 FETCH objects INTO l_db_object_id, l_table_name, l_table_alias, l_context_dependent_flag;
2124 EXIT WHEN objects%NOTFOUND;
2125 log_statement(l_api_name, 'db_object_id', 'db_object_id: ' || l_db_object_id);
2126
2127 --
2128 -- Add DB objects to the from clause
2129
2130 -- For TTA, if g_rule_from is NULL, do no add ','
2131 -- Don't add a comma for the first table in the from clause
2132 IF (g_rule_from IS NULL)
2133 AND (p_type_code IN (3, 4, 5, 7)) THEN -- brach for TTA
2134 g_rule_from := l_table_name || ' ' || l_table_alias;
2135 ELSE
2136 g_rule_from := l_table_name || ' ' || l_table_alias || g_line_feed || ',' || g_rule_from;
2137 END IF; -- end TTA branch
2138
2139 -- Find each join condition joining current db object to its
2140 -- parent db object. Add these conditions to the where clause.
2141 log_statement(l_api_name, 'start_conditions', 'start conditions loop');
2142 OPEN conditions;
2143
2144 WHILE TRUE LOOP
2145 FETCH conditions INTO l_parameter_type_code
2146 , l_column_name
2147 , l_expression
2148 , l_data_type_code
2149 , l_parent_parameter_type_code
2150 , l_parent_column_name
2151 , l_parent_expression
2152 , l_parent_data_type_code
2153 , l_parent_table_alias;
2154 EXIT WHEN conditions%NOTFOUND;
2155 --
2156 log_statement(l_api_name, 'param_type_code', 'param_type_code: ' || l_parameter_type_code);
2157 log_statement(l_api_name, 'column_name', 'column_name: ' || l_column_name);
2158 log_statement(l_api_name, 'expression', 'expression: ' || l_expression);
2159 log_statement(l_api_name, 'data_type_code', 'data_type_code: ' || l_data_type_code);
2160 log_statement(l_api_name, 'parent_param_type_code', 'parent_param_type_code: ' || l_parent_parameter_type_code);
2161 log_statement(l_api_name, 'parent_column_name', 'parent_column_name: ' || l_parent_column_name);
2162 log_statement(l_api_name, 'parent_expression', 'parent_expression: ' || l_parent_expression);
2163 log_statement(l_api_name, 'parent_data_type_code', 'parent_data_type_code: ' || l_parent_data_type_code);
2164 log_statement(l_api_name, 'parent_table_alias', 'parent_table_alias: ' || l_parent_table_alias);
2165 -- find out, if data type conversion is needed
2166 inv_sql_binding_pvt.getconversionstring(l_data_type_code, l_parent_data_type_code, l_left_part_conv_fct, l_right_part_conv_fct);
2167
2168 --
2169 -- find out, if outer join has to be used
2170 IF l_context_dependent_flag = 'Y' THEN
2171 l_outer_join := ' (+)';
2172 ELSIF l_context_dependent_flag = 'N' THEN
2173 l_outer_join := NULL;
2174 ELSE
2175 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2176 fnd_message.set_name('WMS', 'WMS_BAD_CONTEXT_DEPT_FLAG');
2177 fnd_message.set_token('CONTEXT_DEPENDENT_FLAG', l_context_dependent_flag);
2178 log_error_msg(l_api_name, 'bad_context_depend_flag');
2179 fnd_msg_pub.ADD;
2180 END IF;
2181
2182 RAISE fnd_api.g_exc_error;
2183 END IF;
2184
2185 --
2186 -- add join conditions to where clause
2187 -- first, build the left side of the join
2188 g_rule_where := g_rule_where || 'and ';
2189
2190 IF l_parameter_type_code = 1 THEN -- based on column in table
2191 g_rule_where := g_rule_where || l_table_alias || '.' || l_column_name || l_outer_join;
2192 ELSIF l_parameter_type_code = 2 THEN -- based on expression
2193 --g_rule_where := g_rule_where || l_expression || l_outer_join;
2194 g_rule_where := g_rule_where || l_expression ; -- || l_outer_join; --Bug #3719043
2195 ELSE
2196 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2197 fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2198 fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2199 log_error_msg(l_api_name, 'bad_param_type_code_joins');
2200 fnd_msg_pub.ADD;
2201 END IF;
2202
2203 RAISE fnd_api.g_exc_error;
2204 END IF;
2205
2206 -- add equal sign
2207 g_rule_where := g_rule_where || ' = ' || l_left_part_conv_fct;
2208
2209 -- now, build right side of join condition
2210 IF l_parent_parameter_type_code = 1 THEN
2211 g_rule_where := g_rule_where || l_parent_table_alias || '.' || l_parent_column_name;
2212 ELSIF l_parent_parameter_type_code = 2 THEN
2213 g_rule_where := g_rule_where || l_parent_expression;
2214 ELSE
2215 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2216 fnd_message.set_name('WMS', 'WMS_BAD_PARENT_PARA_TYPE');
2217 fnd_message.set_token('PARENT_PARAMETER_TYPE_CODE', l_parent_parameter_type_code);
2218 log_error_msg(l_api_name, 'bad_parent_param_type_joins');
2219 fnd_msg_pub.ADD;
2220 END IF;
2221
2222 RAISE fnd_api.g_exc_error;
2223 END IF;
2224
2225 g_rule_where := g_rule_where || l_right_part_conv_fct || g_line_feed;
2226 END LOOP;
2227
2228 CLOSE conditions;
2229 log_statement(l_api_name, 'end_conditions', 'end of conditions loop');
2230 END LOOP;
2231
2232 CLOSE objects;
2233 log_statement(l_api_name, 'end_objects', 'end of objects loop');
2234
2235 -- Add qty function parameter
2236 -- added by jcearley on 12/8/99
2237 -- qtyfunction should be added only for picking or putaway
2238 -- 2/21/02 - we no longer add the quantity function to the putaway
2239 -- sql statement. Instead, we check capacity in Apply.
2240 -- old code: IF (p_type_code IN (1,2)) THEN
2241 IF (p_type_code = 2) THEN
2242 -- Add serial number to select statement. If item is serial controlled,
2243 -- and we are detailing it, then get serial number from base. Otherwise,
2244 -- set serial number to NULL
2245 IF p_type_code = 2 THEN
2246 g_rule_select := g_rule_select || ',' || g_base_table_alias || '.SERIAL_NUMBER' || g_line_feed;
2247 ELSE
2248 g_rule_select := g_rule_select || ',NULL SERIAL_NUMBER' || g_line_feed;
2249 END IF;
2250
2251 -- Used when we are detailing a serial controlled item but
2252 -- not detailing serial numbers.
2253 g_rule_select_serial := g_rule_select_serial || ',NULL SERIAL_NUMBER' || g_line_feed;
2254 log_statement(l_api_name, 'qty_func', 'finding qty function');
2255 OPEN qtyfnct;
2256 FETCH qtyfnct INTO l_parameter_type_code, l_column_name, l_expression, l_data_type_code, l_table_alias;
2257
2258 IF qtyfnct%NOTFOUND THEN
2259 CLOSE qtyfnct;
2260
2261 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2262 fnd_message.set_name('WMS', 'WMS_QTY_FUNC_NOT_FOUND');
2263 log_error_msg(l_api_name, 'qty_func_not_found');
2264 fnd_msg_pub.ADD;
2265 END IF;
2266
2267 RAISE fnd_api.g_exc_error;
2268 END IF;
2269
2270 CLOSE qtyfnct;
2271 --
2272 log_statement(l_api_name, 'param_type_code_qty', 'param_type_code: ' || l_parameter_type_code);
2273 log_statement(l_api_name, 'column_name_qty', 'column_name: ' || l_column_name);
2274 log_statement(l_api_name, 'expression_qty', 'expression: ' || l_expression);
2275 log_statement(l_api_name, 'data_type_code_qty', 'data_type_code: ' || l_data_type_code);
2276 log_statement(l_api_name, 'table_alias_qty', 'table_alias: ' || l_table_alias);
2277
2278 IF l_data_type_code <> 1 THEN
2279 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2280 fnd_message.set_name('WMS', 'WMS_BAD_QTY_FUNC_DATA_TYPE');
2281 fnd_message.set_token('DATATYPE', l_data_type_code);
2282 log_error_msg(l_api_name, 'bad_qty_func_data_type');
2283 fnd_msg_pub.ADD;
2284 END IF;
2285
2286 RAISE fnd_api.g_exc_error;
2287 END IF;
2288
2289 --
2290
2291 -- Add qty function parameter to select clause
2292 IF l_parameter_type_code = 1 THEN
2293 g_rule_select := g_rule_select || ',nvl(' || l_table_alias || '.' || l_column_name || ',0)' || g_line_feed;
2294 g_rule_select_serial := g_rule_select_serial || ',sum(nvl(' || l_table_alias || '.' || l_column_name || ',0))' || g_line_feed;
2295 ELSIF l_parameter_type_code = 2 THEN
2296 -- Important Detail !!!
2297 -- Since the only quantity used by the engine internally
2298 -- for picking is the primary quantity,
2299 -- the expression from the parameter is ignored here.
2300 -- Instead, we only look at the primary quantity from the
2301 -- base.
2302 -- The next line is commented out and replaced with the
2303 -- line followed.
2304
2305 --updated by jcearley on 12/7/99
2306 -- primary quantity is only useful for picking. Thus, I'm adding a check
2307 -- on the type_code. If it's picking, use primary qty. If it's put away,
2308 -- use the previously commented out line.
2309 IF (p_type_code = 1) THEN --put away
2310 g_rule_select := g_rule_select
2311 || ',nvl(' || l_expression || ',0)'
2312 || g_line_feed;
2313 g_rule_select_serial := g_rule_select_serial
2314 || ',sum(nvl(' || l_expression || ',0))'
2315 || g_line_feed;
2316 ELSIF (p_type_code = 2) THEN
2317 g_rule_select := g_rule_select
2318 || ',base.primary_quantity ' || g_line_feed
2319 || ',base.secondary_quantity ' || g_line_feed -- new
2320 || ',base.grade_code ' || g_line_feed; -- new
2321 g_rule_select_serial := g_rule_select_serial
2322 || ',sum(base.primary_quantity) ' || g_line_feed
2323 || ',sum(base.secondary_quantity) ' || g_line_feed -- new
2324 || ',base.grade_code ' || g_line_feed; -- new
2325 END IF;
2326 ELSE
2327 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2328 fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2329 fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2330 log_error_msg(l_api_name, 'bad_param_type_code_qty');
2331 fnd_msg_pub.ADD;
2332 END IF;
2333
2334 RAISE fnd_api.g_exc_error;
2335 END IF; -- parameter type code = 1
2336 END IF; -- type code in 1,2
2337
2338 --
2339 log_statement(l_api_name, 'start_restrictions', 'start restrictions loop');
2340 -- Add restrictions
2341 OPEN RESTRICT;
2342
2343 --
2344 -- Loop through all the restrictions, adding them to where clause
2345 WHILE TRUE LOOP
2346 FETCH RESTRICT INTO l_parameter_type_code
2347 , l_column_name
2348 , l_expression
2349 , l_data_type_code
2350 , l_table_alias
2351 , l_operator
2352 , l_operand_type_code
2353 , l_operand_constant_number
2354 , l_operand_constant_character
2355 , l_operand_constant_date
2356 , l_operand_expression
2357 , l_operand_flex_value_set_id
2358 , l_logical_operator
2359 , l_bracket_open
2360 , l_bracket_close
2361 , l_parent_parameter_type_code
2362 , l_parent_column_name
2363 , l_parent_expression
2364 , l_parent_data_type_code
2365 , l_parent_table_alias
2366 , l_validation_type
2367 , l_id_column_name
2368 , l_value_column_name
2369 , l_application_table_name
2370 , l_additional_where_clause
2371 , l_rule_id
2372 , l_sequence_number;
2373 EXIT WHEN RESTRICT%NOTFOUND;
2374 --
2375 log_statement(l_api_name, 'sequence_num', 'sequence_num: ' || l_sequence_number);
2376
2377 -- For first restriction, add 'and (' before adding the restrictions.
2378 -- Needed to join restrictions and other join statements already in
2379 -- the where clause.
2380 IF l_restriction_exist = FALSE THEN
2381 l_restriction_exist := TRUE;
2382 g_rule_where := g_rule_where || 'and (' || g_line_feed;
2383 END IF;
2384
2385 --
2386 -- find out, if data type conversion is needed
2387 inv_sql_binding_pvt.getconversionstring(l_parent_data_type_code, l_data_type_code, l_left_part_conv_fct, l_right_part_conv_fct);
2388 log_statement(l_api_name, 'left_part', 'add left part of res');
2389
2390 -- add left part of the restrictions
2391 IF l_parameter_type_code = 1 THEN -- parameter is table.column
2392 g_rule_where := g_rule_where
2393 || l_logical_operator
2394 || l_bracket_open
2395 || ' '
2396 || l_left_part_conv_fct
2397 || l_table_alias
2398 || '.'
2399 || l_column_name
2400 || l_right_part_conv_fct
2401 || ' '
2402 || l_operator
2403 || ' ';
2404 ELSIF l_parameter_type_code = 2 THEN -- parameter is an expression
2405 g_rule_where := g_rule_where
2406 || l_logical_operator
2407 || l_bracket_open
2408 || ' '
2409 || l_left_part_conv_fct
2410 || l_expression
2411 || l_right_part_conv_fct
2412 || ' '
2413 || l_operator
2414 || ' ';
2415 ELSE
2416 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2417 fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2418 fnd_message.set_token('PARAMETER_TYPE_CODE', l_parameter_type_code);
2419 log_error_msg(l_api_name, 'bad_param_type_code_left_rest');
2420 fnd_msg_pub.ADD;
2421 END IF;
2422
2423 RAISE fnd_api.g_exc_error;
2424 END IF;
2425
2426 --
2427 log_statement(l_api_name, 'right_part', 'add right part of res');
2428
2429 -- add right part of the restrictions
2430
2431 IF l_operand_type_code = 1 THEN -- right side = const. number
2432 g_rule_where := g_rule_where || l_operand_constant_number || l_operand_expression || l_bracket_close || g_line_feed;
2433 ELSIF l_operand_type_code = 2 THEN -- right side = const. character
2434 --need to insert escape character of any apostrophes already in
2435 -- character field
2436
2437 --first case - string of length one
2438 IF LENGTH(l_operand_constant_character) = 1 THEN
2439 --if the one character is an apostrophe, provide escape
2440 -- character, then add single quotes
2441 IF l_operand_constant_character = '''' THEN
2442 l_new_constant_character := '''''';
2443 END IF;
2444
2445 l_new_constant_character := '''' || l_operand_constant_character || '''';
2446 -- second case - length > 2 - treat any single quote which is not
2447 -- the first or last character as an apostrophe, and ecape the
2448 -- character
2449 ELSIF LENGTH(l_operand_constant_character) > 2 THEN
2450 -- get the string minus the first and last characters
2451 -- (we take care of first and last characters later)
2452 l_new_constant_character := SUBSTR(l_operand_constant_character, 2, LENGTH(l_operand_constant_character) - 2);
2453 -- replace all apostrophes with two apostrophes
2454 l_new_constant_character := REPLACE(l_new_constant_character, '''', '''''');
2455 -- recontstruct the original string
2456 l_new_constant_character :=
2457 SUBSTR(l_operand_constant_character, 1, 1)
2458 || l_new_constant_character
2459 || SUBSTR( l_operand_constant_character , -1 , 1 );
2460 -- third case - Length 2 - treat any single quote like a single
2461 -- quote. we deal with quotes at the beginning and end of the string
2462 -- below.
2463 ELSE
2464 l_new_constant_character := l_operand_constant_character;
2465 END IF;
2466
2467 IF LENGTH(l_new_constant_character) > 1 THEN
2468 --check to see if string already has single quotes around it
2469 --if not, add the quotes.
2470 --this process checks both sides. if there is an initial quote but not
2471 -- a trailing quote, only the trailing quote is added.
2472 IF (SUBSTR(l_new_constant_character, 1, 1) <> '''') THEN
2473 l_new_constant_character := '''' || l_new_constant_character;
2474 END IF;
2475
2476 IF (SUBSTR(l_new_constant_character, -1, 1) <> '''') THEN
2477 l_new_constant_character := l_new_constant_character || '''';
2478 END IF;
2479 END IF;
2480
2481 g_rule_where := g_rule_where || l_new_constant_character || l_bracket_close || g_line_feed;
2482 ELSIF l_operand_type_code = 3 THEN -- right side = const. date
2483 --l_identifier := inv_sql_binding_pvt.InitBindVar(l_operand_constant_date);
2484 --Bug #2611142 - Add quotes before and after l_operand_constant_date
2485 g_rule_where := g_rule_where
2486 || ''''
2487 || l_operand_constant_date
2488 || ''''
2489 || ' '
2490 || l_operand_expression
2491 || l_bracket_close
2492 || g_line_feed;
2493 ELSIF l_operand_type_code = 4 THEN -- right side = parameter
2494 IF l_parent_parameter_type_code = 1 THEN -- table.column
2495 g_rule_where :=
2496 g_rule_where || l_parent_table_alias
2497 || '.'
2498 || l_parent_column_name
2499 || l_operand_expression
2500 || l_bracket_close
2501 || g_line_feed;
2502 ELSIF l_parent_parameter_type_code = 2 THEN -- expression
2503 g_rule_where := g_rule_where
2504 || l_parent_expression
2505 || l_operand_expression
2506 || l_bracket_close
2507 || g_line_feed;
2508 ELSE
2509 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2510 fnd_message.set_name('WMS', 'WMS_BAD_PARENT_PARA_TYPE');
2511 fnd_message.set_token('PARENT_PARAMETER_TYPE_CODE', l_parent_parameter_type_code);
2512 log_error_msg(l_api_name, 'bad_parent_param_type_right_rest');
2513 fnd_msg_pub.ADD;
2514 END IF;
2515
2516 RAISE fnd_api.g_exc_error;
2517 END IF;
2518 ELSIF l_operand_type_code = 5 THEN -- right side = expression
2519 --changed by jcearley on 12/8/99 - automatically put expression
2520 -- in parentheses - prevents syntax error during rule generation
2521 g_rule_where := g_rule_where
2522 || '(' || l_operand_expression || ')'
2523 || l_bracket_close
2524 || g_line_feed;
2525 ELSIF l_operand_type_code = 6 THEN -- right side = flex value set
2526 IF l_validation_type = 'F' THEN -- > validation type 'table'
2527 IF (l_id_column_name IS NULL) THEN
2528 l_flex_column_name := l_value_column_name;
2529 ELSE
2530 l_flex_column_name := l_id_column_name;
2531 END IF;
2532
2533 g_rule_where := g_rule_where
2534 || '( select '
2535 || l_flex_column_name
2536 || ' from '
2537 || l_application_table_name
2538 || ' '
2539 || l_additional_where_clause
2540 || ')'
2541 || l_bracket_close
2542 || g_line_feed;
2543 ELSIF l_validation_type = 'I' THEN -- > validation type 'independent'
2544 --l_identifier := inv_sql_binding_pvt.initbindvar
2545 -- (l_operand_flex_value_set_id);
2546 g_rule_where := g_rule_where
2547 || '( select FLEX_VALUE from '
2548 || 'FND_FLEX_VALUES_VL where FLEX_VALUE_SET_ID = '
2549 || l_operand_flex_value_set_id
2550 || ' and ENABLED_FLAG = ''Y'' and sysdate between nvl('
2551 || 'START_DATE_ACTIVE,sysdate-1) and nvl('
2552 || 'END_DATE_ACTIVE,sysdate+1) )'
2553 || l_bracket_close
2554 || g_line_feed;
2555 ELSE
2556 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2557 fnd_message.set_name('WMS', 'WMS_BAD_REF_FLEXVSET_DATA');
2558 fnd_message.set_token('DATATYPE', l_validation_type);
2559 log_error_msg(l_api_name, 'bad_ref_flexvset_data');
2560 fnd_msg_pub.ADD;
2561 END IF;
2562
2563 RAISE fnd_api.g_exc_error;
2564 END IF;
2565 ELSIF l_operand_type_code = 7 THEN -- right side = nothing
2566 g_rule_where := g_rule_where || l_bracket_close || g_line_feed;
2567 ELSE
2568 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2569 fnd_message.set_name('WMS', 'WMS_BAD_OPERAND_TYPE_CODE');
2570 fnd_message.set_token('OPERAND_TYPE_CODE', l_operand_type_code);
2571 fnd_msg_pub.ADD;
2572 END IF;
2573
2574 RAISE fnd_api.g_exc_error;
2575 END IF;
2576 END LOOP;
2577
2578 CLOSE RESTRICT;
2579 --
2580 log_statement(l_api_name, 'end_restrictions', 'end restrictions loop');
2581
2582 -- Insert bracket after adding the additional restriction clauses
2583 IF l_restriction_exist = TRUE THEN
2584 g_rule_where := g_rule_where || ')' || g_line_feed;
2585 END IF;
2586
2587 --
2588
2589 l_order_by_string := NULL;
2590 log_statement(l_api_name, 'alloc_mode', 'alloc_mode: ' || p_allocation_mode_id);
2591 log_statement(l_api_name, 'start_sort_crit', 'start sort crit loop');
2592 -- Add sort criteria
2593 OPEN sortcrit;
2594
2595 --
2596 -- Loop through all sort criteria, adding them to Order By clause
2597 WHILE TRUE LOOP
2598 FETCH sortcrit INTO l_parameter_type_code
2599 , l_column_name
2600 , l_expression
2601 , l_data_type_code
2602 , l_table_alias
2603 , l_parent_data_type_code
2604 , l_asc_desc
2605 , l_rule_id
2606 , l_sequence_number;
2607 EXIT WHEN sortcrit%NOTFOUND;
2608 --
2609 log_statement(l_api_name, 'seq_number_sort', 'seq_number sort:' || l_sequence_number);
2610 -- find out, if data type conversion is needed
2611 inv_sql_binding_pvt.getconversionstring(l_parent_data_type_code
2612 , l_data_type_code
2613 , l_left_part_conv_fct
2614 , l_right_part_conv_fct);
2615
2616 -- initialize order by clause
2617 IF g_rule_order IS NOT NULL THEN
2618 g_rule_order := g_rule_order || ',';
2619 END IF;
2620
2621 --
2622 -- add sort criterion to order by clause
2623 IF l_parameter_type_code = 1 THEN -- table.column
2624 g_rule_order := g_rule_order
2625 || l_left_part_conv_fct
2626 || l_table_alias
2627 || '.'
2628 || l_column_name
2629 || l_right_part_conv_fct
2630 || ' '
2631 || l_asc_desc
2632 || g_line_feed;
2633
2634 --added support for Picking by UOM
2635 --build the order_by_string for the select stmt;
2636 --this string is a concatenation of all the columns in the
2637 -- order by clause.
2638 -- order by string only matters for picking - set to NULL
2639 -- if not picking
2640 -- Needed in Apply procedure.
2641 IF (p_type_code = 2) THEN --pick
2642 IF (l_order_by_string IS NULL) THEN
2643 l_order_by_string := l_left_part_conv_fct
2644 || l_table_alias || '.' || l_column_name
2645 || l_right_part_conv_fct;
2646 ELSE
2647 -- need to hard code in '||' so string is concatenated at
2648 -- run time
2649 l_order_by_string :=
2650 l_order_by_string
2651 || '||'
2652 || l_left_part_conv_fct
2653 || l_table_alias || '.' || l_column_name
2654 || l_right_part_conv_fct;
2655 END IF;
2656
2657 -- include sort criteria in the group by clause, so that
2658 -- we can preserve the sort order. Used only when
2659 -- detailing serial controlled items but not detailing serial
2660 -- numbers.
2661 g_rule_group_by := g_rule_group_by || ',' || l_table_alias || '.' || l_column_name;
2662 END IF;
2663 ELSIF l_parameter_type_code = 2 THEN -- expression
2664 g_rule_order := g_rule_order
2665 || l_left_part_conv_fct
2666 || l_expression
2667 || l_right_part_conv_fct
2668 || ' '
2669 || l_asc_desc
2670 || g_line_feed;
2671
2672 --build the order_by_string for the select stmt
2673 IF (p_type_code = 2) THEN --pick
2674 IF (l_order_by_string IS NULL) THEN
2675 l_order_by_string := l_left_part_conv_fct || l_expression || l_right_part_conv_fct;
2676 ELSE
2677 l_order_by_string := l_order_by_string
2678 || '||'
2679 || l_left_part_conv_fct
2680 || l_expression
2681 || l_right_part_conv_fct;
2682 END IF;
2683
2684 g_rule_group_by := g_rule_group_by || ',' || l_expression;
2685 END IF;
2686 ELSE
2687 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2688 fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2689 fnd_message.set_token('OPERAND_TYPE_CODE', l_parameter_type_code);
2690 log_error_msg(l_api_name, 'bad_param_type_code_sort');
2691 fnd_msg_pub.ADD;
2692 END IF;
2693
2694 RAISE fnd_api.g_exc_error;
2695 END IF;
2696 END LOOP;
2697
2698 CLOSE sortcrit;
2699 log_statement(l_api_name, 'end_sort_crit', 'end sort crit loop');
2700
2701 --Pick UOM and Rule Consistencies are supported only for picking rules
2702 IF (p_type_code = 2) THEN
2703 l_consist_string := NULL;
2704 --Get consistencies from cursor;
2705 -- These consistencies are concatenated together to form one
2706 -- string. This string is added to the select and order by for the
2707 -- rule sql, and are used in the Apply function.
2708 OPEN consistencies;
2709
2710 LOOP
2711 FETCH consistencies INTO l_parameter_type_code, l_column_name, l_expression, l_table_alias;
2712 EXIT WHEN consistencies%NOTFOUND;
2713
2714 -- if parameter is a db column
2715 IF l_parameter_type_code = 1 THEN
2716 IF l_consist_string IS NULL THEN
2717 l_consist_string := l_table_alias || '.' || l_column_name;
2718 ELSE
2719 --parameter is expression
2720 l_consist_string := l_consist_string
2721 || '||'
2722 || l_table_alias || '.' || l_column_name;
2723 END IF;
2724
2725 -- include consistencies in the group by clause, so that
2726 -- we can preserve them. Used only when
2727 -- detailing serial controlled items but not detailing serial
2728 -- numbers.
2729 g_rule_group_by := g_rule_group_by
2730 || ','
2731 || l_table_alias || '.' || l_column_name
2732 || g_line_feed;
2733 -- if parameter is an expression
2734 ELSIF l_parameter_type_code = 2 THEN
2735 IF l_consist_string IS NULL THEN
2736 l_consist_string := l_expression;
2737 ELSE
2738 l_consist_string := l_consist_string || '||' || l_expression;
2739 END IF;
2740
2741 g_rule_group_by := g_rule_group_by || ',' || l_expression || g_line_feed;
2742 ELSE
2743 fnd_message.set_name('WMS', 'WMS_BAD_PARAMETER_TYPE_CODE');
2744 fnd_message.set_token('OPERAND_TYPE_CODE', l_parameter_type_code);
2745 log_error_msg(l_api_name, 'bad_param_type_code_consist');
2746 fnd_msg_pub.ADD;
2747 RAISE fnd_api.g_exc_error;
2748 END IF;
2749 END LOOP;
2750
2751 --add consist_string to the select clause
2752 -- Used in Apply procedure
2753 IF l_consist_string IS NOT NULL THEN
2754 IF g_rule_order IS NULL THEN
2755 g_rule_order := l_consist_string || g_line_feed;
2756 ELSE
2757 g_rule_order := g_rule_order || ',' || l_consist_string || g_line_feed;
2758 END IF;
2759
2760 /* No longer added consist_string to order_by_string
2761 IF l_order_by_string IS NULL THEN
2762 l_order_by_string := l_consist_string;
2763 ELSE
2764 l_order_by_string:=l_order_by_string || '||' || l_consist_string;
2765 END IF;
2766 */
2767 g_rule_select := g_rule_select
2768 || ','
2769 || l_consist_string
2770 || ' consist_string'
2771 || g_line_feed;
2772 g_rule_select_serial := g_rule_select_serial
2773 || ','
2774 || l_consist_string
2775 || ' consist_string'
2776 || g_line_feed;
2777 g_rule_group_by := g_rule_group_by
2778 || ','
2779 || l_consist_string
2780 || g_line_feed;
2781 -- if no consistencies, don't add anything to order by
2782 ELSE
2783 g_rule_select := g_rule_select || ',NULL consist_string' || g_line_feed;
2784 g_rule_select_serial := g_rule_select_serial || ',NULL consist_string' || g_line_feed;
2785 END IF;
2786
2787 --Add conversion_rate to sort criteria
2788 --if efficient pick flag is set, add conversion rate to front of order by;
2789 --otherwise, add to end of order by
2790 -- Bug#6802143: Serial Number is added in the order by and group by clause for Picking.
2791 IF (g_rule_order IS NULL) THEN
2792 -- conversion rate is only order by
2793 g_rule_order := g_rule_order
2794 || g_base_table_alias
2795 || '.SERIAL_NUMBER asc'
2796 || ','
2797 || g_base_table_alias
2798 || '.CONVERSION_RATE desc'
2799 || g_line_feed;
2800 ELSIF (p_allocation_mode_id IN (g_alloc_pick_uom, g_alloc_strict_pick_uom)) THEN
2801 g_rule_order := g_base_table_alias
2802 || '.CONVERSION_RATE desc'
2803 || g_line_feed
2804 || ','
2805 || g_base_table_alias
2806 || '.SERIAL_NUMBER asc'
2807 || ','
2808 || g_rule_order;
2809 ELSE
2810 g_rule_order := g_rule_order
2811 || ','
2812 || g_base_table_alias
2813 || '.SERIAL_NUMBER asc'
2814 || ','
2815 || g_base_table_alias
2816 || '.CONVERSION_RATE desc'
2817 || g_line_feed;
2818 END IF;
2819
2820 g_rule_group_by := g_rule_group_by
2821 || ','
2822 || g_base_table_alias
2823 || '.SERIAL_NUMBER'
2824 || ','
2825 || g_base_table_alias
2826 || '.CONVERSION_RATE'
2827 || g_line_feed;
2828
2829 -- Add the order_by_string to the select and group by clauses.
2830 -- This string is used in the Apply procedure.
2831 IF (l_order_by_string IS NOT NULL) THEN
2832 g_rule_select := g_rule_select
2833 || ','
2834 || l_order_by_string
2835 || ' order_by_string'
2836 || g_line_feed;
2837 g_rule_select_serial := g_rule_select_serial
2838 || ','
2839 || l_order_by_string
2840 || ' order_by_string'
2841 || g_line_feed;
2842 g_rule_group_by := g_rule_group_by || ',' || l_order_by_string || g_line_feed;
2843 ELSE
2844 g_rule_select := g_rule_select || ',NULL order_by_string' || g_line_feed;
2845 g_rule_select_serial := g_rule_select_serial || ',NULL order_by_string' || g_line_feed;
2846 END IF;
2847 ELSE --order by and consist string only useful in picking
2848 --3/13/02 added for PJM support
2849 -- Add project and task to sort criteria
2850 IF p_type_code = 1 THEN
2851 IF (g_rule_order IS NULL) THEN
2852 -- project and task are only order by
2853 g_rule_order :=
2854 g_rule_order || g_base_table_alias
2855 || '.PROJECT_ID' || g_line_feed
2856 || ',' || g_base_table_alias
2857 || '.TASK_ID' || g_line_feed;
2858 ELSE
2859 --bug 2983185 - g_rule_order was getting concatenated twice
2860 g_rule_order := g_rule_order
2861 || ','
2862 || g_base_table_alias
2863 || '.PROJECT_ID'
2864 || g_line_feed
2865 || ','
2866 || g_base_table_alias
2867 || '.TASK_ID'
2868 || g_line_feed;
2869 END IF;
2870 END IF;
2871
2872 g_rule_select := g_rule_select || ',NULL consist_string' || g_line_feed;
2873 g_rule_select_serial := g_rule_select_serial || ',NULL consist_string' || g_line_feed;
2874 g_rule_select := g_rule_select || ',NULL order_by_string' || g_line_feed;
2875 g_rule_select_serial := g_rule_select_serial || ',NULL order_by_string' || g_line_feed;
2876 END IF;
2877
2878 --
2879 -- Save the pointers, which mark the end of the rule sourced bind variables
2880 --inv_sql_binding_pvt.SaveBindPointers;
2881 --
2882 log_procedure(l_api_name, 'end', 'End BuildRuleSql');
2883 -- end of debugging section
2884 EXCEPTION
2885 WHEN fnd_api.g_exc_error THEN
2886 x_return_status := fnd_api.g_ret_sts_error;
2887 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
2888 --
2889 log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
2890 --
2891 WHEN fnd_api.g_exc_unexpected_error THEN
2892 x_return_status := fnd_api.g_ret_sts_unexp_error;
2893 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
2894 --
2895 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
2896
2897 WHEN OTHERS THEN
2898 IF objects%ISOPEN THEN
2899 CLOSE objects;
2900 END IF;
2901
2902 IF conditions%ISOPEN THEN
2903 CLOSE conditions;
2904 END IF;
2905
2906 IF qtyfnct%ISOPEN THEN
2907 CLOSE qtyfnct;
2908 END IF;
2909
2910 IF RESTRICT%ISOPEN THEN
2911 CLOSE RESTRICT;
2912 END IF;
2913
2914 IF sortcrit%ISOPEN THEN
2915 CLOSE sortcrit;
2916 END IF;
2917
2918 x_return_status := fnd_api.g_ret_sts_unexp_error;
2919
2920 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
2921 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
2922 END IF;
2923
2924 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
2925 --
2926 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
2927 --
2928 END buildrulesql;
2929
2930 --
2931 -- Name : BuildInputSQL
2932 -- Function : Adds the SQL to the where clause to handle
2933 -- input parameters
2934 -- Notes : privat procedure for internal use only
2935 --
2936 PROCEDURE buildinputsql(
2937 x_return_status OUT NOCOPY VARCHAR2
2938 , x_msg_count OUT NOCOPY NUMBER
2939 , x_msg_data OUT NOCOPY VARCHAR2
2940 , p_type_code IN NUMBER
2941 ) IS
2942 -- variables needed for dynamic SQL
2943 l_identifier VARCHAR2(10);
2944 l_api_name VARCHAR2(30) := 'BuildIputSQL';
2945 l_is_mat_status_used NUMBER := NVL(FND_PROFILE.VALUE('INV_MATERIAL_STATUS'), 2);
2946 BEGIN
2947 -- Initialize API return status to success
2948 x_return_status := fnd_api.g_ret_sts_success;
2949
2950 log_procedure(l_api_name, 'start', 'Start BuildInputSql');
2951 -- end of debugging section
2952 --
2953 --
2954 -- Add type code independent input parameters to where clause
2955 -- Notes: For picking, the sql statement already bound organization_id
2956 -- and inventory_item_id in BuildBaseSQL, so here it is redundant but
2957 -- no harm anyway
2958 g_input_where := g_base_table_alias || '.ORGANIZATION_ID = ' || 'g_organization_id' || g_line_feed;
2959 g_input_where := g_input_where || 'and ' || g_base_table_alias || '.INVENTORY_ITEM_ID = ' || 'g_inventory_item_id' || g_line_feed;
2960
2961 -- the move order line can specify the subinventory, locator, revision,
2962 -- and/or lot number to use for the pick or put away. To allow for a
2963 -- generic sql cursor regardless of input values, we use the decode statments
2964 -- in the where clause.
2965 -- When Rule.Apply is called, it will look at these four input values. For
2966 -- all the input values which are Null, the Apply function will set those
2967 -- values to -9999 (or -99 for Revision). Then inside the cursor in the
2968 -- stored rule function, these decode statements make a check on the value
2969 -- of the inputs. If the inputs = -9999 or -99 (i.e. Null), the decode
2970 -- statements create a line which always evaluate to true: a=a or 1=1.
2971 -- If the input has a non -9999 value, then that value is compared to the
2972 -- appropriate column.
2973
2974 -- 2/21/02 - We no longer add subinventory code and locator id to the
2975 -- where clause here. for putaway.
2976 --The decode statements prevent the subinventory/locator indices from
2977 -- being used. Instead, we add subinventory and locator to the where clause
2978 -- in GenerateRulePackage for cursors that are called only when those
2979 -- values are passed.
2980 IF (p_type_code = 2) THEN --picking only
2981 g_input_where := g_input_where
2982 || ' and '
2983 || 'decode(g_subinventory_code, ''-9999'', ''a'', '
2984 || g_base_table_alias
2985 || '.SUBINVENTORY_CODE)'
2986 || ' = '
2987 || 'decode(g_subinventory_code, ''-9999'', ''a'', g_subinventory_code)'
2988 || g_line_feed;
2989 --bug #1252345
2990 --if subinventory is null, we have to make sure we don't pick from
2991 -- non-reservable sub
2992 -- # 6917190
2993 -- 7280339 added check for status_id is null
2994 g_input_where := g_input_where
2995 || ' and '
2996 || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
2997 || ' AND exists(select 1 from mtl_material_statuses where status_id = '
2998 || g_base_table_alias
2999 || '.STATUS_ID'
3000 || ' AND RESERVABLE_TYPE = 1)) OR '
3001 || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3002 || ' or '
3003 || g_base_table_alias
3004 || '.STATUS_ID IS NULL)'
3005 || ' and '
3006 || 'decode(g_subinventory_code, ''-9999'', '
3007 || g_base_table_alias
3008 || '.RESERVABLE_TYPE, 1)'
3009 || ' = 1))'
3010 || g_line_feed;
3011 g_input_where := g_input_where
3012 || ' and '
3013 || 'decode(g_locator_id, -9999, 1, '
3014 || g_base_table_alias
3015 || '.locator_id)'
3016 || ' = '
3017 || 'decode(g_locator_id,-9999, 1, g_locator_id)'
3018 || g_line_feed;
3019 -- Bug 6719290, 6917190
3020 IF l_is_mat_status_used = 1 THEN
3021 g_input_where := g_input_where
3022 || ' and '
3023 || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
3024 || ' AND exists(select 1 from mtl_material_statuses where status_id = '
3025 || g_base_table_alias
3026 || '.STATUS_ID'
3027 || ' AND RESERVABLE_TYPE = 1)) OR '
3028 || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3029 || 'or '
3030 || g_base_table_alias
3031 || '.STATUS_ID IS NULL)'
3032 || ' and '
3033 || 'decode(g_locator_id, -9999, '
3034 || g_base_table_alias
3035 || '.locreservable, 1)'
3036 || ' = 1))'
3037 || g_line_feed;
3038 END IF ;
3039
3040 END IF;
3041
3042 IF (p_type_code = 2) THEN
3043 g_input_where := g_input_where
3044 || ' and '
3045 || 'decode(g_revision, ''-99'', ''a'', '
3046 || g_base_table_alias
3047 || '.REVISION)'
3048 || ' = '
3049 || 'decode(g_revision, ''-99'', ''a'', g_revision)'
3050 || g_line_feed;
3051 g_input_where := g_input_where
3052 || ' and '
3053 || 'decode(g_lot_number, ''-9999'', ''a'', '
3054 || g_base_table_alias
3055 || '.LOT_NUMBER)'
3056 || ' = '
3057 || 'decode(g_lot_number, ''-9999'', ''a'', g_lot_number)'
3058 || g_line_feed;
3059 -- Bug 6719290, 6917190
3060 IF l_is_mat_status_used = 1 THEN
3061 g_input_where := g_input_where
3062 || ' and '
3063 || ' ((exists (select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not null ) '
3064 || ' AND exists(select 1 from mtl_material_statuses where status_id = '
3065 || g_base_table_alias
3066 || '.STATUS_ID'
3067 || ' AND RESERVABLE_TYPE = 1)) OR '
3068 || '((NOT exists(select 1 from mtl_parameters where organization_id = g_organization_id and default_status_id is not NULL) '
3069 || 'or '
3070 || g_base_table_alias
3071 || '.STATUS_ID IS NULL)'
3072 || ' and '
3073 || 'decode(g_lot_number, ''-9999'', '
3074 || g_base_table_alias
3075 || '.lotreservable, 1)'
3076 || ' = 1))'
3077 || g_line_feed;
3078 END IF ;
3079
3080 g_input_where := g_input_where
3081 || ' and '
3082 || 'decode(g_lpn_id, -9999, 1, '
3083 || g_base_table_alias
3084 || '.lpn_id)'
3085 || ' = '
3086 || 'decode(g_lpn_id, -9999, 1, g_lpn_id)'
3087 || g_line_feed;
3088 --cost group doesn't affect finding put away locations,
3089 -- so only check input for pick
3090 g_input_where := g_input_where
3091 || ' and '
3092 || 'decode(g_cost_group_id, -9999, 1, '
3093 || g_base_table_alias
3094 || '.cost_group_id)'
3095 || ' = '
3096 || 'decode(g_cost_group_id, -9999, 1, g_cost_group_id)'
3097 || g_line_feed;
3098 -- Adding project_id and task_id to support PJM
3099 g_input_where := g_input_where
3100 || ' and '
3101 || '(decode(g_project_id, -9999, -1, '
3102 || g_base_table_alias
3103 || '.project_id)'
3104 || ' = '
3105 || 'decode(g_project_id, -9999, -1, g_project_id)'
3106 || ' OR '
3107 || '( g_project_id = -7777 '
3108 || ' and '
3109 || g_base_table_alias
3110 || '.project_id IS NULL)) '
3111 || g_line_feed;
3112 -- If Allow Cross Project Pick is set to NO then task must be exactly equal even if NULL
3113 g_input_where := g_input_where
3114 || ' and '
3115 || '(g_project_id = -9999'
3116 || ' OR '
3117 || 'nvl('
3118 || g_base_table_alias
3119 || '.task_id, -9999)'
3120 || ' = '
3121 || 'g_task_id'
3122 || ' OR '
3123 || '(g_task_id = -7777'
3124 || ' and '
3125 || g_base_table_alias
3126 || '.task_id IS NULL))'
3127 || g_line_feed;
3128 END IF;
3129
3130 IF (p_type_code = 1) THEN
3131 -- Adding project_id and task_id to support PJM
3132 g_input_where := g_input_where
3133 || ' and ('
3134 || 'g_project_id = '
3135 || g_base_table_alias
3136 || '.project_id OR '
3137 || g_base_table_alias
3138 || '.project_id IS NULL)'
3139 || g_line_feed;
3140 g_input_where := g_input_where
3141 || ' and ('
3142 || 'g_task_id = '
3143 || g_base_table_alias
3144 || '.task_id OR '
3145 || g_base_table_alias
3146 || '.task_id IS NULL)'
3147 || g_line_feed;
3148 END IF;
3149
3150 -- always join to the input table
3151 g_input_where :=
3152 g_input_where || ' and ' || g_input_table_alias || '.PP_TRANSACTION_TEMP_ID = ' || 'g_pp_transaction_temp_id' || g_line_feed;
3153
3154 -- end of debugging section
3155 log_procedure(l_api_name, 'end', 'End BuildInputSql');
3156 --
3157 EXCEPTION
3158 WHEN OTHERS THEN
3159 x_return_status := fnd_api.g_ret_sts_unexp_error;
3160
3161 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3162 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3163 END IF;
3164
3165 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3166 --
3167 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3168 --
3169 END buildinputsql;
3170
3171 FUNCTION isruledebugon(p_simulation_mode IN NUMBER)
3172 RETURN BOOLEAN IS
3173 l_return_value BOOLEAN;
3174 l_debug NUMBER;
3175 BEGIN
3176 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3177 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3178 END IF;
3179 l_debug := g_debug;
3180 IF p_simulation_mode <> wms_engine_pvt.g_no_simulation THEN
3181 l_return_value := TRUE;
3182 ELSIF p_simulation_mode = wms_engine_pvt.g_no_simulation THEN
3183 if l_debug = 1 THEN
3184 l_return_value := TRUE;
3185 ELSE
3186 l_return_value := FALSE;
3187 END IF;
3188 ELSE
3189 null;
3190 --l_return_value := fnd_log.test(log_level => fnd_log.level_unexpected, module => 'wms.plsql.' || g_pkg_name || '.' || 'Apply.test');
3191 END IF;
3192
3193 IF l_return_value THEN
3194 if l_debug = 1 THEN
3195 log_statement('IsRuleDebugOn', 'true', 'Debug is on');
3196 END IF;
3197 ELSE
3198 IF l_debug = 1 THEN
3199 log_statement('IsRuleDebugOn', 'false', 'Debug is off');
3200 END IF;
3201 END IF;
3202
3203 RETURN l_return_value;
3204 END isruledebugon;
3205
3206 --
3207 -- Name : FetchCursor
3208 -- Function : Fetches one record at a time from the Rule's
3209 -- SQL statement, using the rule API
3210 -- Pre-reqs : cursor has to be parsed and executed already.
3211 -- Notes : private procedure for internal use only
3212 --
3213 PROCEDURE fetchcursor(
3214 x_return_status OUT NOCOPY VARCHAR2
3215 , x_msg_count OUT NOCOPY NUMBER
3216 , x_msg_data OUT NOCOPY VARCHAR2
3217 , p_cursor IN wms_rule_pvt.cv_pick_type
3218 , p_rule_id IN NUMBER
3219 , x_revision OUT NOCOPY VARCHAR2
3220 , x_lot_number OUT NOCOPY VARCHAR2
3221 , x_lot_expiration_date OUT NOCOPY DATE
3222 , x_subinventory_code OUT NOCOPY VARCHAR2
3223 , x_locator_id OUT NOCOPY NUMBER
3224 , x_cost_group_id OUT NOCOPY NUMBER
3225 , x_uom_code OUT NOCOPY VARCHAR2
3226 , x_lpn_id OUT NOCOPY NUMBER
3227 , x_serial_number OUT NOCOPY VARCHAR2
3228 , x_possible_quantity OUT NOCOPY NUMBER
3229 , x_sec_possible_quantity OUT NOCOPY NUMBER
3230 , x_grade_code OUT NOCOPY VARCHAR2
3231 , x_consist_string OUT NOCOPY VARCHAR2
3232 , x_order_by_string OUT NOCOPY VARCHAR2
3233 , x_rows OUT NOCOPY NUMBER
3234 ) IS
3235 invalid_pkg_state exception;
3236 Pragma Exception_Init(invalid_pkg_state, -6508);
3237
3238 l_list_pkg VARCHAR2(30);
3239
3240 l_api_name VARCHAR2(30) := 'FetchCursor';
3241 l_rows NUMBER;
3242 l_func_sql VARCHAR(1000);
3243 l_cursor NUMBER;
3244 l_dummy NUMBER;
3245 l_package_name VARCHAR2(128);
3246 l_ctr NUMBER := 0;
3247
3248 l_debug NUMBER;
3249
3250 BEGIN
3251 -- Initialize API return status to success
3252 x_return_status := fnd_api.g_ret_sts_success;
3253 --get package name based on rule id
3254 getpackagename(p_rule_id, l_package_name);
3255 --- calling the static fetch cursor. The name of the rule package will be
3256 --- determined based on the rule_id
3257 --- If the ctr is 1 then there is no subscript ,
3258 --- if ctr = 2 then subscript = 1
3259 --- and if ctr = 3 then subscript = 2, this script is added to the package
3260 --- name.
3261
3262
3263 l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
3264 l_list_pkg := 'wms_rule_pick_pkg' || l_ctr ;
3265
3266 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3267 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3268 END IF;
3269 l_debug := g_debug;
3270
3271 IF l_debug = 1 THEN
3272 log_procedure(l_api_name, 'start', 'Start FetchCursor');
3273 END IF;
3274
3275 IF (l_ctr = 1) THEN
3276
3277 wms_rule_pick_pkg1.execute_fetch_rule(
3278 p_cursor
3279 , p_rule_id
3280 , x_revision
3281 , x_lot_number
3282 , x_lot_expiration_date
3283 , x_subinventory_code
3284 , x_locator_id
3285 , x_cost_group_id
3286 , x_uom_code
3287 , x_lpn_id
3288 , x_serial_number
3289 , x_possible_quantity
3290 , x_sec_possible_quantity
3291 , x_grade_code
3292 , x_consist_string
3293 , x_order_by_string
3294 , x_rows
3295 );
3296 ELSIF (l_ctr = 2) THEN
3297
3298 wms_rule_pick_pkg2.execute_fetch_rule(
3299 p_cursor
3300 , p_rule_id
3301 , x_revision
3302 , x_lot_number
3303 , x_lot_expiration_date
3304 , x_subinventory_code
3305 , x_locator_id
3306 , x_cost_group_id
3307 , x_uom_code
3308 , x_lpn_id
3309 , x_serial_number
3310 , x_possible_quantity
3311 , x_sec_possible_quantity
3312 , x_grade_code
3313 , x_consist_string
3314 , x_order_by_string
3315 , x_rows
3316 );
3317 ELSIF (l_ctr = 3) THEN
3318 wms_rule_pick_pkg3.execute_fetch_rule(
3319 p_cursor
3320 , p_rule_id
3321 , x_revision
3322 , x_lot_number
3323 , x_lot_expiration_date
3324 , x_subinventory_code
3325 , x_locator_id
3326 , x_cost_group_id
3327 , x_uom_code
3328 , x_lpn_id
3329 , x_serial_number
3330 , x_possible_quantity
3331 , x_sec_possible_quantity
3332 , x_grade_code
3333 , x_consist_string
3334 , x_order_by_string
3335 , x_rows
3336 );
3337 END IF;
3338
3339 l_rows := x_rows;
3340
3341 IF l_rows = 0 THEN --no row found
3342 x_revision := NULL;
3343 x_lot_number := NULL;
3344 x_lot_expiration_date := NULL;
3345 x_subinventory_code := NULL;
3346 x_locator_id := NULL;
3347 x_cost_group_id := NULL;
3348 x_uom_code := NULL;
3349 x_lpn_id := NULL;
3350 x_serial_number := NULL;
3351 x_possible_quantity := 0;
3352 x_consist_string := NULL;
3353 x_order_by_string := NULL;
3354
3355
3356 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PICK_NO_ROWS' ;
3357
3358 IF l_debug = 1 THEN
3359 log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || p_rule_id);
3360 log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
3361 END IF;
3362
3363 END IF;
3364
3365 x_rows := l_rows;
3366 --
3367
3368 IF l_debug = 1 THEN
3369 log_procedure(l_api_name, 'end', 'End FetchCursor');
3370 END IF;
3371 --
3372 EXCEPTION
3373 WHEN INVALID_PKG_STATE THEN
3374 x_return_status := fnd_api.g_ret_sts_unexp_error;
3375
3376 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3377 fnd_message.set_token('LIST_PKG', l_list_pkg);
3378 fnd_message.set_token('RULE_NAME', l_package_name);
3379 fnd_msg_pub.ADD;
3380 IF l_debug = 1 THEN
3381 log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
3382 || l_list_pkg || ' / ' || l_package_name);
3383 END IF;
3384 RAISE fnd_api.g_exc_unexpected_error;
3385
3386 WHEN OTHERS THEN
3387 x_return_status := fnd_api.g_ret_sts_unexp_error;
3388
3389 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3390 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3391 END IF;
3392
3393 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3394 IF l_debug = 1 THEN
3395 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3396 END IF;
3397 RAISE fnd_api.g_exc_unexpected_error;
3398 END fetchcursor;
3399
3400 --
3401 -- Name : FetchPutAway
3402 -- Function : Fetches one record at a time from the Rule's
3403 -- SQL statement, using the rule API. Called from putaway
3404 -- Pre-reqs : cursor has to be parsed and executed already.
3405 -- Notes : private procedure for internal use only
3406 --
3407 PROCEDURE fetchputaway(
3408 x_return_status OUT NOCOPY VARCHAR2
3409 , x_msg_count OUT NOCOPY NUMBER
3410 , x_msg_data OUT NOCOPY VARCHAR2
3411 , p_cursor IN wms_rule_pvt.cv_put_type
3412 , p_rule_id IN NUMBER
3413 , x_subinventory_code OUT NOCOPY VARCHAR2
3414 , x_locator_id OUT NOCOPY NUMBER
3415 , x_project_id OUT NOCOPY NUMBER
3416 , x_task_id OUT NOCOPY NUMBER
3417 , x_rows OUT NOCOPY NUMBER
3418 ) IS
3419 invalid_pkg_state exception;
3420 Pragma Exception_Init(invalid_pkg_state, -6508);
3421
3422 l_list_pkg VARCHAR2(30);
3423
3424 l_api_name VARCHAR2(30) := 'FetchPutaway';
3425 l_rows NUMBER;
3426 l_func_sql VARCHAR(1000);
3427 l_cursor NUMBER;
3428 l_dummy NUMBER;
3429 l_package_name VARCHAR2(128);
3430 l_ctr NUMBER := 0;
3431
3432 l_debug NUMBER;
3433
3434
3435 BEGIN
3436 -- Initialize API return status to success
3437 x_return_status := fnd_api.g_ret_sts_success;
3438
3439 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3440 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3441 END IF;
3442 l_debug := g_debug;
3443
3444 IF l_debug = 1 THEN
3445 log_procedure(l_api_name, 'start', 'Start FetchPutaway');
3446 log_procedure(l_api_name, 'start', 'Putaway rule id '||p_rule_id);
3447 END IF;
3448
3449 --get package name based on rule id
3450 getpackagename(p_rule_id, l_package_name);
3451 l_ctr := wms_rule_pvt.g_rule_list_put_ctr;
3452 l_list_pkg := 'wms_rule_put_pkg' || l_ctr ;
3453
3454 IF (l_ctr = 1) THEN
3455 wms_rule_put_pkg1.execute_fetch_rule
3456 (p_cursor
3457 , p_rule_id
3458 , x_subinventory_code
3459 , x_locator_id
3460 , x_project_id
3461 , x_task_id
3462 , x_rows);
3463 ELSIF (l_ctr = 2) THEN
3464 wms_rule_put_pkg2.execute_fetch_rule
3465 (p_cursor
3466 , p_rule_id
3467 , x_subinventory_code
3468 , x_locator_id
3469 , x_project_id
3470 , x_task_id
3471 , x_rows);
3472 ELSIF (l_ctr = 3) THEN
3473 wms_rule_put_pkg3.execute_fetch_rule
3474 (p_cursor
3475 , p_rule_id
3476 , x_subinventory_code
3477 , x_locator_id
3478 , x_project_id
3479 , x_task_id
3480 , x_rows);
3481 END IF;
3482
3483 --------
3484 --l_rows := x_rows;
3485 IF l_debug = 1 THEN
3486 log_event(l_api_name, '*************************', '');
3487 log_event(l_api_name, 'x_subinventory_code', x_subinventory_code);
3488 log_event(l_api_name, 'x_locator_id', x_locator_id);
3489 END IF;
3490
3491
3492 IF l_rows = 0 THEN --no row found
3493 x_subinventory_code := NULL;
3494 x_locator_id := NULL;
3495 x_project_id := NULL;
3496 x_task_id := NULL;
3497
3498 -- Bug # 3185073
3499 --WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
3500
3501 IF l_debug = 1 THEN
3502 log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || p_rule_id);
3503 END IF;
3504
3505 IF ( WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE = 'WMS_PICK_NO_ROWS' or
3506 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE = NULL) then
3507
3508 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
3509 END IF;
3510
3511 IF l_debug = 1 THEN
3512 log_event(l_api_name, 'no_rows_found', 'No more rows for rule ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
3513 END IF;
3514
3515 END IF;
3516 --x_rows := l_rows;
3517 IF l_debug = 1 THEN
3518 log_statement(l_api_name, 'put_sub',
3519 'Subinventory: ' || x_subinventory_code);
3520 log_statement(l_api_name, 'put_loc',
3521 'Locator: ' || x_locator_id);
3522 log_statement(l_api_name, 'put_proj',
3523 'Project: ' || x_project_id);
3524 log_statement(l_api_name, 'put_task',
3525 'Task: ' || x_task_id);
3526 log_statement(l_api_name, 'rows',
3527 'Rows Returned: ' || x_rows);
3528 END IF;
3529
3530 IF l_debug = 1 THEN
3531 log_procedure(l_api_name, 'end', 'End FetchPutaway');
3532 END IF;
3533 --
3534 EXCEPTION
3535 WHEN INVALID_PKG_STATE THEN
3536 x_return_status := fnd_api.g_ret_sts_unexp_error;
3537 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3538 fnd_message.set_token('LIST_PKG', l_list_pkg);
3539 fnd_message.set_token('RULE_NAME', l_package_name);
3540 fnd_msg_pub.ADD;
3541
3542 IF l_debug = 1 THEN
3543 log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
3544 || l_list_pkg || ' / ' || l_package_name);
3545 END IF;
3546 RAISE fnd_api.g_exc_unexpected_error;
3547 WHEN OTHERS THEN
3548 x_return_status := fnd_api.g_ret_sts_unexp_error;
3549
3550 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
3551 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
3552 END IF;
3553
3554 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
3555 IF l_debug = 1 THEN
3556 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
3557 END IF;
3558 RAISE fnd_api.g_exc_unexpected_error;
3559 END fetchputaway;
3560
3561 ------------
3562 ---
3563 --- Procedures to handle the static calls to open, fetch and close cursor
3564 --- based on the Rule_id. The name of the API_call is decided based on the the
3565 --- flag retrived from the table.
3566 ---
3567 --- For Pick rules
3568
3569 PROCEDURE pick_open_rule(
3570 p_cursor IN OUT NOCOPY wms_rule_pvt.cv_pick_type
3571 , p_rule_id IN NUMBER
3572 , p_organization_id IN NUMBER
3573 , p_inventory_item_id IN NUMBER
3574 , p_transaction_type_id IN NUMBER
3575 , p_revision IN VARCHAR2
3576 , p_lot_number IN VARCHAR2
3577 , p_subinventory_code IN VARCHAR2
3578 , p_locator_id IN NUMBER
3579 , p_cost_group_id IN NUMBER
3580 , p_pp_transaction_temp_id IN NUMBER
3581 , p_serial_controlled IN NUMBER
3582 , p_detail_serial IN NUMBER
3583 , p_detail_any_serial IN NUMBER
3584 , p_from_serial_number IN VARCHAR2
3585 , p_to_serial_number IN VARCHAR2
3586 , p_unit_number IN VARCHAR2
3587 , p_lpn_id IN NUMBER
3588 , p_project_id IN NUMBER
3589 , p_task_id IN NUMBER
3590 , x_result OUT NOCOPY NUMBER
3591 ) IS
3592
3593 invalid_pkg_state exception;
3594 Pragma Exception_Init(invalid_pkg_state, -6508);
3595 l_msg_data VARCHAR2(240);
3596 l_msg_count NUMBER;
3597 l_api_name VARCHAR2(30);
3598
3599 l_list_pkg VARCHAR2(30);
3600 l_package_name VARCHAR2(128);
3601 l_ctr NUMBER := 0;
3602
3603 l_debug NUMBER;
3604
3605 BEGIN
3606
3607 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3608 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3609 END IF;
3610 l_debug := g_debug;
3611
3612 IF wms_rule_pvt.g_rule_list_pick_ctr IS NULL THEN
3613 wms_rule_pvt.g_rule_list_pick_ctr := wms_rule_gen_pkgs.get_count_no_lock('PICK');
3614 END IF;
3615 l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
3616
3617 l_list_pkg := 'wms_rule_pick_pkg' || l_ctr ;
3618 getpackagename(p_rule_id, l_package_name);
3619
3620 IF (l_ctr = 1) THEN
3621
3622 IF l_debug = 1 THEN
3623 log_statement(l_api_name, ' wms_rule_pick_pkg1.execute_open_rule', l_ctr);
3624 END IF;
3625 wms_rule_pick_pkg1.execute_open_rule(
3626 p_cursor
3627 , p_rule_id
3628 , p_organization_id
3629 , p_inventory_item_id
3630 , p_transaction_type_id
3631 , p_revision
3632 , p_lot_number
3633 , p_subinventory_code
3634 , p_locator_id
3635 , p_cost_group_id
3636 , p_pp_transaction_temp_id
3637 , p_serial_controlled
3638 , p_detail_serial
3639 , p_detail_any_serial
3640 , p_from_serial_number
3641 , p_to_serial_number
3642 , p_unit_number
3643 , p_lpn_id
3644 , p_project_id
3645 , p_task_id
3646 , x_result
3647 );
3648 ELSIF (l_ctr = 2) THEN
3649
3650 IF l_debug = 1 THEN
3651 log_statement(l_api_name, ' wms_rule_pick_pkg2.execute_open_rule', l_ctr);
3652 END IF;
3653
3654 wms_rule_pick_pkg2.execute_open_rule(
3655 p_cursor
3656 , p_rule_id
3657 , p_organization_id
3658 , p_inventory_item_id
3659 , p_transaction_type_id
3660 , p_revision
3661 , p_lot_number
3662 , p_subinventory_code
3663 , p_locator_id
3664 , p_cost_group_id
3665 , p_pp_transaction_temp_id
3666 , p_serial_controlled
3667 , p_detail_serial
3668 , p_detail_any_serial
3669 , p_from_serial_number
3670 , p_to_serial_number
3671 , p_unit_number
3672 , p_lpn_id
3673 , p_project_id
3674 , p_task_id
3675 , x_result
3676 );
3677 ELSIF (l_ctr = 3) THEN
3678 IF l_debug = 1 THEN
3679 log_statement(l_api_name, ' wms_rule_pick_pkg3.execute_open_rule', l_ctr);
3680 END IF;
3681
3682 wms_rule_pick_pkg3.execute_open_rule(
3683 p_cursor
3684 , p_rule_id
3685 , p_organization_id
3686 , p_inventory_item_id
3687 , p_transaction_type_id
3688 , p_revision
3689 , p_lot_number
3690 , p_subinventory_code
3691 , p_locator_id
3692 , p_cost_group_id
3693 , p_pp_transaction_temp_id
3694 , p_serial_controlled
3695 , p_detail_serial
3696 , p_detail_any_serial
3697 , p_from_serial_number
3698 , p_to_serial_number
3699 , p_unit_number
3700 , p_lpn_id
3701 , p_project_id
3702 , p_task_id
3703 , x_result
3704 );
3705 END IF;
3706
3707 EXCEPTION
3708 WHEN INVALID_PKG_STATE THEN
3709 x_result := 0;
3710 wms_rule_pvt.g_rule_list_pick_ctr := wms_rule_gen_pkgs.get_count_no_lock('PICK');
3711
3712 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3713 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3714 fnd_message.set_token('LIST_PKG', l_list_pkg);
3715 fnd_message.set_token('RULE_NAME', l_package_name);
3716 fnd_msg_pub.ADD;
3717
3718 IF l_debug = 1 THEN
3719 log_error(l_api_name, 'execute_open_rule', 'Invalid Package, Contact your DBA - '
3720 || l_list_pkg || ' / ' || l_package_name);
3721
3722 END IF;
3723 END pick_open_rule;
3724
3725 ---
3726 --- Procedure Fetchcursor() is modified to handle static call to fetch a row from the
3727 --- opened picking cursor
3728
3729 ----------------
3730
3731 PROCEDURE put_open_rule(
3732 p_cursor IN OUT NOCOPY wms_rule_pvt.cv_put_type
3733 , p_rule_id IN NUMBER
3734 , p_organization_id IN NUMBER
3735 , p_inventory_item_id IN NUMBER
3736 , p_transaction_type_id IN NUMBER
3737 , p_subinventory_code IN VARCHAR2
3738 , p_locator_id IN NUMBER
3739 , p_pp_transaction_temp_id IN NUMBER
3740 , p_restrict_subs_code IN NUMBER
3741 , p_restrict_locs_code IN NUMBER
3742 , p_project_id IN NUMBER
3743 , p_task_id IN NUMBER
3744 , x_result OUT NOCOPY NUMBER
3745 ) IS
3746
3747 invalid_pkg_state exception;
3748 Pragma Exception_Init(invalid_pkg_state, -6508);
3749 l_msg_data VARCHAR2(240);
3750 l_msg_count NUMBER;
3751 l_api_name VARCHAR2(30);
3752
3753 l_list_pkg VARCHAR2(30);
3754 l_package_name VARCHAR2(128);
3755 l_ctr NUMBER := 0;
3756
3757 l_debug NUMBER;
3758
3759 BEGIN
3760
3761 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
3762 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3763 END IF;
3764 l_debug := g_debug;
3765
3766 if wms_rule_pvt.g_rule_list_put_ctr is null then
3767 wms_rule_pvt.g_rule_list_put_ctr := wms_rule_gen_pkgs.get_count_no_lock('PUTAWAY');
3768 end if;
3769 l_ctr := wms_rule_pvt.g_rule_list_put_ctr;
3770
3771 l_list_pkg := 'wms_rule_put_pkg' || l_ctr ;
3772 getpackagename(p_rule_id, l_package_name);
3773
3774 IF (l_ctr = 1) THEN
3775 wms_rule_put_pkg1.execute_open_rule(
3776 p_cursor
3777 , p_rule_id
3778 , p_organization_id
3779 , p_inventory_item_id
3780 , p_transaction_type_id
3781 , p_subinventory_code
3782 , p_locator_id
3783 , p_pp_transaction_temp_id
3784 , p_restrict_subs_code
3785 , p_restrict_locs_code
3786 , p_project_id
3787 , p_task_id
3788 , x_result
3789 );
3790 ELSIF (l_ctr = 2) THEN
3791 wms_rule_put_pkg2.execute_open_rule(
3792 p_cursor
3793 , p_rule_id
3794 , p_organization_id
3795 , p_inventory_item_id
3796 , p_transaction_type_id
3797 , p_subinventory_code
3798 , p_locator_id
3799 , p_pp_transaction_temp_id
3800 , p_restrict_subs_code
3801 , p_restrict_locs_code
3802 , p_project_id
3803 , p_task_id
3804 , x_result
3805 );
3806 ELSIF (l_ctr = 3) THEN
3807 wms_rule_put_pkg3.execute_open_rule(
3808 p_cursor
3809 , p_rule_id
3810 , p_organization_id
3811 , p_inventory_item_id
3812 , p_transaction_type_id
3813 , p_subinventory_code
3814 , p_locator_id
3815 , p_pp_transaction_temp_id
3816 , p_restrict_subs_code
3817 , p_restrict_locs_code
3818 , p_project_id
3819 , p_task_id
3820 , x_result
3821 );
3822 END IF;
3823
3824 EXCEPTION
3825 WHEN INVALID_PKG_STATE THEN
3826 x_result := 0;
3827 wms_rule_pvt.g_rule_list_put_ctr := wms_rule_gen_pkgs.get_count_no_lock('PUTAWAY');
3828
3829 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3830 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3831 fnd_message.set_token('LIST_PKG', l_list_pkg);
3832 fnd_message.set_token('RULE_NAME', l_package_name);
3833 fnd_msg_pub.ADD;
3834
3835 IF l_debug = 1 THEN
3836 log_error(l_api_name, 'execute_open_rule', 'Invalid Package, Contact your DBA - '
3837 || l_list_pkg || ' / ' || l_package_name);
3838 END IF;
3839 END put_open_rule;
3840
3841 -----------------
3842 --- Procedure FetchPutaway() is modified to handle static call to fetch a row from the
3843 --- opened Putaway cursor
3844
3845 PROCEDURE execute_op_rule(p_rule_id IN NUMBER, p_task_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
3846
3847 invalid_pkg_state exception;
3848 Pragma Exception_Init(invalid_pkg_state, -6508);
3849 l_msg_data VARCHAR2(240);
3850 l_msg_count NUMBER;
3851 l_api_name VARCHAR2(30);
3852 l_list_pkg VARCHAR2(30);
3853 l_package_name VARCHAR2(128);
3854 l_ctr NUMBER := 0;
3855
3856 BEGIN
3857 if wms_rule_pvt.g_rule_list_op_ctr is null then
3858 wms_rule_pvt.g_rule_list_op_ctr := wms_rule_gen_pkgs.get_count_no_lock('OPERATION_PLAN');
3859 end if;
3860 l_ctr := wms_rule_pvt.g_rule_list_op_ctr;
3861
3862 l_list_pkg := 'wms_rule_op_pkg' || l_ctr ;
3863 getpackagename(p_rule_id, l_package_name);
3864
3865 IF (l_ctr = 1) THEN
3866 wms_rule_op_pkg1.execute_op_rule(p_rule_id, p_task_id, x_return_status);
3867 ELSIF (l_ctr = 2) THEN
3868 wms_rule_op_pkg2.execute_op_rule(p_rule_id, p_task_id, x_return_status);
3869 ELSIF (l_ctr = 3) THEN
3870 wms_rule_op_pkg3.execute_op_rule(p_rule_id, p_task_id, x_return_status);
3871 END IF;
3872 IF x_return_status IS NULL THEN
3873 x_return_status := 1;
3874 END IF;
3875 EXCEPTION
3876 WHEN INVALID_PKG_STATE THEN
3877 --x_return_status := 0;
3878 x_return_status := -1 ;
3879 wms_rule_pvt.g_rule_list_op_ctr := wms_rule_gen_pkgs.get_count_no_lock('OPERATION_PLAN');
3880 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3881 x_return_status := fnd_api.g_ret_sts_unexp_error;
3882 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3883 fnd_message.set_token('LIST_PKG', l_list_pkg);
3884 fnd_message.set_token('RULE_NAME', l_package_name);
3885 fnd_msg_pub.ADD;
3886 /*log_error(l_api_name, 'execute_op_rule', 'Invalid Package, Contact your DBA - '
3887 || l_list_pkg || ' / ' || l_package_name); */
3888 END execute_op_rule;
3889
3890 ----- Open cursor and fetch cursor for task rules
3891
3892 PROCEDURE execute_task_rule(p_rule_id IN NUMBER, p_task_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
3893
3894 invalid_pkg_state exception;
3895 Pragma Exception_Init(invalid_pkg_state, -6508);
3896 l_msg_data VARCHAR2(240);
3897 l_msg_count NUMBER;
3898 l_api_name VARCHAR2(30);
3899
3900 l_list_pkg VARCHAR2(30);
3901 l_package_name VARCHAR2(128);
3902
3903 l_ctr NUMBER := 0;
3904
3905
3906 BEGIN
3907 if wms_rule_pvt.g_rule_list_task_ctr is null then
3908 wms_rule_pvt.g_rule_list_task_ctr := wms_rule_gen_pkgs.get_count_no_lock('TASK');
3909 end if;
3910 l_ctr := wms_rule_pvt.g_rule_list_task_ctr;
3911
3912 l_list_pkg := 'wms_rule_task_pkg' || l_ctr ;
3913 getpackagename(p_rule_id, l_package_name);
3914
3915 IF (l_ctr = 1) THEN
3916 wms_rule_task_pkg1.execute_task_rule(p_rule_id, p_task_id, x_return_status);
3917 ELSIF (l_ctr = 2) THEN
3918 wms_rule_task_pkg2.execute_task_rule(p_rule_id, p_task_id, x_return_status);
3919 ELSIF (l_ctr = 3) THEN
3920 wms_rule_task_pkg3.execute_task_rule(p_rule_id, p_task_id, x_return_status);
3921 END IF;
3922 IF x_return_status IS NULL THEN
3923 x_return_status := 1;
3924 END IF;
3925 EXCEPTION
3926 WHEN INVALID_PKG_STATE THEN
3927 --x_return_status := 0;
3928 x_return_status := -1 ;
3929 wms_rule_pvt.g_rule_list_task_ctr := wms_rule_gen_pkgs.get_count_no_lock('TASK');
3930 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3931 x_return_status := fnd_api.g_ret_sts_unexp_error;
3932 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3933 fnd_message.set_token('LIST_PKG', l_list_pkg);
3934 fnd_message.set_token('RULE_NAME', l_package_name);
3935 fnd_msg_pub.ADD;
3936 /*log_error(l_api_name, 'execute_task_rule', 'Invalid Package, Contact your DBA - '
3937 || l_list_pkg || ' / ' || l_package_name); */
3938
3939 END execute_task_rule;
3940
3941 ---
3942
3943 ----- Open cursor and fetch cursor for task rules
3944
3945 PROCEDURE execute_label_rule(p_rule_id IN NUMBER, p_label_request_id IN NUMBER, x_return_status OUT NOCOPY NUMBER) IS
3946
3947 invalid_pkg_state exception;
3948 Pragma Exception_Init(invalid_pkg_state, -6508);
3949 l_msg_data VARCHAR2(240);
3950 l_msg_count NUMBER;
3951 l_api_name VARCHAR2(30);
3952
3953 l_list_pkg VARCHAR2(30);
3954 l_package_name VARCHAR2(128);
3955 l_ctr NUMBER := 0;
3956
3957 BEGIN
3958
3959 if wms_rule_pvt.g_rule_list_label_ctr is null then
3960 wms_rule_pvt.g_rule_list_label_ctr := wms_rule_gen_pkgs.get_count_no_lock('LABEL');
3961 end if;
3962 l_ctr := wms_rule_pvt.g_rule_list_label_ctr;
3963
3964 l_list_pkg := 'wms_rule_label_pkg' || l_ctr ;
3965 getpackagename(p_rule_id, l_package_name);
3966
3967 IF (l_ctr = 1) THEN
3968 wms_rule_label_pkg1.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
3969 ELSIF (l_ctr = 2) THEN
3970 wms_rule_label_pkg2.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
3971 ELSIF (l_ctr = 3) THEN
3972 wms_rule_label_pkg3.execute_label_rule(p_rule_id, p_label_request_id, x_return_status);
3973 END IF;
3974
3975 IF x_return_status IS NULL THEN
3976 x_return_status := 1;
3977 END IF;
3978 EXCEPTION
3979 WHEN INVALID_PKG_STATE THEN
3980 --x_return_status := 0;
3981 x_return_status := -1 ;
3982 wms_rule_pvt.g_rule_list_label_ctr := wms_rule_gen_pkgs.get_count_no_lock('LABEL');
3983 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
3984 x_return_status := fnd_api.g_ret_sts_unexp_error;
3985 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
3986 fnd_message.set_token('LIST_PKG', l_list_pkg);
3987 fnd_message.set_token('RULE_NAME', l_package_name);
3988 fnd_msg_pub.ADD;
3989 /*log_error(l_api_name, 'execute_label_rule', 'Invalid Package, Contact your DBA - '
3990 || l_list_pkg || ' / ' || l_package_name); */
3991
3992 END execute_label_rule;
3993
3994 --- Procedure to Close Pick rule Cursor --
3995 ---
3996
3997 PROCEDURE close_pick_rule(p_rule_id IN NUMBER, p_cursor IN OUT NOCOPY wms_rule_pvt.cv_pick_type) IS
3998
3999 invalid_pkg_state exception;
4000 Pragma Exception_Init(invalid_pkg_state, -6508);
4001 l_msg_data VARCHAR2(240);
4002 l_msg_count NUMBER;
4003 l_api_name VARCHAR2(30);
4004
4005 l_list_pkg VARCHAR2(30);
4006 l_package_name VARCHAR2(128);
4007
4008 l_ctr NUMBER := 0;
4009
4010 BEGIN
4011
4012 l_ctr := wms_rule_pvt.g_rule_list_pick_ctr;
4013 l_list_pkg := 'wms_rule_pick_pkg' || l_ctr ;
4014 getpackagename(p_rule_id, l_package_name);
4015
4016 IF (l_ctr = 1) THEN
4017 wms_rule_pick_pkg1.execute_close_rule(p_rule_id, p_cursor);
4018 ELSIF (l_ctr = 2) THEN
4019 wms_rule_pick_pkg2.execute_close_rule(p_rule_id, p_cursor);
4020 ELSIF (l_ctr = 3) THEN
4021 wms_rule_pick_pkg3.execute_close_rule(p_rule_id, p_cursor);
4022 END IF;
4023
4024 EXCEPTION
4025 WHEN INVALID_PKG_STATE THEN
4026 /* -- WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4027 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4028 fnd_message.set_token('LIST_PKG', l_list_pkg);
4029 fnd_message.set_token('RULE_NAME', l_package_name);
4030 fnd_msg_pub.ADD;
4031 log_error(l_api_name, 'execute_close_rule', 'Invalid Package, Contact your DBA - '
4032 || l_list_pkg || ' / ' || l_package_name); */
4033 RAISE fnd_api.g_exc_unexpected_error;
4034 END close_pick_rule;
4035
4036 -- Procedure to close Putaway rule Cursor ---
4037 --
4038 PROCEDURE close_put_rule(p_rule_id IN NUMBER, p_cursor IN OUT NOCOPY wms_rule_pvt.cv_put_type) IS
4039
4040 invalid_pkg_state exception;
4041 Pragma Exception_Init(invalid_pkg_state, -6508);
4042 l_msg_data VARCHAR2(240);
4043 l_msg_count NUMBER;
4044 l_api_name VARCHAR2(30);
4045 l_list_pkg VARCHAR2(30);
4046 l_package_name VARCHAR2(128);
4047 l_ctr NUMBER := 0;
4048 BEGIN
4049 l_ctr := wms_rule_pvt.g_rule_list_put_ctr;
4050 l_list_pkg := 'wms_rule_put_pkg' || l_ctr ;
4051 getpackagename(p_rule_id, l_package_name);
4052
4053 IF (l_ctr = 1) THEN
4054 wms_rule_put_pkg1.execute_close_rule(p_rule_id, p_cursor);
4055 ELSIF (l_ctr = 2) THEN
4056 wms_rule_put_pkg2.execute_close_rule(p_rule_id, p_cursor);
4057 ELSIF (l_ctr = 3) THEN
4058 wms_rule_put_pkg3.execute_close_rule(p_rule_id, p_cursor);
4059 END IF;
4060
4061 EXCEPTION
4062 WHEN INVALID_PKG_STATE THEN
4063 /*WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'Invalid Package, Contact your DBA - '|| l_list_pkg || ' / ' || l_package_name;
4064 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
4065 fnd_message.set_token('LIST_PKG', l_list_pkg);
4066 fnd_message.set_token('RULE_NAME', l_package_name);
4067 fnd_msg_pub.ADD;
4068 log_error(l_api_name, 'execute_close_rule', 'Invalid Package, Contact your DBA - '
4069 || l_list_pkg || ' / ' || l_package_name);*/
4070 RAISE fnd_api.g_exc_unexpected_error;
4071 END close_put_rule;
4072
4073 --------------
4074 --
4075 -- Name : Rollback_Capacity_Update
4076 -- Function : Used in Apply for Put Away rules.
4077 -- In Apply, the update_loc_suggested_capacity procedure gets
4078 -- called to update the capacity for a locator. This
4079 -- procedure is an autonomous transaction, so it issues
4080 -- a commit. If some sort of error occurs in Apply, we need to
4081 -- undo those changes. We call revert_loc_suggested_capacity
4082 -- to decrement the suggested capacity field. The procedure
4083 -- is also a autonomous transaction
4084 -- Pre-reqs : cursor has to be parsed and executed already.
4085 -- Notes : private procedure for internal use only
4086 --
4087 PROCEDURE rollback_capacity_update(
4088 x_return_status OUT NOCOPY VARCHAR2
4089 , x_msg_count OUT NOCOPY NUMBER
4090 , x_msg_data OUT NOCOPY VARCHAR2
4091 , p_organization_id IN NUMBER
4092 , p_inventory_item_id IN NUMBER
4093 ) IS
4094 l_return_status VARCHAR2(1);
4095 l_msg_data VARCHAR2(240);
4096 l_msg_count NUMBER;
4097 l_no_error BOOLEAN;
4098 l_api_name VARCHAR2(30) := 'rollback_capacity_update';
4099
4100 l_debug NUMBER;
4101
4102 -- gets all of the put away suggestions already created;
4103 -- The locator capacity would have been updated for each of these
4104 -- records
4105 -- type_code 1 = put away; line_type_code 2 = output
4106 CURSOR l_output_lines IS
4107 SELECT to_locator_id
4108 , SUM(primary_quantity) quantity
4109 FROM wms_transactions_temp
4110 WHERE type_code = 1
4111 AND line_type_code = 2
4112 GROUP BY to_locator_id;
4113 BEGIN
4114 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
4115 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
4116 END IF;
4117 l_debug := g_debug;
4118
4119 If l_debug = 1 THEN
4120 log_procedure(l_api_name, 'start', 'Start rollback_capacity_update');
4121 END IF;
4122
4123 l_return_status := fnd_api.g_ret_sts_success;
4124 l_no_error := TRUE;
4125
4126 FOR l_line IN l_output_lines LOOP
4127 -- We don't track capacity at Subinventory level, so no need
4128 -- to update if locator_id is null
4129 IF l_line.to_locator_id IS NOT NULL THEN
4130
4131 IF l_debug = 1 THEN
4132 log_statement(l_api_name, 'calling_revert', 'Calling inv_loc_wms_utils.revert_loc_suggested_capacity');
4133 log_statement(l_api_name, 'revert_org', 'Org: ' || p_organization_id);
4134 log_statement(l_api_name, 'revert_item', 'Item: ' || p_inventory_item_id);
4135 log_statement(l_api_name, 'revert_loc', 'Loc: ' || l_line.to_locator_id);
4136 log_statement(l_api_name, 'revert_qty', 'Qty: ' || l_line.quantity);
4137 END IF;
4138 inv_loc_wms_utils.revert_loc_suggested_capacity(
4139 x_return_status => l_return_status
4140 , x_msg_count => l_msg_count
4141 , x_msg_data => l_msg_data
4142 , p_organization_id => p_organization_id
4143 , p_inventory_location_id => l_line.to_locator_id
4144 , p_inventory_item_id => p_inventory_item_id
4145 , p_primary_uom_flag => 'Y'
4146 , p_transaction_uom_code => NULL
4147 , p_quantity => l_line.quantity
4148 );
4149
4150 --return only the first error message
4151 IF l_no_error
4152 AND l_return_status <> fnd_api.g_ret_sts_success THEN
4153 x_return_status := l_return_status;
4154 x_msg_count := l_msg_count;
4155 x_msg_data := l_msg_data;
4156 l_no_error := FALSE;
4157
4158 IF l_debug = 1 THEN
4159 log_statement(l_api_name, 'first_error', 'Error in inv_loc_wms_utils.revert_loc_suggested_capacity');
4160 END IF;
4161 END IF;
4162 END IF;
4163 END LOOP;
4164 IF l_debug = 1 THEN
4165 log_procedure(l_api_name, 'end', 'End rollback_capacity_update');
4166 END IF;
4167
4168 EXCEPTION
4169 WHEN OTHERS THEN
4170 x_return_status := fnd_api.g_ret_sts_unexp_error;
4171
4172 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
4173 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
4174 END IF;
4175
4176 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4177
4178 IF l_debug = 1 THEN
4179 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
4180 END IF;
4181 END rollback_capacity_update;
4182
4183 -- Bug# 4099907 -- Modifying the fix done in the Bug 3609380
4184 -- Pass the value for transfer_to_sub incase of Subinventory transfer
4185 -- allocations (i.e. with transaction action as 2)
4186 -- Private function
4187 FUNCTION chk_for_passing_xfer_sub
4188 ( p_transaction_temp_id IN NUMBER
4189 , p_to_subinventory_code IN VARCHAR2
4190 )
4191 RETURN VARCHAR2
4192 IS
4193 l_to_subinventory_code MTL_SECONDARY_INVENTORIES.SECONDARY_INVENTORY_NAME%TYPE := NULL ;
4194 l_transaction_action_id NUMBER := 0 ;
4195 l_debug NUMBER := g_debug ;
4196 l_api_name VARCHAR2(30) := 'chk_for_passing_xfer_sub';
4197 l_transaction_type_id NUMBER := 0 ;
4198
4199 BEGIN
4200
4201 IF inv_cache.set_mol_rec(p_transaction_temp_id) THEN
4202 l_transaction_type_id := inv_cache.mol_rec.transaction_type_id;
4203 END IF;
4204
4205 IF l_transaction_type_id <> 0 THEN
4206 IF inv_cache.set_mtt_rec(l_transaction_type_id) THEN
4207 l_transaction_action_id := inv_cache.mtt_rec.transaction_action_id;
4208 END IF;
4209 END IF;
4210
4211 IF l_transaction_action_id = 2 THEN
4212 l_to_subinventory_code := p_to_subinventory_code;
4213 END IF;
4214
4215 IF l_debug = 1 THEN
4216 log_statement(l_api_name, 'l_transaction_action_id', 'l_transaction_action_id : ' || l_transaction_action_id );
4217 log_statement(l_api_name, 'l_to_subinventory_code', 'l_to_subinventory_code: ' || l_to_subinventory_code);
4218 END IF;
4219
4220 RETURN l_to_subinventory_code ;
4221
4222 END chk_for_passing_xfer_sub ;
4223 -- End of function definition for fixing Bug 4099907
4224
4225 PROCEDURE validate_and_insert(
4226 x_return_status OUT NOCOPY VARCHAR2
4227 , x_msg_count OUT NOCOPY NUMBER
4228 , x_msg_data OUT NOCOPY VARCHAR2
4229 , p_record_id IN NUMBER
4230 , p_needed_quantity IN NUMBER
4231 , p_use_pick_uom IN BOOLEAN
4232 , p_organization_id IN NUMBER
4233 , p_inventory_item_id IN NUMBER
4234 , p_to_subinventory_code IN VARCHAR2
4235 , p_to_locator_id IN NUMBER
4236 , p_to_cost_group_id IN NUMBER
4237 , p_primary_uom IN VARCHAR2
4238 , p_transaction_uom IN VARCHAR2
4239 , p_transaction_temp_id IN NUMBER
4240 , p_type_code IN NUMBER
4241 , p_rule_id IN NUMBER
4242 , p_reservation_id IN NUMBER
4243 , p_tree_id IN NUMBER
4244 , p_debug_on IN BOOLEAN
4245 , p_needed_sec_quantity IN NUMBER -- new
4246 , p_secondary_uom IN VARCHAR2 -- new
4247 , p_grade_code IN VARCHAR2 -- new
4248 , x_inserted_record OUT NOCOPY BOOLEAN
4249 , x_allocated_quantity OUT NOCOPY NUMBER
4250 , x_remaining_quantity OUT NOCOPY NUMBER
4251 , x_sec_allocated_quantity OUT NOCOPY NUMBER -- new
4252 , x_sec_remaining_quantity OUT NOCOPY NUMBER -- new
4253 ) IS
4254 l_api_name VARCHAR2(30) := 'validate_and_insert';
4255 l_qoh NUMBER;
4256 l_rqoh NUMBER;
4257 l_qr NUMBER;
4258 l_qs NUMBER;
4259 l_att NUMBER;
4260 l_atr NUMBER;
4261 l_allocation_quantity NUMBER;
4262 l_sqoh NUMBER;
4263 l_srqoh NUMBER;
4264 l_sqr NUMBER;
4265 l_sqs NUMBER;
4266 l_satt NUMBER;
4267 l_satr NUMBER;
4268 l_sallocation_quantity NUMBER;
4269 l_orig_allocation_quantity NUMBER;
4270 l_sorig_allocation_quantity NUMBER;
4271 l_found BOOLEAN;
4272 l_possible_uom_qty NUMBER;
4273 l_possible_trx_qty NUMBER;
4274 l_sec_possible_trx_qty NUMBER;
4275 l_serial_index NUMBER;
4276 l_lot_divisible_flag VARCHAR2(1);
4277 l_lot_control_code NUMBER;
4278 l_to_locator_id NUMBER;
4279 l_dual_uom_ctl NUMBER;
4280 l_detailed_rsv_exist NUMBER;
4281 l_dummy_qty NUMBER;
4282
4283 l_debug NUMBER;
4284 l_indiv_lot_allowed VARCHAR2(1);
4285
4286 CURSOR C_item_info IS
4287 SELECT lot_divisible_flag
4288 , lot_control_code
4289 , dual_uom_control
4290 FROM mtl_system_items
4291 WHERE organization_id = p_organization_id
4292 AND inventory_item_id = p_inventory_item_id;
4293
4294 Cursor c_detailed_reservation IS
4295 Select 1
4296 , secondary_reservation_quantity
4297 From mtl_reservations
4298 Where reservation_id = p_reservation_id
4299 and lot_number = g_locs(p_record_id).lot_number;
4300 BEGIN
4301 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
4302 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
4303 END IF;
4304 l_debug := g_debug;
4305
4306 x_return_status := fnd_api.g_ret_sts_success;
4307 l_allocation_quantity := p_needed_quantity;
4308 l_sallocation_quantity := p_needed_sec_quantity;
4309 l_to_locator_id := p_to_locator_id;
4310 /*
4311
4312 Open C_item_info;
4313 Fetch C_item_info
4314 Into l_lot_divisible_flag
4315 , l_lot_control_code
4316 , l_dual_uom_ctl
4317 ;
4318 Close C_item_info;
4319 */
4320 -- [ Added the following code and commented the above item cursor
4321 l_lot_divisible_flag := inv_cache.item_rec.lot_divisible_flag;
4322 l_lot_control_code := inv_cache.item_rec.lot_control_code;
4323 l_dual_uom_ctl := inv_cache.item_rec.dual_uom_control;
4324 -- ]
4325 /* lot specific conversion 3986955*/
4326 IF l_dual_uom_ctl > 1 and nvl(g_locs(p_record_id).lot_number,'-9999') <> '-9999' THEN
4327 /* bug 5441849, if detailed reservation exist, meaning that user has made the
4328 * correct 2nd qty either by system defaults on the lot
4329 * or manually changed it with the appropriate value, this value on the reservation
4330 * should be carried over to the allocation
4331 */
4332 l_detailed_rsv_exist := 0;
4333 Open c_detailed_reservation ;
4334 Fetch c_detailed_reservation
4335 Into l_detailed_rsv_exist
4336 , l_dummy_qty;
4337 Close c_detailed_reservation;
4338 if l_detailed_rsv_exist = 1 Then
4339 l_sallocation_quantity := l_dummy_qty;
4340 else
4341 l_sallocation_quantity := inv_convert.inv_um_convert(
4342 Item_id => p_inventory_item_id
4343 , Lot_number => g_locs(p_record_id).lot_number
4344 , Organization_id => p_organization_id
4345 , Precision => null
4346 , From_quantity => l_allocation_quantity
4347 , From_unit => p_primary_uom
4348 , To_unit => p_secondary_uom
4349 , from_name => NULL
4350 , to_name => NULL
4351 );
4352 End if;
4353 End If;
4354
4355 IF l_dual_uom_ctl = 1 THEN
4356 l_sallocation_quantity := null;
4357 END IF;
4358
4359 IF l_debug = 1 THEN
4360 log_procedure(l_api_name, 'validate and insert', 'Start Validate_And_Insert');
4361 log_statement(l_api_name, 'validate and insert', 'lot_divisible_flag : ' || l_lot_divisible_flag);
4362 log_statement(l_api_name, 'validate and insert', 'needed quantity: ' || p_needed_quantity);
4363 log_statement(l_api_name, 'validate and insert', 'sec_needed quantity: ' || p_needed_sec_quantity);
4364 log_statement(l_api_name, 'validate and insert', 'p_record_id: ' || p_record_id);
4365 END IF;
4366 /* bug 3972784, remove locator_id if no locator control */
4367 IF ( wms_engine_pvt.g_org_loc_control in (1,4) -- no loc ctl org level
4368 AND ( wms_engine_pvt.g_sub_loc_control = 1 -- no loc ctl sub level
4369 OR (wms_engine_pvt.g_sub_loc_control = 5
4370 AND wms_engine_pvt.g_item_loc_control = 1 -- no loc ctl item level
4371 )
4372 )
4373 )
4374 THEN
4375 l_to_locator_id := null;
4376 log_statement(l_api_name, 'non locator controled',' Non locator controled');
4377 END IF;
4378 IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1 AND g_locs(p_record_id).quantity <= l_allocation_quantity THEN -- lot ctl and indivisible
4379 l_allocation_quantity := g_locs(p_record_id).quantity;
4380 l_sallocation_quantity := g_locs(p_record_id).secondary_quantity;
4381
4382 ELSE
4383 IF l_allocation_quantity > g_locs(p_record_id).quantity THEN
4384 l_allocation_quantity := g_locs(p_record_id).quantity;
4385 l_sallocation_quantity := g_locs(p_record_id).secondary_quantity;
4386
4387 END IF;
4388 END IF;
4389 -- BUG 3609380 : Removing p_to_subinevntory_code.
4390 --query quantity tree
4391 IF l_debug = 1 THEN
4392 log_statement(l_api_name, 'p_revision', g_locs(p_record_id).revision);
4393 log_statement(l_api_name, 'p_lot_number', g_locs(p_record_id).lot_number);
4394 log_statement(l_api_name, 'p_subinventory', g_locs(p_record_id).subinventory_code);
4395 log_statement(l_api_name, 'record_quantity', 'record quantity: ' || l_allocation_quantity);
4396 log_statement(l_api_name, 'sec_record_quantity', 'sec_record quantity: ' || l_sallocation_quantity);
4397 log_statement(l_api_name, 'query_tree', 'Calling Query Tree');
4398 log_statement(l_api_name, 'tree_id', 'tree_id: ' || p_tree_id);
4399
4400 END IF;
4401
4402 inv_quantity_tree_pvt.query_tree
4403 (
4404 p_api_version_number => g_qty_tree_api_version
4405 , p_init_msg_lst => fnd_api.g_false -- p_init_msg_lst
4406 , x_return_status => x_return_status
4407 , x_msg_count => x_msg_count
4408 , x_msg_data => x_msg_data
4409 , p_tree_id => p_tree_id
4410 , p_revision => g_locs(p_record_id).revision
4411 , p_lot_number => g_locs(p_record_id).lot_number
4412 , p_subinventory_code => g_locs(p_record_id).subinventory_code
4413 , p_locator_id => g_locs(p_record_id).locator_id
4414 , x_qoh => l_qoh
4415 , x_sqoh => l_sqoh
4416 , x_rqoh => l_rqoh
4417 , x_srqoh => l_srqoh
4418 , x_qr => l_qr
4419 , x_sqr => l_sqr
4420 , x_qs => l_qs
4421 , x_sqs => l_sqs
4422 , x_att => l_att
4423 , x_satt => l_satt
4424 , x_atr => l_atr
4425 , x_satr => l_satr
4426 , p_transfer_subinventory_code => chk_for_passing_xfer_sub ( TO_NUMBER(p_transaction_temp_id) , p_to_subinventory_code) -- Bug # 4099907
4427 , p_cost_group_id => g_locs(p_record_id).cost_group_id
4428 , p_lpn_id => g_locs(p_record_id).lpn_id
4429 );
4430 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
4431 IF l_debug = 1 THEN
4432 log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
4433 END IF;
4434 RAISE fnd_api.g_exc_unexpected_error;
4435 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
4436 IF l_debug = 1 THEN
4437 log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
4438 END IF;
4439 RAISE fnd_api.g_exc_error;
4440 END IF;
4441
4442 IF l_debug = 1 THEN
4443 log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
4444 log_statement(l_api_name, 'satt_qty', 'Secondary Available quantity = ' || l_satt);
4445 log_statement(l_api_name, 'grade_code', 'grade_code = ' || p_grade_code);
4446 END IF;
4447 -- [ LOT_INDIV
4448 -- Checking ,
4449 -- a. If the pre suggestion record fetched from the rule is greater than the max qty allowed
4450 -- after adjusting the for upper tolerance .
4451 -- b. If ATT qty is equal to ON hand Qty to that of the pre suggestions record qty.
4452 -- It may be different due to partial reservations.
4453 -- The pre suggestions record will be skipped, if any of the above condition is false
4454 -- and fetch the next rec
4455 -- ]
4456 IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1 AND g_locs(p_record_id).quantity <= l_allocation_quantity THEN -- lot ctl and indivisible
4457
4458 IF ((l_att = g_locs(p_record_id).quantity) and ( l_qoh = l_att)) THEN
4459 l_indiv_lot_allowed := 'Y';
4460 Else
4461 l_indiv_lot_allowed := 'N';
4462 IF l_debug = 1 THEN
4463 log_statement(l_api_name, '', 'All the material is not available for this rec.');
4464 END IF;
4465 End if;
4466 Else
4467 l_indiv_lot_allowed := 'N' ;
4468 END IF;
4469
4470 --update record quantity
4471 IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1 THEN -- lot ctl and indivisible
4472 IF l_indiv_lot_allowed = 'Y' THEN
4473 g_locs(p_record_id).quantity := l_att;
4474 g_locs(p_record_id).secondary_quantity := l_satt;
4475 g_locs(p_record_id).grade_code := p_grade_code;
4476 --update possible allocate quantity
4477 l_allocation_quantity := l_att;
4478 l_sallocation_quantity := l_satt;
4479 ELSE
4480 l_allocation_quantity := 0;
4481 l_sallocation_quantity := 0;
4482 END IF;
4483 IF l_debug = 1 THEN
4484 log_statement(l_api_name, 'Lot Indiv', ' lot IS NOT divisible -- indivsible' );
4485 log_statement(l_api_name, 'Lot Indiv', 'New possible qty: ' || l_allocation_quantity);
4486 END IF;
4487 ELSE
4488 IF l_att < g_locs(p_record_id).quantity THEN
4489 g_locs(p_record_id).quantity := l_att;
4490 g_locs(p_record_id).secondary_quantity := l_satt;
4491 g_locs(p_record_id).grade_code := p_grade_code;
4492 END IF;
4493 --update possible allocate quantity
4494 IF l_att < l_allocation_quantity THEN
4495 l_allocation_quantity := l_att;
4496 l_sallocation_quantity := l_satt;
4497 END IF;
4498 END IF;
4499 IF l_debug = 1 THEN
4500 log_statement(l_api_name, 'tree_qty', 'ATT < possible quantity. New possible qty: ' || g_locs(p_record_id).quantity);
4501 END IF;
4502
4503
4504 --if no available quantity, return
4505 IF l_allocation_quantity <= 0 THEN
4506 --if reading from table, go to next record
4507 IF l_debug = 1 THEN
4508 log_event(l_api_name, 'zero_tree_qty', 'Available quantity ' || 'returned from quantity tree is zero');
4509 END IF;
4510 IF p_debug_on THEN
4511 g_trace_recs(p_record_id).att_qty := l_att;
4512 g_trace_recs(p_record_id).secondary_att_qty := l_satt;
4513 g_trace_recs(p_record_id).att_qty_flag := 'N';
4514 END IF;
4515 x_allocated_quantity := 0;
4516 x_remaining_quantity := 0;
4517 x_inserted_record := FALSE;
4518 RETURN;
4519 END IF;
4520
4521 IF p_debug_on THEN
4522 g_trace_recs(p_record_id).att_qty := l_att;
4523 g_trace_recs(p_record_id).secondary_att_qty := l_satt;
4524 g_trace_recs(p_record_id).att_qty_flag := 'Y';
4525 END IF;
4526
4527 --check to see if serial number has already been used
4528 IF (g_locs(p_record_id).serial_number IS NOT NULL
4529 And g_locs(p_record_id).serial_number <> FND_API.G_MISS_CHAR)
4530 THEN
4531 IF l_debug = 1 THEN
4532 log_statement(l_api_name, 'search_sn', 'Calling Search Serial Numbers');
4533 END IF;
4534
4535 inv_detail_util_pvt.search_serial_numbers(
4536 p_organization_id => p_organization_id
4537 , p_inventory_item_id => p_inventory_item_id
4538 , p_serial_number => g_locs(p_record_id).serial_number
4539 , x_found => l_found
4540 , x_return_status => x_return_status
4541 , x_msg_count => x_msg_count
4542 , x_msg_data => x_msg_data
4543 );
4544
4545 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
4546 IF l_debug = 1 THEN
4547 log_statement(l_api_name, 'uerr_search_sn', 'Unexpected error in search_serial_numbers');
4548 END IF;
4549 RAISE fnd_api.g_exc_unexpected_error;
4550 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
4551 IF l_debug = 1 THEN
4552 log_statement(l_api_name, 'err_search_sn', 'Error in search_serial_numbers');
4553 END IF;
4554 RAISE fnd_api.g_exc_error;
4555 END IF;
4556
4557 IF l_found THEN
4558 IF p_debug_on THEN
4559 g_trace_recs(p_record_id).serial_number_used_flag := 'N';
4560 END IF;
4561 IF l_debug = 1 THEN
4562 log_event(l_api_name, 'sn_used', 'Serial Number has been used');
4563 END IF;
4564 g_locs(p_record_id).quantity := 0;
4565 x_allocated_quantity := 0;
4566 x_remaining_quantity := 0;
4567 x_inserted_record := FALSE;
4568 RETURN;
4569 END IF;
4570
4571 IF p_debug_on THEN
4572 g_trace_recs(p_record_id).serial_number_used_flag := 'Y';
4573 END IF;
4574 END IF;
4575
4576 --If we are factoring in Pick UOM, convert quantity into Pick UOM.
4577 --Then, find the the largest non-decimal quantity in Pick UOM. Convert
4578 --back to primary UOM
4579 -- if Uom code is null, than use primary uom
4580 -- if pick uom = primary uom, skip conversions
4581
4582 l_orig_allocation_quantity := l_allocation_quantity;
4583 l_sorig_allocation_quantity := l_sallocation_quantity;
4584
4585 IF p_use_pick_uom
4586 AND g_locs(p_record_id).uom_code IS NOT NULL
4587 AND g_locs(p_record_id).uom_code <> p_primary_uom THEN
4588
4589 IF l_debug = 1 THEN
4590 log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
4591 END IF;
4592 --convert from primary uom to pick uom
4593 l_possible_uom_qty := inv_convert.inv_um_convert(
4594 p_inventory_item_id
4595 , NULL
4596 , l_allocation_quantity
4597 , p_primary_uom
4598 , g_locs(p_record_id).uom_code
4599 , NULL
4600 , NULL
4601 );
4602
4603 --if no conversion defined or some error in conversion,
4604 --inv_um_convert returns -99999. In this case, don't carry
4605 --out any more conversion functions. possible quantity
4606 --remains unchanged
4607 IF (l_possible_uom_qty <> -99999) THEN
4608 --don't want to pick fractional amounts of pick uom
4609 l_possible_uom_qty := FLOOR(l_possible_uom_qty);
4610
4611 IF l_debug = 1 THEN
4612 log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
4613 END IF;
4614 --convert back to primary uom
4615 l_allocation_quantity := inv_convert.inv_um_convert(
4616 p_inventory_item_id
4617 , NULL
4618 , l_possible_uom_qty
4619 , g_locs(p_record_id).uom_code
4620 , p_primary_uom
4621 , NULL
4622 , NULL
4623 );
4624 IF l_debug = 1 THEN
4625 log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: ' || l_allocation_quantity);
4626 END IF;
4627 END IF;
4628 END IF;
4629
4630 --populate remaining quantity
4631 x_remaining_quantity := l_orig_allocation_quantity - l_allocation_quantity;
4632 x_sec_remaining_quantity := l_sorig_allocation_quantity - l_sallocation_quantity;
4633 IF l_debug = 1 THEN
4634 log_statement(l_api_name, 'rem_qty', 'remaining_quantity : ' || x_remaining_quantity);
4635 END IF;
4636
4637 IF l_allocation_quantity <= 0 THEN
4638 IF l_debug = 1 THEN
4639 log_statement(l_api_name, 'no_alloc_qty', 'Quantity remaining to allocate. Exiting.');
4640 END IF;
4641 x_allocated_quantity := 0;
4642 x_sec_allocated_quantity := 0;
4643 x_inserted_record := FALSE;
4644 RETURN;
4645 END IF;
4646
4647 --Lock Serial number, so that no other detailing process
4648 -- can use it.
4649 IF (g_locs(p_record_id).serial_number IS NOT NULL
4650 And g_locs(p_record_id).serial_number <> FND_API.G_MISS_CHAR)
4651 THEN
4652 l_found := inv_detail_util_pvt.lock_serial_number(p_inventory_item_id, g_locs(p_record_id).serial_number);
4653
4654 IF l_found = FALSE THEN
4655 IF l_debug = 1 THEN
4656 log_statement(l_api_name, 'lock_sn', 'Could not lock Serial Number. Exiting.');
4657 END IF;
4658
4659 IF p_debug_on THEN
4660 g_trace_recs(p_record_id).serial_number_used_flag := 'N';
4661 END IF;
4662
4663 x_remaining_quantity := g_locs(p_record_id).quantity;
4664 x_allocated_quantity := 0;
4665 x_sec_remaining_quantity := null;
4666 x_sec_allocated_quantity := null;
4667 x_inserted_record := FALSE;
4668 RETURN;
4669 END IF;
4670
4671 -- add serial number to pl/sql table of detailed serials
4672 inv_detail_util_pvt.add_serial_number(p_inventory_item_id, p_organization_id, g_locs(p_record_id).serial_number, l_serial_index);
4673 END IF;
4674
4675 -- Update quantity tree for this suggested quantity
4676 IF l_debug = 1 THEN
4677 log_statement(l_api_name, 'update_tree', 'Updating qty tree');
4678 END IF;
4679
4680 inv_quantity_tree_pvt.update_quantities
4681 (
4682 p_api_version_number => g_qty_tree_api_version
4683 , p_init_msg_lst => fnd_api.g_false
4684 , x_return_status => x_return_status
4685 , x_msg_count => x_msg_count
4686 , x_msg_data => x_msg_data
4687 , p_tree_id => p_tree_id
4688 , p_revision => g_locs(p_record_id).revision
4689 , p_lot_number => g_locs(p_record_id).lot_number
4690 , p_subinventory_code => g_locs(p_record_id).subinventory_code
4691 , p_locator_id => g_locs(p_record_id).locator_id
4692 , p_primary_quantity => l_allocation_quantity
4693 , p_secondary_quantity => l_sallocation_quantity -- INVCONV
4694 , p_quantity_type => inv_quantity_tree_pvt.g_qs_txn
4695 , x_qoh => l_qoh
4696 , x_rqoh => l_rqoh
4697 , x_qr => l_qr
4698 , x_qs => l_qs
4699 , x_att => l_att
4700 , x_atr => l_atr
4701 , x_sqoh => l_sqoh -- INVCONV
4702 , x_srqoh => l_srqoh -- INVCONV
4703 , x_sqr => l_sqr -- INVCONV
4704 , x_sqs => l_sqs -- INVCONV
4705 , x_satt => l_satt -- INVCONV
4706 , x_satr => l_satr -- INVCONV
4707 , p_transfer_subinventory_code => p_to_subinventory_code
4708 , p_cost_group_id => g_locs(p_record_id).cost_group_id
4709 , p_lpn_id => g_locs(p_record_id).lpn_id
4710 );
4711
4712 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
4713 IF l_debug = 1 THEN
4714 log_statement(l_api_name, 'uerr_update_qty', 'Unexpected error in inv_quantity_tree_pvt.update_quantities');
4715 END IF;
4716
4717 RAISE fnd_api.g_exc_unexpected_error;
4718 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
4719 IF l_debug = 1 THEN
4720 log_statement(l_api_name, 'err_update_qty', 'Error in inv_quantity_tree_pvt.update_quantities');
4721 END IF;
4722 RAISE fnd_api.g_exc_error;
4723 END IF;
4724
4725 --If quantity remaining to allocate is greater than 0, update the
4726 --quantity tree and insert the record into WTT
4727 IF p_transaction_uom = p_primary_uom THEN
4728 l_possible_trx_qty := l_allocation_quantity;
4729 ELSE
4730 l_possible_trx_qty :=
4731 inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_allocation_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
4732 END IF;
4733 l_sec_possible_trx_qty := l_sallocation_quantity;
4734
4735 IF l_debug = 1 THEN
4736 log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Trx Qty: ' || l_possible_trx_qty);
4737 log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Sec Trx Qty: ' || l_sec_possible_trx_qty);
4738 END IF;
4739 -- insert temporary suggestion
4740 INSERT INTO wms_transactions_temp
4741 (
4742 pp_transaction_temp_id
4743 , transaction_temp_id
4744 , type_code
4745 , line_type_code
4746 , transaction_quantity
4747 , primary_quantity
4748 , secondary_quantity
4749 , grade_code
4750 , revision
4751 , lot_number
4752 , lot_expiration_date
4753 , from_subinventory_code
4754 , from_locator_id
4755 , rule_id
4756 , reservation_id
4757 , serial_number
4758 , to_subinventory_code
4759 , to_locator_id
4760 , from_cost_group_id
4761 , to_cost_group_id
4762 , lpn_id
4763 )
4764 VALUES (
4765 wms_transactions_temp_s.NEXTVAL
4766 , p_transaction_temp_id
4767 , p_type_code
4768 , 2 -- line type code is output
4769 , l_possible_trx_qty
4770 , l_allocation_quantity
4771 , l_sallocation_quantity
4772 , g_locs(p_record_id).grade_code
4773 , g_locs(p_record_id).revision
4774 , g_locs(p_record_id).lot_number
4775 , g_locs(p_record_id).lot_expiration_date
4776 , g_locs(p_record_id).subinventory_code
4777 , g_locs(p_record_id).locator_id
4778 , p_rule_id
4779 , p_reservation_id
4780 , g_locs(p_record_id).serial_number
4781 , p_to_subinventory_code
4782 , l_to_locator_id
4783 , g_locs(p_record_id).cost_group_id
4784 , p_to_cost_group_id
4785 , g_locs(p_record_id).lpn_id
4786 );
4787 IF l_debug = 1 THEN
4788 log_statement(l_api_name, 'finish_insert_wtt', 'Finished inserting wtt recs.');
4789 log_statement(l_api_name, 'alloc_qty', 'Alloc qty: ' || l_allocation_quantity);
4790 log_statement(l_api_name, 'sec_alloc_qty', 'sec_Alloc qty: ' || l_sallocation_quantity);
4791 END IF;
4792
4793 IF p_debug_on THEN
4794 g_trace_recs(p_record_id).suggested_qty := l_allocation_quantity;
4795 g_trace_recs(p_record_id).secondary_suggested_qty := l_sallocation_quantity;
4796 END IF;
4797
4798 x_inserted_record := TRUE;
4799 x_allocated_quantity := l_allocation_quantity;
4800 x_sec_allocated_quantity := l_sallocation_quantity;
4801 IF l_debug = 1 THEN
4802 log_statement(l_api_name, 'alloc_qty', 'Allocated quantity: ' || x_allocated_quantity);
4803 log_statement(l_api_name, 'sec_alloc_qty', 'sec_Allocated quantity: ' || x_sec_allocated_quantity);
4804 log_procedure(l_api_name, 'end', 'End Validate_and_Insert');
4805 END IF;
4806
4807 EXCEPTION
4808 WHEN fnd_api.g_exc_error THEN
4809 x_return_status := fnd_api.g_ret_sts_error;
4810 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4811 --
4812 IF l_debug = 1 THEN
4813 log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
4814 END IF;
4815
4816 WHEN fnd_api.g_exc_unexpected_error THEN
4817 x_return_status := fnd_api.g_ret_sts_unexp_error;
4818 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4819 IF l_debug = 1 THEN
4820 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
4821 END IF;
4822
4823 WHEN OTHERS THEN
4824 x_return_status := fnd_api.g_ret_sts_unexp_error;
4825
4826 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
4827 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
4828 END IF;
4829
4830 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
4831 IF l_debug = 1 THEN
4832 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
4833 END IF;
4834
4835 END validate_and_insert;
4836 --- Added the following procedure for bug #4006426
4837
4838 -- This procedure is used to get the quantity available to transact
4839 -- for a sub-transfer from a non-reservable subinventory.
4840 -- It assumed that pending transactions only exist at locator and lpn level
4841 -- The quantity is calculated with onhand quantity from
4842 -- MTL_ONHAND_QUANTITIES_DETAIL and pending transactions from
4843 -- MTL_MATERIAL_TRANSACTIONS_TEMP
4844 -- First get onhand and pending transactions at LPN level
4845 -- If LPN level availability > 0 then get pending transactions at Locator level
4846 -- return onhand less pending transactions
4847 -- NOTES :-
4848 -- 1) The quantities calculated do not include suggestions
4849 -- 2) Transfer SUB and locator are not needed in this query as this should be used
4850 -- only to get availability in a locator controlled SUB.
4851 -- 3) LOT expiration dates are not considered as this is to be used only for inventory moves
4852
4853 PROCEDURE GET_AVAIL_QTY_FOR_XFER
4854 ( p_organization_id IN NUMBER
4855 , p_inventory_item_id IN NUMBER
4856 , p_revision IN VARCHAR2
4857 , p_lot_number IN VARCHAR2
4858 , p_subinventory_code IN VARCHAR2
4859 , p_locator_id IN NUMBER
4860 , p_lpn_id IN NUMBER
4861 , x_qoh OUT NOCOPY NUMBER
4862 , x_att OUT NOCOPY NUMBER
4863 , x_return_status OUT NOCOPY VARCHAR2
4864 , x_msg_count OUT NOCOPY NUMBER
4865 , x_msg_data OUT NOCOPY VARCHAR2
4866 )
4867 AS
4868 l_qoh NUMBER;
4869 l_att NUMBER;
4870 l_lpn_qoh NUMBER;
4871 l_lpn_att NUMBER;
4872 l_loc_qoh NUMBER;
4873 l_loc_att NUMBER;
4874 l_moq_qty NUMBER;
4875 l_mmtt_qty_src NUMBER;
4876 l_mmtt_qty_dest NUMBER;
4877
4878 l_debug NUMBER := 1;
4879
4880 BEGIN
4881
4882 IF(l_debug=1) THEN
4883 inv_log_util.trace('Inside :GET_AVAIL_QTY_FOR_XFER ' , 'Start', 9);
4884 inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER ' , 'p_organization_id :'||p_organization_id, 9);
4885 inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER ' , 'p_inventory_item_id :'||p_inventory_item_id, 9);
4886 inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER ' , 'p_revision :'||p_revision, 9);
4887 inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER ' , 'p_subinventory_code :'||p_subinventory_code, 9);
4888 inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER ' , 'p_lot_number :'||p_lot_number, 9);
4889 inv_log_util.trace('GET_AVAIL_QTY_FOR_XFER ' , 'p_lpn_id :'||p_lpn_id, 9);
4890 END IF;
4891
4892 IF p_lpn_id IS NOT NULL THEN
4893 -- LPN level
4894 SELECT SUM(moq.primary_transaction_quantity)
4895 INTO l_moq_qty
4896 FROM mtl_onhand_quantities_detail moq
4897 WHERE moq.organization_id = p_organization_id
4898 AND moq.inventory_item_id = p_inventory_item_id
4899 AND nvl(moq.revision,'@@') = nvl(p_revision,'@@')
4900 AND moq.subinventory_code = p_subinventory_code
4901 AND decode(p_lot_number,null,'@@',moq.lot_number) = nvl(p_lot_number,'@@')
4902 AND moq.locator_id = p_locator_id
4903 AND moq.lpn_id = p_lpn_id;
4904
4905 IF(l_debug=1) THEN
4906 inv_log_util.trace('Total MOQ quantity LPN Level: ' || to_char(l_moq_qty), 'GET_AVAIL_QTY_FOR_XFER', 9);
4907 END IF;
4908
4909 SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
4910 Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
4911 Sign(mmtt.primary_quantity)))
4912 * round(Abs(mmtt.primary_quantity),5))
4913 INTO l_mmtt_qty_src
4914 FROM mtl_material_transactions_temp mmtt
4915 WHERE mmtt.organization_id = p_organization_id
4916 AND mmtt.inventory_item_id = p_inventory_item_id
4917 AND nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
4918 AND mmtt.subinventory_code = p_subinventory_code
4919 AND mmtt.locator_id = p_locator_id
4920 AND NVL(mmtt.content_lpn_id,mmtt.transfer_lpn_id) = p_lpn_id
4921 AND mmtt.posting_flag = 'Y'
4922 AND mmtt.subinventory_code IS NOT NULL
4923 AND (Nvl(mmtt.transaction_status,0) <> 2 OR
4924 Nvl(mmtt.transaction_status,0) = 2 AND
4925 mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
4926 )
4927 AND mmtt.transaction_action_id NOT IN (5,6,24,30);
4928
4929 IF(l_debug=1) THEN
4930 inv_log_util.trace('Total MMTT Trx quantity Source Org Sub : ' || to_char(l_mmtt_qty_src), 'GET_AVAIL_QTY_FOR_XFER', 9);
4931 END IF;
4932
4933 SELECT SUM(Abs(mmtt.primary_quantity))
4934 INTO l_mmtt_qty_dest
4935 FROM mtl_material_transactions_temp mmtt
4936 WHERE decode(mmtt.transaction_action_id,3,
4937 mmtt.transfer_organization,mmtt.organization_id) = p_organization_id
4938 AND mmtt.inventory_item_id = p_inventory_item_id
4939 AND nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
4940 AND mmtt.transfer_subinventory = p_subinventory_code
4941 AND mmtt.transfer_to_location = p_locator_id
4942 AND NVL(mmtt.content_lpn_id,mmtt.transfer_lpn_id) = p_lpn_id
4943 AND mmtt.posting_flag = 'Y'
4944 AND Nvl(mmtt.transaction_status,0) <> 2
4945 AND mmtt.transaction_action_id in (2,28,3)
4946 AND mmtt.wip_supply_type IS NULL;
4947
4948 IF(l_debug=1) THEN
4949 inv_log_util.trace('Total MMTT Trx quantity Dest Org Sub : ' || to_char(l_mmtt_qty_dest), 'GET_AVAIL_QTY_FOR_XFER', 9);
4950 END IF;
4951
4952 l_lpn_qoh := nvl(l_moq_qty,0);
4953 l_lpn_att := nvl(l_moq_qty,0) + nvl(l_mmtt_qty_src,0) + nvl(l_mmtt_qty_dest,0);
4954
4955 END IF;
4956
4957 -- Only check onhand and pending at locator level if there is availability at LPN
4958 -- or no lpn passed in
4959 IF (nvl(l_lpn_att,0) > 0) OR (p_lpn_id IS NULL) THEN
4960
4961 SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
4962 Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
4963 Sign(mmtt.primary_quantity)))
4964 * round(Abs(mmtt.primary_quantity),5))
4965 INTO l_mmtt_qty_src
4966 FROM mtl_material_transactions_temp mmtt
4967 WHERE mmtt.organization_id = p_organization_id
4968 AND mmtt.inventory_item_id = p_inventory_item_id
4969 AND nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
4970 AND mmtt.subinventory_code = p_subinventory_code
4971 AND mmtt.locator_id = p_locator_id
4972 AND mmtt.posting_flag = 'Y'
4973 AND mmtt.subinventory_code IS NOT NULL
4974 AND (Nvl(mmtt.transaction_status,0) <> 2 OR
4975 Nvl(mmtt.transaction_status,0) = 2 AND
4976 mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
4977 )
4978 AND mmtt.transaction_action_id NOT IN (5,6,24,30);
4979
4980 IF(l_debug=1) THEN
4981 inv_log_util.trace('Total MMTT Trx quantity Source Org Sub : ' || to_char(l_mmtt_qty_src), 'GET_AVAIL_QTY_FOR_XFER', 9);
4982 END IF;
4983
4984 SELECT SUM(moq.primary_transaction_quantity)
4985 INTO l_moq_qty
4986 FROM mtl_onhand_quantities_detail moq
4987 WHERE moq.organization_id = p_organization_id
4988 AND moq.inventory_item_id = p_inventory_item_id
4989 AND nvl(moq.revision,'@@') = nvl(p_revision,'@@')
4990 AND moq.subinventory_code = p_subinventory_code
4991 AND decode(p_lot_number,null,'@@',moq.lot_number) = nvl(p_lot_number,'@@')
4992 AND moq.locator_id = p_locator_id;
4993
4994 IF(l_debug=1) THEN
4995 inv_log_util.trace('Total MOQ quantity LPN Level: ' || to_char(l_moq_qty), 'GET_AVAIL_QTY_FOR_XFER', 9);
4996 END IF;
4997
4998 SELECT SUM(Decode(mmtt.transaction_status, 2, 1,
4999 Decode(mmtt.transaction_action_id,1,-1,2,-1,28,-1,3,-1,
5000 Sign(mmtt.primary_quantity)))
5001 * round(Abs(mmtt.primary_quantity),5))
5002 INTO l_mmtt_qty_src
5003 FROM mtl_material_transactions_temp mmtt
5004 WHERE mmtt.organization_id = p_organization_id
5005 AND mmtt.inventory_item_id = p_inventory_item_id
5006 AND nvl(mmtt.revision,'@@') = nvl(p_revision,'@@')
5007 AND mmtt.subinventory_code = p_subinventory_code
5008 AND mmtt.locator_id = p_locator_id
5009 AND mmtt.posting_flag = 'Y'
5010 AND mmtt.subinventory_code IS NOT NULL
5011 AND (Nvl(mmtt.transaction_status,0) <> 2 OR
5012 Nvl(mmtt.transaction_status,0) = 2 AND
5013 mmtt.transaction_action_id IN (1,2,28,3,21,29,32,34)
5014 )
5015 AND mmtt.transaction_action_id NOT IN (5,6,24,30);
5016 l_loc_qoh := nvl(l_moq_qty,0);
5017 l_loc_att := nvl(l_moq_qty,0) + nvl(l_mmtt_qty_src,0) + nvl(l_mmtt_qty_dest,0);
5018 END IF;
5019
5020
5021 -- Quantity available for transfer is the minimum of availability at LPN and locator levels
5022 IF p_lpn_id IS NULL THEN
5023 x_qoh := l_loc_qoh;
5024 x_att := l_loc_att;
5025 ELSE
5026 x_qoh := l_lpn_qoh;
5027 IF nvl(l_lpn_att,0) > nvl(l_loc_att,0) THEN
5028 x_att := l_loc_att;
5029 ELSE
5030 x_att := l_lpn_att;
5031 END IF;
5032 END IF;
5033
5034 IF(l_debug=1) THEN
5035 inv_log_util.trace('Total quantity on-hand: ' || to_char(l_qoh), 'GET_AVAIL_QTY_FOR_XFER', 9);
5036 END IF;
5037 END GET_AVAIL_QTY_FOR_XFER;
5038
5039
5040 ---
5041 PROCEDURE ValidNinsert(
5042 x_return_status OUT NOCOPY VARCHAR2
5043 , x_msg_count OUT NOCOPY NUMBER
5044 , x_msg_data OUT NOCOPY VARCHAR2
5045 , p_record_id IN NUMBER
5046 , p_needed_quantity IN NUMBER
5047 , p_use_pick_uom IN BOOLEAN
5048 , p_organization_id IN NUMBER
5049 , p_inventory_item_id IN NUMBER
5050 , p_to_subinventory_code IN VARCHAR2
5051 , p_to_locator_id IN NUMBER
5052 , p_to_cost_group_id IN NUMBER
5053 , p_primary_uom IN VARCHAR2
5054 , p_transaction_uom IN VARCHAR2
5055 , p_transaction_temp_id IN NUMBER
5056 , p_type_code IN NUMBER
5057 , p_rule_id IN NUMBER
5058 , p_reservation_id IN NUMBER
5059 , p_tree_id IN NUMBER
5060 , p_debug_on IN BOOLEAN
5061 , x_inserted_record OUT NOCOPY BOOLEAN
5062 , x_allocated_quantity OUT NOCOPY NUMBER
5063 , x_remaining_quantity OUT NOCOPY NUMBER
5064 ) IS
5065 l_api_name VARCHAR2(30) := 'validate_N_insert';
5066 l_att NUMBER;
5067 l_qoh NUMBER;
5068 l_allocation_quantity NUMBER;
5069 l_orig_allocation_quantity NUMBER;
5070 l_found BOOLEAN;
5071 l_possible_uom_qty NUMBER;
5072 l_possible_trx_qty NUMBER;
5073 l_serial_index NUMBER;
5074
5075 l_debug NUMBER;
5076
5077 BEGIN
5078 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
5079 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
5080 END IF;
5081 l_debug := g_debug;
5082
5083 x_return_status := fnd_api.g_ret_sts_success;
5084 l_allocation_quantity := p_needed_quantity;
5085
5086 IF l_debug = 1 THEN
5087 log_procedure(l_api_name, 'start', 'Start Validate_N_Insert');
5088 log_statement(l_api_name, 'needed_quantity', 'needed quantity: ' || p_needed_quantity);
5089 log_statement(l_api_name, 'rec_id', 'p_record_id: ' || p_record_id);
5090 END IF;
5091
5092 IF l_allocation_quantity > g_locs(p_record_id).quantity THEN
5093 l_allocation_quantity := g_locs(p_record_id).quantity;
5094 log_statement(l_api_name, 'record_quantity', 'record quantity: ' || l_allocation_quantity);
5095 END IF;
5096
5097 GET_AVAIL_QTY_FOR_XFER(
5098 p_organization_id => p_organization_id
5099 , p_inventory_item_id => p_inventory_item_id
5100 , p_revision => g_locs(p_record_id).revision
5101 , p_lot_number => g_locs(p_record_id).lot_number
5102 , p_subinventory_code => g_locs(p_record_id).subinventory_code
5103 , p_locator_id => g_locs(p_record_id).locator_id
5104 , p_lpn_id => g_locs(p_record_id).lpn_id
5105 , x_qoh => l_qoh
5106 , x_att => l_att
5107 , x_return_status => x_return_status
5108 , x_msg_count => x_msg_count
5109 , x_msg_data => x_msg_data );
5110
5111
5112 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5113 IF l_debug = 1 THEN
5114 log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
5115 END IF;
5116 RAISE fnd_api.g_exc_unexpected_error;
5117 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5118 IF l_debug = 1 THEN
5119 log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
5120 END IF;
5121 RAISE fnd_api.g_exc_error;
5122 END IF;
5123
5124 IF l_debug = 1 THEN
5125 log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
5126 END IF;
5127 --update record quantity
5128 IF l_att < g_locs(p_record_id).quantity THEN
5129 g_locs(p_record_id).quantity := l_att;
5130 END IF;
5131
5132 --update possible allocate quantity
5133 IF l_att < l_allocation_quantity THEN
5134 l_allocation_quantity := l_att;
5135 IF l_debug = 1 THEN
5136 log_statement(l_api_name, 'tAvailable_qty', 'ATT < possible quantity. New possible qty: ' || g_locs(p_record_id).quantity);
5137 END IF;
5138 END IF;
5139
5140 --if no available quantity, return
5141 IF l_allocation_quantity <= 0 THEN
5142 --if reading from table, go to next record
5143 IF l_debug = 1 THEN
5144 log_event(l_api_name, 'zero_tree_qty', 'Available quantity ' || 'returned from quantity tree is zero');
5145 END IF;
5146
5147 IF p_debug_on THEN
5148 g_trace_recs(p_record_id).att_qty := l_att;
5149 g_trace_recs(p_record_id).att_qty_flag := 'N';
5150 END IF;
5151
5152 x_allocated_quantity := 0;
5153 x_remaining_quantity := 0;
5154 x_inserted_record := FALSE;
5155 RETURN;
5156 END IF;
5157
5158 IF p_debug_on THEN
5159 g_trace_recs(p_record_id).att_qty := l_att;
5160 g_trace_recs(p_record_id).att_qty_flag := 'Y';
5161 END IF;
5162
5163 --check to see if serial number has already been used
5164 IF g_locs(p_record_id).serial_number IS NOT NULL THEN
5165 IF l_debug = 1 THEN
5166 log_statement(l_api_name, 'search_sn', 'Calling Search Serial Numbers');
5167 END IF;
5168
5169 inv_detail_util_pvt.search_serial_numbers(
5170 p_organization_id => p_organization_id
5171 , p_inventory_item_id => p_inventory_item_id
5172 , p_serial_number => g_locs(p_record_id).serial_number
5173 , x_found => l_found
5174 , x_return_status => x_return_status
5175 , x_msg_count => x_msg_count
5176 , x_msg_data => x_msg_data
5177 );
5178
5179 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5180 IF l_debug = 1 THEN
5181 log_statement(l_api_name, 'uerr_search_sn', 'Unexpected error in search_serial_numbers');
5182 END IF;
5183 RAISE fnd_api.g_exc_unexpected_error;
5184 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5185 IF l_debug = 1 THEN
5186 log_statement(l_api_name, 'err_search_sn', 'Error in search_serial_numbers');
5187 END IF;
5188 RAISE fnd_api.g_exc_error;
5189 END IF;
5190
5191 IF l_found THEN
5192 IF p_debug_on THEN
5193 g_trace_recs(p_record_id).serial_number_used_flag := 'N';
5194 END IF;
5195 IF l_debug = 1 THEN
5196 log_event(l_api_name, 'sn_used', 'Serial Number has been used');
5197 END IF;
5198 g_locs(p_record_id).quantity := 0;
5199 x_allocated_quantity := 0;
5200 x_remaining_quantity := 0;
5201 x_inserted_record := FALSE;
5202 RETURN;
5203 END IF;
5204
5205 IF p_debug_on THEN
5206 g_trace_recs(p_record_id).serial_number_used_flag := 'Y';
5207 END IF;
5208 END IF;
5209
5210 --If we are factoring in Pick UOM, convert quantity into Pick UOM.
5211 --Then, find the the largest non-decimal quantity in Pick UOM. Convert
5212 --back to primary UOM
5213 -- if Uom code is null, than use primary uom
5214 -- if pick uom = primary uom, skip conversions
5215
5216 l_orig_allocation_quantity := l_allocation_quantity;
5217
5218 IF p_use_pick_uom
5219 AND g_locs(p_record_id).uom_code IS NOT NULL
5220 AND g_locs(p_record_id).uom_code <> p_primary_uom THEN
5221
5222 IF l_debug = 1 THEN
5223 log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
5224 END IF;
5225 --convert from primary uom to pick uom
5226 l_possible_uom_qty := inv_convert.inv_um_convert(
5227 p_inventory_item_id
5228 , NULL
5229 , l_allocation_quantity
5230 , p_primary_uom
5231 , g_locs(p_record_id).uom_code
5232 , NULL
5233 , NULL
5234 );
5235
5236 --if no conversion defined or some error in conversion,
5237 --inv_um_convert returns -99999. In this case, don't carry
5238 --out any more conversion functions. possible quantity
5239 --remains unchanged
5240 IF (l_possible_uom_qty <> -99999) THEN
5241 --don't want to pick fractional amounts of pick uom
5242 l_possible_uom_qty := FLOOR(l_possible_uom_qty);
5243
5244 IF l_debug = 1 THEN
5245 log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
5246 END IF;
5247 --convert back to primary uom
5248 l_allocation_quantity := inv_convert.inv_um_convert(
5249 p_inventory_item_id
5250 , NULL
5251 , l_possible_uom_qty
5252 , g_locs(p_record_id).uom_code
5253 , p_primary_uom
5254 , NULL
5255 , NULL
5256 );
5257 IF l_debug = 1 THEN
5258 log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: ' || l_allocation_quantity);
5259 END IF;
5260 END IF;
5261 END IF;
5262
5263 --populate remaining quantity
5264 x_remaining_quantity := l_orig_allocation_quantity - l_allocation_quantity;
5265 IF l_debug = 1 THEN
5266 log_statement(l_api_name, 'rem_qty', 'remaining_quantity : ' || x_remaining_quantity);
5267 END IF;
5268
5269 IF l_allocation_quantity <= 0 THEN
5270 IF l_debug = 1 THEN
5271 log_statement(l_api_name, 'no_alloc_qty', 'Quantity remaining to allocate. Exiting.');
5272 END IF;
5273 x_allocated_quantity := 0;
5274 x_inserted_record := FALSE;
5275 RETURN;
5276 END IF;
5277
5278 --Lock Serial number, so that no other detailing process
5279 -- can use it.
5280 IF g_locs(p_record_id).serial_number IS NOT NULL THEN
5281 l_found := inv_detail_util_pvt.lock_serial_number(p_inventory_item_id, g_locs(p_record_id).serial_number);
5282
5283 IF l_found = FALSE THEN
5284 IF l_debug = 1 THEN
5285 log_statement(l_api_name, 'lock_sn', 'Could not lock Serial Number. Exiting.');
5286 END IF;
5287
5288 IF p_debug_on THEN
5289 g_trace_recs(p_record_id).serial_number_used_flag := 'N';
5290 END IF;
5291
5292 x_remaining_quantity := g_locs(p_record_id).quantity;
5293 x_allocated_quantity := 0;
5294 x_inserted_record := FALSE;
5295 RETURN;
5296 END IF;
5297
5298 -- add serial number to pl/sql table of detailed serials
5299 inv_detail_util_pvt.add_serial_number(p_inventory_item_id, p_organization_id, g_locs(p_record_id).serial_number, l_serial_index);
5300 END IF;
5301
5302 --If quantity remaining to allocate is greater than 0, update the
5303 --quantity tree and insert the record into WTT
5304 IF p_transaction_uom = p_primary_uom THEN
5305 l_possible_trx_qty := l_allocation_quantity;
5306 ELSE
5307 l_possible_trx_qty :=
5308 inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_allocation_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
5309 END IF;
5310 IF l_debug = 1 THEN
5311 log_statement(l_api_name, 'insert_wtt_rec', 'Inserting wtt recs. Trx Qty: ' || l_possible_trx_qty);
5312 END IF;
5313 -- insert temporary suggestion
5314 INSERT INTO wms_transactions_temp
5315 (
5316 pp_transaction_temp_id
5317 , transaction_temp_id
5318 , type_code
5319 , line_type_code
5320 , transaction_quantity
5321 , primary_quantity
5322 , revision
5323 , lot_number
5324 , lot_expiration_date
5325 , from_subinventory_code
5326 , from_locator_id
5327 , rule_id
5328 , reservation_id
5329 , serial_number
5330 , to_subinventory_code
5331 , to_locator_id
5332 , from_cost_group_id
5333 , to_cost_group_id
5334 , lpn_id
5335 )
5336 VALUES (
5337 wms_transactions_temp_s.NEXTVAL
5338 , p_transaction_temp_id
5339 , p_type_code
5340 , 2 -- line type code is output
5341 , l_possible_trx_qty
5342 , l_allocation_quantity
5343 , g_locs(p_record_id).revision
5344 , g_locs(p_record_id).lot_number
5345 , g_locs(p_record_id).lot_expiration_date
5346 , g_locs(p_record_id).subinventory_code
5347 , g_locs(p_record_id).locator_id
5348 , p_rule_id
5349 , p_reservation_id
5350 , g_locs(p_record_id).serial_number
5351 , p_to_subinventory_code
5352 , p_to_locator_id
5353 , g_locs(p_record_id).cost_group_id
5354 , p_to_cost_group_id
5355 , g_locs(p_record_id).lpn_id
5356 );
5357 IF l_debug = 1 THEN
5358 log_statement(l_api_name, 'finish_insert_wtt', 'Finished inserting wtt recs.');
5359 log_statement(l_api_name, 'alloc_qty', 'Alloc qty: ' || l_allocation_quantity);
5360 END IF;
5361
5362 IF p_debug_on THEN
5363 g_trace_recs(p_record_id).suggested_qty := l_allocation_quantity;
5364 END IF;
5365
5366 x_inserted_record := TRUE;
5367 x_allocated_quantity := l_allocation_quantity;
5368 IF l_debug = 1 THEN
5369 log_statement(l_api_name, 'alloc_qty', 'Allocated quantity: ' || x_allocated_quantity);
5370 log_procedure(l_api_name, 'end', 'End Validate_and_Insert');
5371 END IF;
5372
5373 EXCEPTION
5374 WHEN fnd_api.g_exc_error THEN
5375 x_return_status := fnd_api.g_ret_sts_error;
5376 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5377 --
5378 IF l_debug = 1 THEN
5379 log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
5380 END IF;
5381
5382 WHEN fnd_api.g_exc_unexpected_error THEN
5383 x_return_status := fnd_api.g_ret_sts_unexp_error;
5384 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5385 IF l_debug = 1 THEN
5386 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
5387 END IF;
5388
5389 WHEN OTHERS THEN
5390 x_return_status := fnd_api.g_ret_sts_unexp_error;
5391
5392 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
5393 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
5394 END IF;
5395
5396 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5397 IF l_debug = 1 THEN
5398 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
5399 END IF;
5400
5401 END ValidNinsert;
5402
5403 -- End of bug #4006426 ---
5404
5405
5406 PROCEDURE rollback_consist_allocations(
5407 x_return_status OUT NOCOPY VARCHAR2
5408 , x_msg_count OUT NOCOPY NUMBER
5409 , x_msg_data OUT NOCOPY VARCHAR2
5410 , p_group_id IN NUMBER
5411 , p_tree_id IN NUMBER
5412 , p_type_code IN NUMBER
5413 , p_first_uom_rec IN NUMBER
5414 , p_last_uom_rec IN NUMBER
5415 , p_prev_rec IN NUMBER
5416 , p_next_rec IN NUMBER
5417 , p_debug_on IN BOOLEAN
5418 ) IS
5419 l_api_name VARCHAR2(30) := 'rollback_consist_allocations';
5420 l_current_loc NUMBER;
5421 l_next_rec NUMBER;
5422
5423 l_debug NUMBER;
5424 BEGIN
5425 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
5426 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
5427 END IF;
5428 l_debug := g_debug;
5429
5430 IF l_debug = 1 THEN
5431 log_procedure(l_api_name, 'Start', 'Start Rollback_Consist_Allocations');
5432 -- rollback the changes we've made
5433 log_statement(l_api_name, 'consist_not_enough_qty', 'Not enough quantity in this consistency group. ' || 'Rolling back suggestions');
5434 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
5435 END IF;
5436 inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
5437
5438 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5439 IF l_debug = 1 THEN
5440 log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
5441 END IF;
5442 RAISE fnd_api.g_exc_unexpected_error;
5443 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5444 IF l_debug = 1 THEN
5445 log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
5446 END IF;
5447 RAISE fnd_api.g_exc_error;
5448 END IF;
5449
5450 --put pick UOM records back into the list;
5451 --we need to put this records between after the last
5452 --record that has the current order by string, since
5453 --these recs have the same order by string. The last rec
5454 --with the same order by string is stored in l_prev_rec,
5455 --and the first rec with the next order by string is l_loc_id
5456 --We only do this is the pick uom list is populated
5457 IF l_debug = 1 THEN
5458 log_statement(l_api_name, 'p_first_uom_rec', 'first_uom_rec: ' || p_first_uom_rec);
5459 log_statement(l_api_name, 'p_next_rec', 'next_rec: ' || p_next_rec);
5460 log_statement(l_api_name, 'p_prev_rec', 'prev_rec: ' || p_prev_rec);
5461 END IF;
5462 IF p_first_uom_rec <> 0 THEN
5463 IF p_next_rec IS NULL THEN
5464 l_next_rec := p_prev_rec;
5465
5466 LOOP
5467 EXIT WHEN NVL(l_next_rec, 0) = 0;
5468 EXIT WHEN g_locs(l_next_rec).order_by_string <> g_locs(p_prev_rec).order_by_string;
5469 l_next_rec := g_locs(l_next_rec).next_rec;
5470 END LOOP;
5471 ELSE
5472 l_next_rec := p_next_rec;
5473 END IF;
5474
5475 IF p_prev_rec = 0 THEN
5476 g_consists(p_group_id).first_rec := p_first_uom_rec;
5477 ELSE
5478 g_locs(p_prev_rec).next_rec := p_first_uom_rec;
5479 END IF;
5480
5481 g_locs(p_last_uom_rec).next_rec := l_next_rec;
5482 END IF;
5483
5484 --loop through trace recs, updating recs for this consist
5485 -- group to change consist_string_flag from Y to N
5486 -- and to set suggested quantity back to 0
5487 IF p_debug_on THEN
5488
5489 l_current_loc := g_consists(p_group_id).first_rec;
5490 IF l_debug = 1 THEN
5491 log_statement(l_api_name, 'trace', 'Updating trace records');
5492 log_statement(l_api_name, 'first_loc', 'First rec to update: ' || l_current_loc);
5493 END IF ;
5494
5495 --loop through each record in this consist group
5496 LOOP
5497 EXIT WHEN NVL(l_current_loc, 0) = 0;
5498 --update the trace records
5499 g_trace_recs(l_current_loc).consist_string_flag := 'N';
5500 g_trace_recs(l_current_loc).suggested_qty := 0;
5501 l_current_loc := g_locs(l_current_loc).next_rec;
5502 IF l_debug = 1 THEN
5503 log_statement(l_api_name, 'current_loc', 'Current rec: ' || l_current_loc);
5504 END IF ;
5505 END LOOP;
5506 END IF;
5507
5508 DELETE FROM wms_transactions_temp
5509 WHERE line_type_code = 2
5510 AND type_code = p_type_code;
5511 IF l_debug = 1 THEN
5512 log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
5513 log_procedure(l_api_name, 'End', 'End Rollback_Consist_Allocations');
5514 END IF;
5515 EXCEPTION
5516 WHEN fnd_api.g_exc_error THEN
5517 x_return_status := fnd_api.g_ret_sts_error;
5518 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5519 IF l_debug = 1 THEN
5520 log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
5521 END IF;
5522
5523 WHEN fnd_api.g_exc_unexpected_error THEN
5524 x_return_status := fnd_api.g_ret_sts_unexp_error;
5525 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5526 IF l_debug = 1 THEN
5527 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
5528 END IF;
5529
5530 WHEN OTHERS THEN
5531 x_return_status := fnd_api.g_ret_sts_unexp_error;
5532
5533 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
5534 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
5535 END IF;
5536
5537 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
5538 IF l_debug = 1 THEN
5539 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
5540 END IF;
5541
5542 END rollback_consist_allocations;
5543
5544 PROCEDURE allocate_consist_group(
5545 x_return_status OUT NOCOPY VARCHAR2
5546 , x_msg_count OUT NOCOPY NUMBER
5547 , x_msg_data OUT NOCOPY VARCHAR2
5548 , p_group_id IN NUMBER
5549 , p_needed_quantity IN NUMBER
5550 , p_use_pick_uom IN BOOLEAN
5551 , p_organization_id IN NUMBER
5552 , p_inventory_item_id IN NUMBER
5553 , p_to_subinventory_code IN VARCHAR2
5554 , p_to_locator_id IN NUMBER
5555 , p_to_cost_group_id IN NUMBER
5556 , p_primary_uom IN VARCHAR2
5557 , p_transaction_uom IN VARCHAR2
5558 , p_transaction_temp_id IN NUMBER
5559 , p_type_code IN NUMBER
5560 , p_rule_id IN NUMBER
5561 , p_reservation_id IN NUMBER
5562 , p_tree_id IN NUMBER
5563 , p_debug_on IN BOOLEAN
5564 , p_needed_sec_quantity IN NUMBER -- new
5565 , p_secondary_uom IN VARCHAR2 -- new
5566 , p_grade_code IN VARCHAR2 -- new
5567 , p_lot_divisible_flag IN VARCHAR2 -- new
5568 , x_success OUT NOCOPY BOOLEAN
5569 ) IS
5570 l_api_name VARCHAR2(30) := 'allocate_consist_group';
5571 l_loc_id NUMBER;
5572 l_current_order_by_string VARCHAR2(1000) := NULL;
5573 l_first_rec_uom NUMBER := 0;
5574 l_last_rec_uom NUMBER := 0;
5575 l_last_rec_cur_uom NUMBER := 0;
5576 l_uom_loc_id NUMBER;
5577 l_needed_quantity NUMBER;
5578 l_inserted_record BOOLEAN;
5579 l_allocated_quantity NUMBER;
5580 l_remaining_quantity NUMBER;
5581 l_expected_quantity NUMBER;
5582 l_sec_needed_quantity NUMBER; -- new
5583 l_sec_allocated_quantity NUMBER; -- new
5584 l_sec_remaining_quantity NUMBER; -- new
5585 l_sec_expected_quantity NUMBER; -- new
5586 l_current_loc NUMBER;
5587 l_prev_rec NUMBER := 0;
5588 l_original_needed_quantity NUMBER;
5589 l_uom_index NUMBER;
5590
5591 l_debug NUMBER;
5592 BEGIN
5593 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
5594 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
5595 END IF;
5596 l_debug := g_debug;
5597
5598 IF l_debug = 1 THEN
5599 log_procedure(l_api_name, 'Start', 'Start Allocate_Consist_Group');
5600 END IF;
5601 l_needed_quantity := p_needed_quantity;
5602 l_original_needed_quantity := p_needed_quantity;
5603 l_loc_id := g_consists(p_group_id).first_rec;
5604 x_success := FALSE;
5605
5606 --for each record in the consistency group
5607 LOOP
5608 EXIT WHEN l_loc_id = 0;
5609
5610 --Allocation from pick UOM list if this rec's order string is not
5611 -- equal to previous rec's order string and we are using pick UOM
5612 -- and the pick UOM list is not empty
5613 IF NVL(l_current_order_by_string, '@@@') <> NVL(g_locs(l_loc_id).order_by_string, '@@@')
5614 AND p_use_pick_uom
5615 AND l_first_rec_uom <> 0 THEN
5616 IF l_debug = 1 THEN
5617 log_statement(l_api_name, 'pick_uom', 'Allocating pick UOM records');
5618 END IF;
5619
5620 l_uom_loc_id := l_first_rec_uom;
5621
5622 --for each record in Pick UOM table
5623 LOOP
5624 EXIT WHEN l_uom_loc_id = 0;
5625 l_expected_quantity := g_locs(l_uom_loc_id).quantity;
5626
5627 --validate_and_insert will allocation no more than needed quantity
5628 IF l_needed_quantity < l_expected_quantity THEN
5629 l_expected_quantity := l_needed_quantity;
5630 END IF;
5631 IF l_debug = 1 THEN
5632 log_statement(l_api_name, 'exp_qty', 'Expected Qty: ' || l_expected_quantity);
5633 log_statement(l_api_name, 'val_insert', 'Calling Validate and Insert');
5634 END IF;
5635 --call helper procedure to validate and insert record
5636 validate_and_insert(
5637 x_return_status => x_return_status
5638 , x_msg_count => x_msg_count
5639 , x_msg_data => x_msg_data
5640 , p_record_id => l_uom_loc_id
5641 , p_needed_quantity => l_needed_quantity
5642 , p_use_pick_uom => FALSE
5643 , p_organization_id => p_organization_id
5644 , p_inventory_item_id => p_inventory_item_id
5645 , p_to_subinventory_code => p_to_subinventory_code
5646 , p_to_locator_id => p_to_locator_id
5647 , p_to_cost_group_id => p_to_cost_group_id
5648 , p_primary_uom => p_primary_uom
5649 , p_transaction_uom => p_transaction_uom
5650 , p_transaction_temp_id => p_transaction_temp_id
5651 , p_type_code => p_type_code
5652 , p_rule_id => p_rule_id
5653 , p_reservation_id => p_reservation_id
5654 , p_tree_id => p_tree_id
5655 , p_debug_on => p_debug_on
5656 , p_needed_sec_quantity => l_sec_needed_quantity
5657 , p_secondary_uom => p_secondary_uom
5658 , p_grade_code => p_grade_code
5659 , x_inserted_record => l_inserted_record
5660 , x_allocated_quantity => l_allocated_quantity
5661 , x_remaining_quantity => l_remaining_quantity
5662 , x_sec_allocated_quantity => l_sec_allocated_quantity
5663 , x_sec_remaining_quantity => l_sec_remaining_quantity
5664 );
5665
5666 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5667 IF l_debug = 1 THEN
5668 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
5669 END IF;
5670 RAISE fnd_api.g_exc_unexpected_error;
5671 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5672 IF l_debug = 1 THEN
5673 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
5674 END IF;
5675 RAISE fnd_api.g_exc_error;
5676 END IF;
5677
5678 --If function did not insert full quantity, decrease group qty
5679 IF l_expected_quantity > l_allocated_quantity THEN
5680 IF l_debug = 1 THEN
5681 log_statement(l_api_name, 'did_not_alloc_full', 'Not all of the expected quantity was allocated');
5682 END IF;
5683 g_consists(p_group_id).quantity := g_consists(p_group_id).quantity - (l_expected_quantity - l_allocated_quantity);
5684 IF l_debug = 1 THEN
5685 log_statement(l_api_name, 'new_group_qty', 'New group quantity: ' || g_consists(p_group_id).quantity);
5686 END IF;
5687 g_locs(l_uom_loc_id).quantity := l_allocated_quantity;
5688 g_locs(l_uom_loc_id).secondary_quantity := l_sec_allocated_quantity;
5689
5690 --If group qty is now less than needed qty, rollback and return
5691 IF g_consists(p_group_id).quantity < l_original_needed_quantity THEN
5692 IF l_debug = 1 THEN
5693 log_statement(
5694 l_api_name
5695 , 'rollback_consist'
5696 , 'Not enough quantity in consist group. Calling ' || 'rollback consist allocations.'
5697 );
5698
5699 END IF;
5700
5701 rollback_consist_allocations(
5702 x_return_status => x_return_status
5703 , x_msg_count => x_msg_count
5704 , x_msg_data => x_msg_data
5705 , p_group_id => p_group_id
5706 , p_tree_id => p_tree_id
5707 , p_type_code => p_type_code
5708 , p_first_uom_rec => l_first_rec_uom
5709 , p_last_uom_rec => l_last_rec_uom
5710 , p_prev_rec => l_prev_rec
5711 , p_next_rec => l_loc_id
5712 , p_debug_on => p_debug_on
5713 );
5714
5715 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5716 IF l_debug = 1 THEN
5717 log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
5718 END IF;
5719 RAISE fnd_api.g_exc_unexpected_error;
5720 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5721 IF l_debug = 1 THEN
5722 log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
5723 END IF;
5724 RAISE fnd_api.g_exc_error;
5725 END IF;
5726 IF l_debug = 1 THEN
5727 log_statement(l_api_name, 'after_rollback_consist', 'Rolled back the allocations. Exiting');
5728 END IF;
5729 x_success := FALSE;
5730 RETURN;
5731 END IF;
5732 END IF;
5733
5734 IF p_debug_on THEN
5735 g_trace_recs(l_uom_loc_id).consist_string_flag := 'Y';
5736 END IF;
5737
5738 --Decrease remaining qty to be allocated
5739 l_needed_quantity := l_needed_quantity - l_allocated_quantity;
5740 l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
5741
5742 --if no qty left to detail, exit pick UOM loop
5743 IF l_needed_quantity <= 0 THEN
5744 IF l_debug = 1 THEN
5745 log_statement(l_api_name, 'no_more_qty', 'Allocated all the needed quantity. Exiting.');
5746 END IF;
5747 x_success := TRUE;
5748 RETURN;
5749 END IF;
5750 IF l_debug = 1 THEN
5751 log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
5752 END IF;
5753 l_uom_loc_id := g_locs(l_uom_loc_id).next_rec;
5754 END LOOP;
5755 END IF;
5756
5757 l_current_order_by_string := g_locs(l_loc_id).order_by_string;
5758 -- Call validate_and_insert on current record
5759 -- If group qty is now less than needed qty, rollback and return
5760 -- If remaining qty > 0 and use Pick UOM, add new record to pick uom table
5761 -- decrease remaining qty to be allocated
5762 -- exit when no more qty left to detail
5763 l_expected_quantity := g_locs(l_loc_id).quantity;
5764
5765 --validate_and_insert will allocation no more than needed quantity
5766 IF l_needed_quantity < l_expected_quantity THEN
5767 l_expected_quantity := l_needed_quantity;
5768 END IF;
5769 IF l_debug = 1 THEN
5770 log_statement(l_api_name, 'exp_qty', 'Expected Qty: ' || l_expected_quantity);
5771 log_statement(l_api_name, 'val_insert', 'Calling Validate and Insert');
5772 END IF;
5773 -- Added the following restriction - 5258131
5774 IF (l_needed_quantity > l_expected_quantity AND p_lot_divisible_flag = 'N')
5775 OR (NVL(p_lot_divisible_flag, 'Y') = 'Y') THEN
5776 validate_and_insert(
5777 x_return_status => x_return_status
5778 , x_msg_count => x_msg_count
5779 , x_msg_data => x_msg_data
5780 , p_record_id => l_loc_id
5781 , p_needed_quantity => l_needed_quantity
5782 , p_use_pick_uom => p_use_pick_uom
5783 , p_organization_id => p_organization_id
5784 , p_inventory_item_id => p_inventory_item_id
5785 , p_to_subinventory_code => p_to_subinventory_code
5786 , p_to_locator_id => p_to_locator_id
5787 , p_to_cost_group_id => p_to_cost_group_id
5788 , p_primary_uom => p_primary_uom
5789 , p_transaction_uom => p_transaction_uom
5790 , p_transaction_temp_id => p_transaction_temp_id
5791 , p_type_code => p_type_code
5792 , p_rule_id => p_rule_id
5793 , p_reservation_id => p_reservation_id
5794 , p_tree_id => p_tree_id
5795 , p_debug_on => p_debug_on
5796 , p_needed_sec_quantity => l_sec_needed_quantity
5797 , p_secondary_uom => p_secondary_uom
5798 , p_grade_code => p_grade_code
5799 , x_inserted_record => l_inserted_record
5800 , x_allocated_quantity => l_allocated_quantity
5801 , x_remaining_quantity => l_remaining_quantity
5802 , x_sec_allocated_quantity => l_sec_allocated_quantity
5803 , x_sec_remaining_quantity => l_sec_remaining_quantity
5804 );
5805
5806 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5807 IF l_debug = 1 THEN
5808 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
5809 END IF;
5810 RAISE fnd_api.g_exc_unexpected_error;
5811 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5812 IF l_debug = 1 THEN
5813 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
5814 END IF;
5815 RAISE fnd_api.g_exc_error;
5816 END IF;
5817 END IF; -- End of If 5258131
5818 --If function did not insert full quantity, decrease group qty
5819 IF l_expected_quantity > l_allocated_quantity THEN
5820 IF l_debug = 1 THEN
5821 log_statement(l_api_name, 'did_not_alloc_full', 'Not all of the expected quantity was allocated');
5822 END IF;
5823 g_consists(p_group_id).quantity := g_consists(p_group_id).quantity - (l_expected_quantity - l_allocated_quantity);
5824 IF l_debug = 1 THEN
5825 log_statement(l_api_name, 'new_group_qty', 'New group quantity: ' || g_consists(p_group_id).quantity);
5826 END IF;
5827 g_locs(l_loc_id).quantity := l_allocated_quantity;
5828 g_locs(l_loc_id).secondary_quantity := l_sec_allocated_quantity;
5829
5830 --If group qty is now less than needed qty, rollback and return
5831 IF g_consists(p_group_id).quantity < l_original_needed_quantity THEN
5832 --out of records with cur_consist_string;
5833 -- rollback the changes we've made
5834 IF l_debug = 1 THEN
5835 log_statement(l_api_name, 'rollback_consist', 'Not enough quantity in consist group. Calling ' || 'rollback consist allocations.');
5836 END IF;
5837 rollback_consist_allocations(
5838 x_return_status => x_return_status
5839 , x_msg_count => x_msg_count
5840 , x_msg_data => x_msg_data
5841 , p_group_id => p_group_id
5842 , p_tree_id => p_tree_id
5843 , p_type_code => p_type_code
5844 , p_first_uom_rec => l_first_rec_uom
5845 , p_last_uom_rec => l_last_rec_uom
5846 , p_prev_rec => l_loc_id
5847 , p_next_rec => NULL
5848 , p_debug_on => p_debug_on
5849 );
5850
5851 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
5852 IF l_debug = 1 THEN
5853 log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
5854 END IF;
5855 RAISE fnd_api.g_exc_unexpected_error;
5856 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
5857 IF l_debug = 1 THEN
5858 log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
5859 END IF;
5860 RAISE fnd_api.g_exc_error;
5861 END IF;
5862 IF l_debug = 1 THEN
5863 log_statement(l_api_name, 'after_rollback_consist', 'Rolled back the allocations. Exiting');
5864 END IF;
5865 x_success := FALSE;
5866 RETURN;
5867 END IF;
5868 END IF;
5869
5870 IF p_debug_on THEN
5871 g_trace_recs(l_loc_id).consist_string_flag := 'Y';
5872 END IF;
5873
5874 --Decrease remaining qty to be allocated
5875 l_needed_quantity := l_needed_quantity - l_allocated_quantity;
5876 l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
5877
5878 --if no qty left to detail, exit loop
5879 IF l_needed_quantity <= 0 THEN
5880 x_success := TRUE;
5881 IF l_debug = 1 THEN
5882 log_statement(l_api_name, 'no_more_qty', 'Allocated all the needed quantity. Exiting.');
5883 END IF;
5884 RETURN;
5885 END IF;
5886 IF l_debug = 1 THEN
5887 log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
5888 END IF;
5889 --handle pick UOM
5890 IF l_remaining_quantity > 0
5891 AND p_use_pick_uom THEN
5892 IF l_debug = 1 THEN
5893 log_statement(l_api_name, 'create_pick_uom', 'Create a pick UOM record.Remaining quantity:' || l_remaining_quantity);
5894 END IF;
5895
5896 --create new record if necessary
5897 IF l_remaining_quantity < g_locs(l_loc_id).quantity THEN
5898 g_locs_index := g_locs_index + 1;
5899 g_locs(g_locs_index) := g_locs(l_loc_id);
5900 g_locs(g_locs_index).quantity := l_remaining_quantity;
5901 g_locs(l_loc_id).quantity := g_locs(l_loc_id).quantity - l_remaining_quantity;
5902 l_uom_index := g_locs_index;
5903 l_prev_rec := l_loc_id;
5904 ELSE
5905 --if could not be allocated, remove record from
5906 --current linked list
5907 IF l_prev_rec <> 0 THEN
5908 g_locs(l_prev_rec).next_rec := g_locs(l_loc_id).next_rec;
5909 ELSE
5910 g_consists(p_group_id).first_rec := g_locs(l_loc_id).next_rec;
5911 END IF;
5912
5913 l_uom_index := l_loc_id;
5914 --if rec is removed from link list, prev_rec does not change
5915 END IF;
5916
5917 --set pointers
5918 -- new record is first record in table
5919 IF l_first_rec_uom = 0 THEN
5920 l_first_rec_uom := l_uom_index;
5921 l_last_rec_cur_uom := l_uom_index;
5922 l_last_rec_uom := l_uom_index;
5923 g_locs(l_uom_index).next_rec := 0;
5924 IF l_debug = 1 THEN
5925 log_statement(l_api_name, 'first_rec', 'The saved uom record is the first record in table');
5926 END IF;
5927 -- new record is first record with that uom code
5928 ELSIF g_locs(l_first_rec_uom).uom_code <> g_locs(l_uom_index).uom_code THEN
5929 g_locs(l_uom_index).next_rec := l_first_rec_uom;
5930 l_first_rec_uom := l_uom_index;
5931 l_last_rec_cur_uom := l_uom_index;
5932 IF l_debug = 1 THEN
5933 log_statement(l_api_name, 'first_rec_uom', 'The saved uom record is the first record for uom in table');
5934 END IF;
5935 -- records with this uom code already exist in table
5936 ELSE
5937 g_locs(l_uom_index).next_rec := g_locs(l_last_rec_cur_uom).next_rec;
5938 g_locs(l_last_rec_cur_uom).next_rec := l_uom_index;
5939 l_last_rec_cur_uom := l_uom_index;
5940
5941 IF g_locs(l_uom_index).next_rec = 0 THEN
5942 l_last_rec_uom := l_uom_index;
5943 END IF;
5944 IF l_debug = 1 THEN
5945 log_statement(l_api_name, 'not_first_rec_uom', 'The saved record is not first record for uom in table');
5946 END IF;
5947 END IF;
5948 IF l_debug = 1 THEN
5949 log_statement(l_api_name, 'saving_loc', 'Storing record in uom table');
5950 END IF;
5951
5952 IF p_debug_on THEN
5953 --determine if we created a new record or not
5954 IF l_uom_index = g_locs_index THEN
5955 g_trace_recs(g_locs_index) := g_trace_recs(l_loc_id);
5956 g_trace_recs(l_loc_id).quantity := g_trace_recs(l_loc_id).quantity - l_remaining_quantity;
5957 g_trace_recs(g_locs_index).quantity := l_remaining_quantity;
5958 g_trace_recs(l_loc_id).pick_uom_flag := 'P';
5959 g_trace_recs(g_locs_index).pick_uom_flag := 'N';
5960 ELSE
5961 g_trace_recs(l_loc_id).pick_uom_flag := 'N';
5962 END IF;
5963 END IF;
5964 ELSE
5965 l_prev_rec := l_loc_id;
5966 END IF;
5967
5968 l_loc_id := g_locs(l_loc_id).next_rec;
5969 END LOOP;
5970
5971 IF l_needed_quantity <= 0 THEN
5972 x_success := TRUE;
5973 ELSE
5974 --some sort of error occurred in our calculations;
5975 --we thought that there was enough material in the consistency
5976 --group, but we've allocated all the location records, but we have
5977 --not fulfilled all of the needed quantity;
5978 --Rollback the changes.
5979 IF l_debug = 1 THEN
5980 log_statement(
5981 l_api_name
5982 , 'rollback_consist'
5983 , 'Quantity value on consist group was wrong. There is not enough '
5984 || 'quantity to allocate in this consist group.. Calling '
5985 || 'rollback consist allocations.'
5986 );
5987 END IF;
5988 rollback_consist_allocations(
5989 x_return_status => x_return_status
5990 , x_msg_count => x_msg_count
5991 , x_msg_data => x_msg_data
5992 , p_group_id => p_group_id
5993 , p_tree_id => p_tree_id
5994 , p_type_code => p_type_code
5995 , p_first_uom_rec => 0
5996 , p_last_uom_rec => 0
5997 , p_prev_rec => 0
5998 , p_next_rec => 0
5999 , p_debug_on => p_debug_on
6000 );
6001
6002 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6003 IF l_debug = 1 THEN
6004 log_error(l_api_name, 'uerr_rollback_consist', 'Unexpected error in rollback_consist_allocations');
6005 END IF;
6006 RAISE fnd_api.g_exc_unexpected_error;
6007 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6008 IF l_debug = 1 THEN
6009 log_error(l_api_name, 'err_rollback_consist', 'Error in rollback_consist_allocations');
6010 END IF;
6011 RAISE fnd_api.g_exc_error;
6012 END IF;
6013
6014 x_success := FALSE;
6015 END IF;
6016 IF l_debug = 1 THEN
6017 log_procedure(l_api_name, 'end', 'End Allocate_Consist_Group');
6018 END IF;
6019 EXCEPTION
6020 WHEN fnd_api.g_exc_error THEN
6021 x_return_status := fnd_api.g_ret_sts_error;
6022 x_success := FALSE;
6023 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6024 IF l_debug = 1 THEN
6025 log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
6026 END IF;
6027
6028 WHEN fnd_api.g_exc_unexpected_error THEN
6029 x_return_status := fnd_api.g_ret_sts_unexp_error;
6030 x_success := FALSE;
6031 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6032 IF l_debug = 1 THEN
6033 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
6034 END IF;
6035 WHEN OTHERS THEN
6036 x_return_status := fnd_api.g_ret_sts_unexp_error;
6037 x_success := FALSE;
6038
6039 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6040 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
6041 END IF;
6042
6043 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6044 IF l_debug = 1 THEN
6045 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
6046 END IF;
6047
6048 END allocate_consist_group;
6049
6050 PROCEDURE insert_consist_record(
6051 x_return_status OUT NOCOPY VARCHAR2
6052 , x_msg_count OUT NOCOPY NUMBER
6053 , x_msg_data OUT NOCOPY VARCHAR2
6054 , p_record_id IN NUMBER
6055 , p_needed_quantity IN NUMBER
6056 , p_use_pick_uom IN BOOLEAN
6057 , p_organization_id IN NUMBER
6058 , p_inventory_item_id IN NUMBER
6059 , p_to_subinventory_code IN VARCHAR2
6060 , p_to_locator_id IN NUMBER
6061 , p_to_cost_group_id IN NUMBER
6062 , p_primary_uom IN VARCHAR2
6063 , p_transaction_uom IN VARCHAR2
6064 , p_transaction_temp_id IN NUMBER
6065 , p_type_code IN NUMBER
6066 , p_rule_id IN NUMBER
6067 , p_reservation_id IN NUMBER
6068 , p_tree_id IN NUMBER
6069 , p_debug_on IN BOOLEAN
6070 , p_order_by_rank IN NUMBER
6071 , p_needed_sec_quantity IN NUMBER -- new
6072 , p_secondary_uom IN VARCHAR2 -- new
6073 , p_grade_code IN VARCHAR2 -- new
6074 , x_finished OUT NOCOPY BOOLEAN
6075 , x_remaining_quantity OUT NOCOPY NUMBER
6076 ) IS
6077 l_api_name VARCHAR2(30) := 'insert_consist_record';
6078 l_cur_group NUMBER;
6079 l_hash_size NUMBER;
6080 l_possible_quantity NUMBER;
6081 l_needed_quantity NUMBER;
6082 l_possible_uom_qty NUMBER;
6083 l_sec_possible_quantity NUMBER; -- new
6084 l_sec_needed_quantity NUMBER; -- new
6085 l_sec_possible_uom_qty NUMBER; -- new
6086
6087 l_debug NUMBER;
6088
6089 BEGIN
6090 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
6091 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6092 END IF;
6093 l_debug := g_debug;
6094 IF l_debug = 1 THEN
6095 log_procedure(l_api_name, 'start', 'Start Insert Consist Record');
6096 END IF;
6097
6098 x_finished := FALSE;
6099 -- used in get_hash_value. That procedure works best if
6100 -- hashsize is power of 2
6101 l_hash_size := POWER(2, 15);
6102 --get hash index for this consist string
6103 IF l_debug = 1 THEN
6104 log_statement(l_api_name, 'get_hash_value', 'Calling get_hash_value');
6105 END IF;
6106 l_cur_group := DBMS_UTILITY.get_hash_value(NAME => g_locs(p_record_id).consist_string, base => 1, hash_size => l_hash_size);
6107
6108 --Because the hash function can return the same index for different
6109 -- consist strings, we have to check to see if the group at the index
6110 -- returned above has the same consist string as the current record.
6111 -- If not, look at the next record. Continue on until we find the
6112 -- correct consist group or determine that the group has not been defined
6113 -- yet
6114 LOOP
6115 EXIT WHEN NOT g_consists.EXISTS(l_cur_group);
6116 EXIT WHEN g_consists(l_cur_group).consist_string = g_locs(p_record_id).consist_string;
6117 l_cur_group := l_cur_group + 1;
6118 END LOOP;
6119
6120 --If we need to take Pick UOM into consideration, we need to determine
6121 -- how much of this record is needed
6122 IF p_use_pick_uom THEN
6123 IF l_debug = 1 THEN
6124 log_statement(l_api_name, 'pick_uom', 'Handle Pick UOM');
6125 END IF;
6126
6127 IF p_needed_quantity < g_locs(p_record_id).quantity THEN
6128 l_possible_quantity := p_needed_quantity;
6129 ELSE
6130 l_possible_quantity := g_locs(p_record_id).quantity;
6131 END IF;
6132
6133 IF g_consists.EXISTS(l_cur_group) THEN
6134 l_needed_quantity := p_needed_quantity - g_consists(l_cur_group).quantity;
6135 l_sec_needed_quantity := p_needed_sec_quantity - g_consists(l_cur_group).secondary_quantity;
6136
6137 IF l_possible_quantity > l_needed_quantity THEN
6138 l_possible_quantity := l_needed_quantity;
6139 END IF;
6140 END IF;
6141
6142 IF NVL(g_locs(p_record_id).uom_code, p_primary_uom) <> p_primary_uom THEN
6143 IF l_debug = 1 THEN
6144 log_statement(l_api_name, 'start_uom_conversion', 'Converting from primary uom to pick uom');
6145 END IF;
6146 --convert from primary uom to pick uom
6147 l_possible_uom_qty := inv_convert.inv_um_convert(
6148 p_inventory_item_id
6149 , NULL
6150 , l_possible_quantity
6151 , p_primary_uom
6152 , g_locs(p_record_id).uom_code
6153 , NULL
6154 , NULL
6155 );
6156
6157 --if no conversion defined or some error in conversion,
6158 --inv_um_convert returns -99999. In this case, don't carry
6159 --out any more conversion functions. possible quantity
6160 --remains unchanged
6161 IF (l_possible_uom_qty <> -99999) THEN
6162 --don't want to pick fractional amounts of pick uom
6163 l_possible_uom_qty := FLOOR(l_possible_uom_qty);
6164 IF l_debug = 1 THEN
6165 log_statement(l_api_name, 'to_primary_uom', 'Converting from pick uom to primary uom');
6166 END IF;
6167 --convert back to primary uom
6168 l_possible_quantity := inv_convert.inv_um_convert(
6169 p_inventory_item_id
6170 , NULL
6171 , l_possible_uom_qty
6172 , g_locs(p_record_id).uom_code
6173 , p_primary_uom
6174 , NULL
6175 , NULL
6176 );
6177 IF l_debug = 1 THEN
6178 log_statement(l_api_name, 'after_pick_uom_convert', 'Possible quantity after conversion for pick uom: ' || l_possible_quantity);
6179 END IF;
6180 END IF;
6181 END IF;
6182
6183 x_remaining_quantity := g_locs(p_record_id).quantity - l_possible_quantity;
6184 --don't update the g_loc.quantity here. It'll get updated in Apply.
6185 ELSE
6186 x_remaining_quantity := 0;
6187 l_possible_quantity := g_locs(p_record_id).quantity;
6188 END IF;
6189
6190 IF l_possible_quantity <= 0 THEN
6191 x_finished := FALSE;
6192 RETURN;
6193 END IF;
6194
6195 --If group does exist
6196 IF g_consists.EXISTS(l_cur_group) THEN
6197 IF l_debug = 1 THEN
6198 log_statement(l_api_name, 'group_exists', 'The consist group already exists');
6199 END IF;
6200 --set pointer values
6201 --Bug#4361016.Addedthe below IF Block to make sure that no node has next_rec
6202 --pointer pointing to itself because this causes infinite loop.
6203 IF (g_consists(l_cur_group).last_rec = p_record_id) THEN
6204 g_locs(g_consists(l_cur_group).last_rec).next_rec := 0;
6205 ELSE
6206 g_locs(g_consists(l_cur_group).last_rec).next_rec := p_record_id;
6207 END IF;
6208 g_consists(l_cur_group).last_rec := p_record_id;
6209 --increase group quantity
6210 g_consists(l_cur_group).quantity := g_consists(l_cur_group).quantity + l_possible_quantity;
6211 --If group does not exist
6212 ELSE
6213 IF l_debug =1 THEN
6214 log_statement(l_api_name, 'new_group', 'Creating a new consist group');
6215 END IF;
6216 --create new group
6217 g_consists(l_cur_group).consist_string := g_locs(p_record_id).consist_string;
6218 g_consists(l_cur_group).first_rec := p_record_id;
6219 g_consists(l_cur_group).last_rec := p_record_id;
6220 g_consists(l_cur_group).next_group := 0;
6221 g_consists(l_cur_group).quantity := l_possible_quantity;
6222 g_consists(l_cur_group).order_by_rank := p_order_by_rank;
6223
6224 IF g_first_consist_group = 0 THEN
6225 g_first_consist_group := l_cur_group;
6226 ELSE
6227 g_consists(g_last_consist_group).next_group := l_cur_group;
6228 END IF;
6229
6230 g_last_consist_group := l_cur_group;
6231 END IF;
6232
6233 --If group quantity >= needed qty and the consist group in the first
6234 -- set of records by sort criteria
6235 IF g_consists(l_cur_group).quantity >= p_needed_quantity
6236 AND g_consists(l_cur_group).order_by_rank = g_first_order_by_rank THEN
6237 IF l_debug = 1 THEN
6238 log_statement(l_api_name, 'alloc_group', 'The consist group has enough quantity to allocation. ' || 'Calling allocate_consist_group.');
6239 END IF;
6240 --call allocate_consist_group
6241 allocate_consist_group(
6242 x_return_status => x_return_status
6243 , x_msg_count => x_msg_count
6244 , x_msg_data => x_msg_data
6245 , p_group_id => l_cur_group
6246 , p_needed_quantity => p_needed_quantity
6247 , p_use_pick_uom => p_use_pick_uom
6248 , p_organization_id => p_organization_id
6249 , p_inventory_item_id => p_inventory_item_id
6250 , p_to_subinventory_code => p_to_subinventory_code
6251 , p_to_locator_id => p_to_locator_id
6252 , p_to_cost_group_id => p_to_cost_group_id
6253 , p_primary_uom => p_primary_uom
6254 , p_transaction_uom => p_transaction_uom
6255 , p_transaction_temp_id => p_transaction_temp_id
6256 , p_type_code => p_type_code
6257 , p_rule_id => p_rule_id
6258 , p_reservation_id => p_reservation_id
6259 , p_tree_id => p_tree_id
6260 , p_debug_on => p_debug_on
6261 , p_needed_sec_quantity => l_sec_needed_quantity
6262 , p_secondary_uom => p_secondary_uom
6263 , p_grade_code => p_grade_code
6264 , p_lot_divisible_flag => inv_cache.item_rec.lot_divisible_flag
6265 , x_success => x_finished
6266 );
6267
6268 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6269 IF l_debug = 1 THEN
6270 log_error(l_api_name, 'uerr_alloc_consist_group', 'Unexpected error in allocate_consist_group');
6271 END IF;
6272 RAISE fnd_api.g_exc_unexpected_error;
6273 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6274 IF l_debug = 1 THEN
6275 log_error(l_api_name, 'err_alloc_consist_group', 'Error in allocate_consist_group');
6276 END IF;
6277 RAISE fnd_api.g_exc_error;
6278 END IF;
6279 END IF;
6280
6281 x_return_status := fnd_api.g_ret_sts_success;
6282 IF l_debug = 1 THEN
6283 log_procedure(l_api_name, 'end', 'End Insert_Consist_Record');
6284 END IF;
6285 EXCEPTION
6286 WHEN fnd_api.g_exc_error THEN
6287 x_return_status := fnd_api.g_ret_sts_error;
6288 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6289 IF l_debug = 1 THEN
6290 log_error(l_api_name, 'error', 'Error - ' || x_msg_data);
6291 END IF;
6292 --
6293 WHEN fnd_api.g_exc_unexpected_error THEN
6294 x_return_status := fnd_api.g_ret_sts_unexp_error;
6295 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6296 IF l_debug = 1 THEN
6297 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
6298 END IF;
6299
6300 WHEN OTHERS THEN
6301 x_return_status := fnd_api.g_ret_sts_unexp_error;
6302
6303 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6304 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
6305 END IF;
6306
6307 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
6308 IF l_debug = 1 THEN
6309 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
6310 END IF;
6311
6312 END insert_consist_record;
6313
6314 PROCEDURE invalidate_lpn_group(p_lpn_id IN NUMBER) IS
6315 l_api_name VARCHAR2(30) := 'invalidate_lpn_group';
6316 l_prev_group NUMBER;
6317 l_next_group NUMBER;
6318 l_debug NUMBER;
6319 BEGIN
6320 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
6321 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6322 END IF;
6323 l_debug := g_debug;
6324 IF l_debug = 1 THEN
6325 log_procedure(l_api_name, 'start', 'Start Invalidate_Lpn_Group');
6326 log_statement(l_api_name, 'lpn', 'Invalidating LPN: ' || p_lpn_id);
6327 END IF;
6328 g_lpns(p_lpn_id).total_quantity := -1;
6329 l_prev_group := g_lpns(p_lpn_id).prev_group;
6330 l_next_group := g_lpns(p_lpn_id).next_group;
6331 IF l_debug = 1 THEN
6332 log_statement(l_api_name, 'prev', 'Prev LPN: ' || l_prev_group);
6333 log_statement(l_api_name, 'next', 'Next LPN: ' || l_next_group);
6334 END IF;
6335
6336 IF l_prev_group <> 0 THEN
6337 g_lpns(l_prev_group).next_group := l_next_group;
6338 END IF;
6339
6340 IF l_next_group <> 0 THEN
6341 g_lpns(l_next_group).prev_group := l_prev_group;
6342 END IF;
6343
6344 IF p_lpn_id = g_first_lpn_group THEN
6345 g_first_lpn_group := l_next_group;
6346
6347 IF g_first_lpn_group = 0 THEN
6348 g_first_order_by_rank := NULL;
6349 ELSE
6350 g_first_order_by_rank := g_lpns(g_first_lpn_group).order_by_rank;
6351 END IF;
6352 END IF;
6353
6354 IF g_last_lpn_group = p_lpn_id THEN
6355 g_last_lpn_group := l_next_group;
6356 END IF;
6357 IF l_debug = 1 THEN
6358 log_procedure(l_api_name, 'end', 'End Invalidate_Lpn_Group');
6359 END IF;
6360 END invalidate_lpn_group;
6361
6362 --bug 2349283 - the INV_Validate function updates the locator table,
6363 --thus locking the table. The UpdateLocCapacity function called in
6364 --Apply for putaway rules also updates the locator table, but in a
6365 -- different session. It tries to get a lock on the table, but
6366 --can't. So, we get a deadlock. To resolve this, we make this
6367 -- function a autonomous transaction, and issue a commit at the end.
6368 FUNCTION doprojectcheck(
6369 x_return_status OUT NOCOPY VARCHAR2
6370 , p_locator_id IN NUMBER
6371 , p_project_id IN NUMBER
6372 , p_task_id IN NUMBER
6373 , x_new_locator_id IN OUT NOCOPY NUMBER
6374 , x_exist_locator_id OUT NOCOPY NUMBER --Added bug3237702
6375 )
6376 RETURN BOOLEAN IS
6377 PRAGMA AUTONOMOUS_TRANSACTION;
6378 /*l_locator inv_validate.LOCATOR;
6379 l_org inv_validate.org;
6380 l_sub inv_validate.sub;*/
6381 success NUMBER;
6382 retval BOOLEAN;
6383 BEGIN
6384 x_exist_locator_id := NULL;
6385 -- If the current locator doesn't have the project and task segments
6386 -- populated, then check if another there is a logical locator for this
6387 -- one with the required
6388 -- project and task and return FALSE. If none exists then create one and
6389 -- return TRUE. If the locator has a project and task that is not equal
6390 -- to the required then return FALSE.
6391 /*SELECT *
6392 INTO l_locator
6393 FROM mtl_item_locations
6394 WHERE inventory_location_id = p_locator_id; Commented bug3237702*/
6395 -- Cache for better performance
6396 if nvl(g_locator_id,-9999) <> p_locator_id THEN
6397 SELECT *
6398 INTO g_locator
6399 FROM MTL_ITEM_LOCATIONS
6400 WHERE inventory_location_id = p_locator_id;
6401 end if;
6402 --Added bug3237702 ends
6403
6404 --bug 2797980 - added NVL to handle case where task is NULL
6405 IF (g_locator.project_id = p_project_id AND
6406 NVL(g_locator.task_id,-1) = NVL(p_task_id,-1)) THEN
6407 x_new_locator_id := p_locator_id;
6408 RETURN TRUE;
6409 ELSE
6410 IF g_locator.project_id IS NOT NULL THEN
6411 RETURN FALSE;
6412 END IF;
6413 END IF;
6414
6415 g_locator.inventory_location_id := null;
6416 g_locator.physical_location_id := p_locator_id;
6417 g_locator.project_id := p_project_id;
6418 g_locator.task_id := p_task_id;
6419 g_locator.segment19 := p_project_id;
6420 g_locator.segment20 := p_task_id;
6421
6422 -- Cache for better performance
6423 retval := inv_cache.set_org_rec(g_locator.organization_id);
6424 /*
6425 select *
6426 into l_org
6427 from mtl_parameters
6428 where organization_id = l_locator.organization_id;
6429 */
6430 retval := inv_cache.set_tosub_rec(g_locator.organization_id, g_locator.subinventory_code);
6431 /* select *
6432 into l_sub
6433 from mtl_secondary_inventories
6434 where secondary_inventory_name = l_locator.subinventory_code
6435 and organization_id = l_locator.organization_id;
6436 */
6437 success := INV_Validate.ValidateLocator(
6438 p_locator => g_locator,
6439 p_org => inv_cache.org_rec,
6440 p_sub => inv_cache.tosub_rec,
6441 p_validation_mode => INV_Validate.EXISTS_OR_CREATE,
6442 p_value_or_id => 'I');
6443
6444 COMMIT;
6445
6446 x_new_locator_id := g_locator.inventory_location_id;
6447 if( success = INV_Validate.T and FND_FLEX_KEYVAL.new_combination) then
6448 return TRUE;
6449 END IF;
6450
6451 x_exist_locator_id := g_locator.inventory_location_id;
6452 -- Locator with project segments already exists
6453 return FALSE;
6454 END DoProjectCheck;
6455
6456 --
6457 -- API name : Apply
6458 -- Type : Private
6459 -- Function : Applies a wms rule to the given transaction
6460 -- input parameters and creates recommendations
6461 -- Pre-reqs : Record in WMS_STRATEGY_MAT_TXN_TMP_V uniquely
6462 -- identified by parameters p_transaction_temp_id and
6463 -- p_type_code ( base table for the view is
6464 -- MTL_MATERIAL_TRANSACTIONS_TEMP );
6465 -- At least one transaction detail record in
6466 -- WMS_TRX_DETAILS_TMP_V identified by line type code = 1
6467 -- and parameters p_transaction_temp_id and p_type_code
6468 -- ( base tables are MTL_MATERIAL_TRANSACTIONS_TEMP and
6469 -- WMS_TRANSACTIONS_TEMP, respectively );
6470 -- Rule record has to exist in WMS_RULES_B uniquely
6471 -- identified by parameter p_rule_id;
6472 -- Package WMS_RULE_(RULEID) must exist;
6473 -- If picking, quantity tree has to exist, created through
6474 -- INV_Quantity_Tree_PVT.Create_Tree and uniquely identified
6475 -- by parameter p_tree_id
6476 -- Parameters :
6477 -- p_api_version Standard Input Parameter
6478 -- p_init_msg_list Standard Input Parameter
6479 -- p_commit Standard Input Parameter
6480 -- p_validation_level Standard Input Parameter
6481 -- p_rule_id Identifier of the rule to apply
6482 -- p_type_code Type code of the rule
6483 -- p_partial_success_allowed_flag
6484 -- 'Y' or 'N'
6485 -- p_transaction_temp_id Identifier for the record in view
6486 -- wms_strategy_mat_txn_tmp_v that represents
6487 -- the request for detailing
6488 -- p_organization_id Organization identifier
6489 -- p_inventory_item_id Inventory item identifier
6490 -- p_transaction_uom Transaction UOM code
6491 -- p_primary_uom Primary UOM code
6492 -- p_tree_id Identifier for the quantity tree
6493 --
6494 -- Output Parameters
6495 -- x_return_status Standard Output Parameter
6496 -- x_msg_count Standard Output Parameter
6497 -- x_msg_data Standard Output Parameter
6498 -- x_finished whether the rule has found enough quantity to
6499 -- find a location that completely satisfy
6500 -- the requested quantity (value is 'Y' or 'N')
6501 --
6502 -- Version
6503 -- Currently version is 1.0
6504 --
6505 -- Notes : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
6506 -- This API must be called internally by
6507 -- WMS_Strategy_PVT.Apply only !
6508 --APPLY
6509 PROCEDURE apply(
6510 p_api_version IN NUMBER
6511 , p_init_msg_list IN VARCHAR2
6512 , p_commit IN VARCHAR2
6513 , p_validation_level IN NUMBER
6514 , x_return_status OUT NOCOPY VARCHAR2
6515 , x_msg_count OUT NOCOPY NUMBER
6516 , x_msg_data OUT NOCOPY VARCHAR2
6517 , p_rule_id IN NUMBER
6518 , p_type_code IN NUMBER
6519 , p_partial_success_allowed_flag IN VARCHAR2
6520 , p_transaction_temp_id IN NUMBER
6521 , p_organization_id IN NUMBER
6522 , p_inventory_item_id IN NUMBER
6523 , p_transaction_uom IN VARCHAR2
6524 , p_primary_uom IN VARCHAR2
6525 , p_secondary_uom IN VARCHAR2 -- new
6526 , p_grade_code IN VARCHAR2 -- new
6527 , p_transaction_type_id IN NUMBER
6528 , p_tree_id IN NUMBER
6529 , x_finished OUT NOCOPY VARCHAR2
6530 , p_detail_serial IN BOOLEAN
6531 , p_from_serial IN VARCHAR2
6532 , p_to_serial IN VARCHAR2
6533 , p_detail_any_serial IN NUMBER
6534 , p_unit_volume IN NUMBER
6535 , p_volume_uom_code IN VARCHAR2
6536 , p_unit_weight IN NUMBER
6537 , p_weight_uom_code IN VARCHAR2
6538 , p_base_uom_code IN VARCHAR2
6539 , p_lpn_id IN NUMBER
6540 , p_unit_number IN VARCHAR2
6541 , p_simulation_mode IN NUMBER
6542 , p_project_id IN NUMBER
6543 , p_task_id IN NUMBER
6544 ) IS
6545 -- API standard variables
6546 l_api_version CONSTANT NUMBER := 1.0;
6547 l_api_name CONSTANT VARCHAR2(30) := 'Apply';
6548 -- variables needed for dynamic SQL
6549 l_cursor INTEGER;
6550 l_rows INTEGER;
6551 -- rule dynamic SQL input variables
6552 l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE;
6553 l_revision wms_transactions_temp.revision%TYPE;
6554 l_lot_number wms_transactions_temp.lot_number%TYPE;
6555 l_lot_expiration_date wms_transactions_temp.lot_expiration_date%TYPE;
6556 l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
6557 l_to_subinventory_code wms_transactions_temp.to_subinventory_code%TYPE;
6558 l_subinventory_code wms_transactions_temp.to_subinventory_code%TYPE;
6559 l_from_locator_id wms_transactions_temp.from_locator_id%TYPE;
6560 l_to_locator_id wms_transactions_temp.to_locator_id%TYPE;
6561 l_locator_id wms_transactions_temp.to_locator_id%TYPE;
6562 l_from_cost_group_id wms_transactions_temp.from_cost_group_id%TYPE;
6563 l_to_cost_group_id wms_transactions_temp.to_cost_group_id%TYPE;
6564 l_cost_group_id wms_transactions_temp.to_cost_group_id%TYPE;
6565 l_lpn_id wms_transactions_temp.lpn_id%TYPE;
6566 l_initial_pri_quantity wms_transactions_temp.primary_quantity%TYPE;
6567 -- rule dynamic SQL output variables
6568 l_orevision wms_transactions_temp.revision%TYPE;
6569 l_olot_number wms_transactions_temp.lot_number%TYPE;
6570 l_olot_expiration_date wms_transactions_temp.lot_expiration_date%TYPE;
6571 l_osubinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
6572 l_olocator_id wms_transactions_temp.from_locator_id%TYPE;
6573 l_olocator_id_prev wms_transactions_temp.from_locator_id%TYPE;
6574 l_olocator_id_new wms_transactions_temp.from_locator_id%TYPE;
6575 l_ocost_group_id wms_transactions_temp.from_cost_group_id%TYPE;
6576 l_olpn_id wms_transactions_temp.lpn_id%TYPE;
6577 l_possible_quantity wms_transactions_temp.primary_quantity%TYPE;
6578 l_possible_trx_qty wms_transactions_temp.transaction_quantity%TYPE;
6579 l_sec_possible_quantity wms_transactions_temp.secondary_quantity%TYPE;
6580 l_sec_possible_trx_qty wms_transactions_temp.transaction_quantity%TYPE;
6581 l_reservation_id wms_transactions_temp.reservation_id%TYPE;
6582 -- variables needed for qty tree
6583 l_qoh NUMBER;
6584 l_rqoh NUMBER;
6585 l_qr NUMBER;
6586 l_qs NUMBER;
6587 l_att NUMBER;
6588 l_atr NUMBER;
6589 l_sqoh NUMBER;
6590 l_srqoh NUMBER;
6591 l_sqr NUMBER;
6592 l_sqs NUMBER;
6593 l_satt NUMBER;
6594 l_satr NUMBER;
6595 --
6596 l_rule_func_sql LONG;
6597 l_rule_result NUMBER;
6598 l_dummy NUMBER;
6599 l_pack_exists NUMBER;
6600 l_serial_control_code NUMBER;
6601 l_is_serial_control NUMBER;
6602 l_package_name VARCHAR2(128);
6603 l_msg_data VARCHAR2(240);
6604 l_msg_count NUMBER;
6605 l_rule_id NUMBER;
6606 l_unit_number VARCHAR2(30);
6607 --variables related to pick by UOM
6608 l_uom_code VARCHAR2(3);
6609 l_order_by_string VARCHAR2(1000);
6610 l_consist_string VARCHAR2(1000);
6611 l_cur_order_by_string VARCHAR2(1000) := '-9999999';
6612 l_default_pick_rule NUMBER;
6613 l_default_put_rule NUMBER;
6614 l_allowed VARCHAR2(1);
6615 l_loc_avail_units NUMBER;
6616 l_capacity_updated BOOLEAN;
6617 l_consider_staging_capacity BOOLEAN; --Added bug3237702
6618 l_return_status VARCHAR2(1);
6619 l_consist_exists BOOLEAN;
6620 l_comingle VARCHAR2(1);
6621 l_serial_number VARCHAR2(30);
6622 l_detail_serial NUMBER;
6623 l_found BOOLEAN;
6624 l_first_serial NUMBER;
6625 l_locs_index NUMBER; --index to v_locs table
6626 l_debug_on BOOLEAN;
6627 l_uom_index NUMBER;
6628 l_lpn_controlled_flag NUMBER;
6629 l_check_cg BOOLEAN;
6630 l_restrict_subs_code NUMBER;
6631 l_restrict_locs_code NUMBER;
6632 l_quantity_function NUMBER;
6633 v_current_row t_location_rec;
6634 --added to support allocation mode
6635 l_cur_lpn_group NUMBER;
6636 l_cur_lpn_rec NUMBER;
6637 l_inserted_record BOOLEAN;
6638 l_needed_quantity NUMBER;
6639 l_expected_quantity NUMBER;
6640 l_allocated_quantity NUMBER;
6641 l_remaining_quantity NUMBER;
6642 l_allocation_mode NUMBER;
6643 l_sec_needed_quantity NUMBER; -- new
6644 l_sec_expected_quantity NUMBER; -- new
6645 l_sec_allocated_quantity NUMBER; -- new
6646 l_sec_remaining_quantity NUMBER; -- new
6647 l_grade_code VARCHAR2(150); -- new
6648 l_cur_uom_rec NUMBER;
6649 l_first_uom_rec NUMBER;
6650 l_last_uom_rec NUMBER;
6651 l_finished BOOLEAN;
6652 l_cur_consist_group NUMBER;
6653 l_use_pick_uom BOOLEAN;
6654 l_order_by_rank NUMBER := 0;
6655 l_cur_rec NUMBER;
6656 l_prev_rec NUMBER;
6657 l_next_rec NUMBER;
6658 l_hash_size NUMBER;
6659 l_sub_rsv_type NUMBER;
6660
6661 --added to support pjm
6662 l_project_id NUMBER;
6663 l_oproject_id NUMBER;
6664 l_task_id NUMBER;
6665 l_otask_id NUMBER;
6666 l_input_lpn_id NUMBER;
6667 --- Initilization of Ref cursors for Pick and putaway rules
6668 -- Added to pass into DoProjectCheck new parameter used in other apply procedure Bug3237702
6669 l_dummy_loc NUMBER;
6670 v_pick_cursor wms_rule_pvt.cv_pick_type;
6671 v_put_cursor wms_rule_pvt.cv_put_type;
6672 l_debug NUMBER; -- 1 for debug is on , 0 for debug is off
6673 l_progress VARCHAR2(10); -- local variable to track program progress,
6674 -- especially useful when exception occurs
6675 l_rule_counter INTEGER;
6676
6677 ---- Mat Status Check Variables
6678 l_serial_trx_allowed VARCHAR2(1);
6679 l_sub_loc_lot_trx_allowed VARCHAR2(1);
6680 l_serial_status_id NUMBER;
6681
6682 ---
6683
6684 l_serial_status INV_CACHE.ITEM_REC.serial_status_enabled%TYPE;
6685 l_lot_status INV_CACHE.ITEM_REC.lot_status_enabled%TYPE;
6686
6687 ---- End Mat Status Var
6688
6689 l_lot_divisible_flag VARCHAR2(1);
6690
6691 l_rule_override_flag VARCHAR2(1);
6692 l_lot_control_code NUMBER;
6693 l_revision_control_code NUMBER;
6694 l_grade_control_flag VARCHAR2(1);
6695 l_reservation_is_detailed VARCHAR2(1);
6696 l_sl_rsv_is_detailed VARCHAR2(1);
6697
6698 l_return_value BOOLEAN; -- [ Added ]
6699 ---
6700 l_allocate_serial_flag VARCHAR2(1);
6701 l_custom_select_serials INV_DETAIL_UTIL_PVT.g_serial_row_table_rec;
6702 l_custom_serial_index NUMBER;
6703
6704 -- [ Lot Indivisible Var
6705 l_indiv_lot_allowed VARCHAR2(1); -- [ Added ]
6706 l_max_tolerance NUMBER;
6707 l_min_tolerance NUMBER;
6708
6709 -- LPN Status Project
6710 l_onhand_status_trx_allowed VARCHAR2(1);
6711 l_default_status_id NUMBER ;
6712 -- LPN Status Project
6713
6714 --cursor to get default rule ids from mtl_parameters table
6715 CURSOR l_default_rules IS
6716 SELECT default_wms_picking_rule_id
6717 , default_put_away_rule_id
6718 , rules_override_lot_reservation
6719 FROM mtl_parameters
6720 WHERE organization_id = p_organization_id;
6721
6722 --cursor used to determine if item is lot controlled
6723 CURSOR l_cur_serial IS
6724 SELECT serial_number_control_code
6725 , NVL(restrict_subinventories_code, 2)
6726 , NVL(restrict_locators_code, 2)
6727 , lot_divisible_flag
6728 , lot_control_code
6729 , revision_qty_control_code
6730 , grade_control_flag
6731 FROM mtl_system_items
6732 WHERE organization_id = p_organization_id
6733 AND inventory_item_id = p_inventory_item_id;
6734
6735 --cursor used to determine if the rule package exists
6736 CURSOR l_pack_gen IS
6737 SELECT COUNT(object_name)
6738 FROM user_objects
6739 WHERE object_name = l_package_name;
6740
6741 --cursor used to determine if suggestions should be minimized
6742 -- for this rule. This flag affects how the Pick UOM functionality
6743 -- works.
6744 CURSOR c_allocation_mode IS
6745 SELECT allocation_mode_id
6746 , qty_function_parameter_id
6747 FROM wms_rules_b
6748 WHERE rule_id = l_rule_id;
6749
6750 --cursor used to determine if rule has any consistency requirements
6751 CURSOR l_consist IS
6752 SELECT consistency_id
6753 FROM wms_rule_consistencies
6754 WHERE rule_id = l_rule_id;
6755
6756 --cursor to get lpn controlled flag from subinventory
6757 CURSOR c_subinventory IS
6758 SELECT lpn_controlled_flag, reservable_type
6759 FROM mtl_secondary_inventories
6760 WHERE organization_id = p_organization_id
6761 AND secondary_inventory_name = l_osubinventory_code;
6762
6763 --cursor to get the total quantity for the LPN
6764 CURSOR c_lpn_quantity IS
6765 SELECT SUM(primary_transaction_quantity)
6766 FROM mtl_onhand_quantities_detail
6767 WHERE lpn_id = v_current_row.lpn_id;
6768
6769 --Bug 5251221, cursor to get the serials which are allocated for the current rule
6770 CURSOR l_get_serial IS
6771 SELECT serial_number FROM wms_transactions_temp
6772 WHERE rule_id = l_rule_id;
6773
6774
6775 BEGIN
6776 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
6777 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6778 END IF;
6779 l_debug := g_debug;
6780 l_progress := 10;
6781
6782 -- debugging portion
6783 -- can be commented ut for final code
6784 if nvl(inv_cache.is_pickrelease, FALSE) THEN
6785 If (l_debug = 1) then
6786 log_event(l_api_name, 'Check if Pick Release', 'True');
6787 End if;
6788 l_consider_staging_capacity := FALSE;
6789 else
6790 If (l_debug = 1) then
6791 log_event(l_api_name, 'Check if Pick Release', 'False');
6792 End if;
6793 l_consider_staging_capacity := TRUE;
6794 end if;
6795
6796 IF l_debug = 1 THEN
6797 log_procedure(l_api_name, 'start', 'Start wms_rule_pvt.Apply');
6798 log_event(l_api_name, 'Apply ', 'org_id '||p_organization_id);
6799 log_event(l_api_name, 'Apply ', 'item_id '||p_inventory_item_id);
6800 END IF;
6801 -- end of debugging section
6802 --
6803 -- Standard start of API savepoint
6804 SAVEPOINT applyrulesp;
6805
6806 -- Standard call to check for call compatibility
6807 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
6808 RAISE fnd_api.g_exc_unexpected_error;
6809 END IF;
6810
6811 -- Initialize message list if p_init_msg_list is set to TRUE
6812 IF fnd_api.to_boolean(p_init_msg_list) THEN
6813 fnd_msg_pub.initialize;
6814 END IF;
6815
6816 -- LPN Status Project
6817 if (inv_cache.set_org_rec(p_organization_id)) then
6818 l_default_status_id := nvl(inv_cache.org_rec.default_status_id,-1);
6819 IF l_debug = 1 THEN
6820 log_statement(l_api_name, 'Value of l_default_status_id: ', l_default_status_id);
6821 END IF;
6822 end if;
6823 -- LPN Status Project
6824
6825 --
6826 -- Initialize API return status to success
6827 x_return_status := fnd_api.g_ret_sts_success;
6828 --
6829 -- Initialize functional return status to completed
6830 x_finished := fnd_api.g_true;
6831
6832 --
6833 -- Validate input parameters and pre-requisites, if validation level
6834 -- requires this
6835 IF p_validation_level <> fnd_api.g_valid_level_none THEN
6836 IF p_type_code IS NULL
6837 OR p_type_code = fnd_api.g_miss_num THEN
6838 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6839 fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
6840 fnd_msg_pub.ADD;
6841
6842 IF l_debug = 1 THEN
6843 log_error_msg(l_api_name, 'type_code_missing');
6844 END IF;
6845
6846 END IF;
6847
6848 RAISE fnd_api.g_exc_error;
6849 END IF;
6850
6851 /* get the org defaults */
6852 IF l_debug = 1 THEN
6853 log_statement(l_api_name,'no_rule','Getting default rule at org level');
6854 END IF;
6855 OPEN l_default_rules;
6856 FETCH l_default_rules
6857 INTO l_default_pick_rule
6858 , l_default_put_rule
6859 , l_rule_override_flag
6860 ;
6861 IF l_default_rules%NOTFOUND THEN
6862 IF l_debug = 1 THEN
6863 log_statement(l_api_name, 'org_not_found', 'Organization not found');
6864 END IF;
6865 l_default_pick_rule := NULL;
6866 l_default_put_rule := NULL;
6867 END IF;
6868 CLOSE l_default_rules;
6869
6870 --changed by jcearley on 11/22/99, b/c a null rule_id is now allowed
6871 -- if rule_id is null, use default rule (0 for put away, 1 for pick)
6872 IF p_rule_id IS NULL
6873 OR p_rule_id = fnd_api.g_miss_num THEN
6874 --query org parameters to get user's default rule
6875 --if default rule not defined, use default seeded rule
6876 IF p_type_code = 1 THEN --put away
6877 l_rule_id := l_default_put_rule;
6878 IF l_rule_id IS NULL THEN
6879 IF l_debug = 1 THEN
6880 log_statement(l_api_name, 'no_org_rule_put',
6881 'Did not find org default put away rule');
6882 END IF;
6883 l_rule_id := 10;
6884 END IF;
6885 ELSE --pick
6886 l_rule_id := l_default_pick_rule;
6887 IF l_rule_id IS NULL THEN
6888 IF l_debug = 1 THEN
6889 log_statement(l_api_name, 'no_org_rule_put',
6890 'Did not find org default put away rule');
6891 END IF;
6892 l_rule_id := 2;
6893 END IF;
6894 END IF;
6895 IF l_debug = 1 THEN
6896 log_statement(l_api_name, 'default_rule',
6897 'Rule being used: ' || l_rule_id);
6898 END IF;
6899 ELSE
6900 l_rule_id := p_rule_id;
6901 END IF;
6902
6903 IF p_partial_success_allowed_flag IS NULL
6904 OR p_partial_success_allowed_flag = fnd_api.g_miss_char THEN
6905 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6906 fnd_message.set_name('WMS', 'WMS_PARTIAL_SUCC_FLAG_MISS');
6907 IF l_debug = 1 THEN
6908 log_error_msg(l_api_name, 'partial_succ_flag_missing');
6909 END IF;
6910 fnd_msg_pub.ADD;
6911 END IF;
6912 RAISE fnd_api.g_exc_error;
6913 END IF;
6914
6915 IF p_transaction_temp_id IS NULL
6916 OR p_transaction_temp_id = fnd_api.g_miss_num THEN
6917 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6918 fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
6919 fnd_msg_pub.ADD;
6920 IF l_debug = 1 THEN
6921 log_error_msg(l_api_name, 'trx_req_line_id_missing');
6922 END IF;
6923 END IF;
6924 RAISE fnd_api.g_exc_error;
6925 END IF;
6926
6927 IF p_organization_id IS NULL
6928 OR p_organization_id = fnd_api.g_miss_num THEN
6929 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6930 fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
6931 fnd_msg_pub.ADD;
6932 IF l_debug = 1 THEN
6933 log_error_msg(l_api_name, 'org_id_missing');
6934 END IF;
6935 END IF;
6936
6937 RAISE fnd_api.g_exc_error;
6938 END IF;
6939
6940 IF p_inventory_item_id IS NULL
6941 OR p_inventory_item_id = fnd_api.g_miss_num THEN
6942 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6943 fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
6944 fnd_msg_pub.ADD;
6945 IF l_debug = 1 THEN
6946 log_error_msg(l_api_name, 'item_id_missing');
6947 END IF;
6948 END IF;
6949
6950 RAISE fnd_api.g_exc_error;
6951 END IF;
6952
6953 IF p_type_code = 2
6954 AND (p_tree_id IS NULL
6955 OR p_tree_id = fnd_api.g_miss_num
6956 ) THEN
6957 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
6958 fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
6959 fnd_msg_pub.ADD;
6960 IF l_debug = 1 THEN
6961 log_error_msg(l_api_name, 'qty_tree_id_missing');
6962 END IF;
6963 END IF;
6964 RAISE fnd_api.g_exc_error;
6965 END IF;
6966 END IF;
6967
6968 --inv_pp_debug.send_message_to_pipe('finished validations and qty tree init');
6969 --
6970 -- backup qty tree
6971 IF p_type_code = 2 THEN
6972 IF l_debug = 1 THEN
6973 log_statement(l_api_name, 'PICK','PICK');
6974 log_statement(l_api_name, 'backup_tree',
6975 'Calling inv_quantity_tree_pvt.backup_tree');
6976 END IF;
6977 inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
6978 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
6979 IF l_debug = 1 THEN
6980 log_statement(l_api_name, 'backup_tree_unexp_err',
6981 'Unexpected error from inv_quantity_tree_pvt.backup_tree');
6982 END IF;
6983 RAISE fnd_api.g_exc_unexpected_error;
6984 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
6985 IF l_debug = 1 THEN
6986 log_statement(l_api_name, 'backup_tree_err',
6987 'Error from inv_quantity_tree_pvt.backup_tree');
6988 END IF;
6989 RAISE fnd_api.g_exc_error;
6990 END IF;
6991 --does the rule have any consistency restrictions?
6992 OPEN l_consist;
6993 FETCH l_consist INTO l_dummy;
6994 IF l_consist%NOTFOUND THEN
6995 l_consist_exists := FALSE;
6996 IF l_debug = 1 THEN
6997 log_statement(l_api_name, 'consist_exist_false',
6998 'Consistencies do not exist');
6999 END IF;
7000 ELSE
7001 l_consist_exists := TRUE;
7002 IF l_debug = 1 THEN
7003 log_statement(l_api_name, 'consist_exist_true', 'Cosistencies exist');
7004 END IF;
7005 END IF;
7006 CLOSE l_consist;
7007 END IF;
7008 --log_statement(l_api_name, 'allocation_mode', 'consist done');
7009 --
7010 --Get allocation mode
7011 OPEN c_allocation_mode;
7012 FETCH c_allocation_mode INTO l_allocation_mode, l_quantity_function;
7013
7014 --log_statement(l_api_name, 'allocation_mode', 'allocation_mode '||l_allocation_mode);
7015
7016 IF c_allocation_mode%NOTFOUND
7017 OR l_allocation_mode IS NULL THEN
7018 --by default, make allocation mode 3
7019 l_allocation_mode := 3;
7020 END IF;
7021
7022 CLOSE c_allocation_mode;
7023
7024
7025 IF l_allocation_mode IN (3, 4, 5) THEN --value = 5 added for R12.1 replenishment project
7026 l_use_pick_uom := TRUE;
7027 ELSE
7028 l_use_pick_uom := FALSE;
7029 END IF;
7030
7031 -- make sure, everything is clean
7032 freeglobals;
7033 wms_parameter_pvt.clearcache;
7034 --log_statement(l_api_name, 'apply', 'all cache cleared ');
7035 --
7036 g_trace_recs.DELETE;
7037 l_debug_on := isruledebugon(p_simulation_mode);
7038 -- - [
7039 --query items table to see if item is serial controlled (picking) or if it
7040 --restricts subs or locators (putaway)
7041
7042 /* OPEN l_cur_serial;
7043 FETCH l_cur_serial
7044 INTO l_serial_control_code
7045 , l_restrict_subs_code
7046 , l_restrict_locs_code
7047 , l_lot_divisible_flag
7048 , l_lot_control_code
7049 , l_revision_control_code
7050 , l_grade_control_flag
7051 ;
7052
7053 log_statement(l_api_name, 'apply', 'fecth iitem info done ');
7054 IF l_cur_serial%NOTFOUND THEN
7055 l_serial_control_code := 1;
7056 l_restrict_subs_code := 2;
7057 l_restrict_locs_code := 2;
7058 END IF;
7059
7060 CLOSE l_cur_serial; */
7061
7062
7063 -- Removed the above code and added the following variables for performances
7064
7065 l_return_value := INV_CACHE.set_item_rec(
7066 p_organization_id,
7067 p_inventory_item_id);
7068 If NOT l_return_value Then
7069 If l_debug = 1 then
7070 log_statement(l_api_name, '-', 'Error setting from sub cache');
7071 end if;
7072 RAISE fnd_api.g_exc_unexpected_error;
7073 End If;
7074
7075 l_serial_control_code := NVL(inv_cache.item_rec.serial_number_control_code,1);
7076 l_restrict_subs_code := NVL(inv_cache.item_rec.restrict_subinventories_code, 2);
7077 l_restrict_locs_code := NVL(inv_cache.item_rec.restrict_locators_code, 2);
7078 l_lot_divisible_flag := inv_cache.item_rec.lot_divisible_flag;
7079 l_lot_control_code := inv_cache.item_rec.lot_control_code;
7080 l_revision_control_code := inv_cache.item_rec.revision_qty_control_code;
7081 l_grade_control_flag := inv_cache.item_rec.grade_control_flag;
7082
7083 -- ]
7084
7085 -- Only detail serial numbers if they are prespecified or entered
7086 -- at inventory receipt for this item.
7087 IF p_type_code = 2 THEN --pick
7088 IF l_serial_control_code IN (2, 5) THEN
7089 l_is_serial_control := 1;
7090 ELSE
7091 l_is_serial_control := 0;
7092 END IF;
7093 ELSE
7094 l_is_serial_control := 0;
7095 END IF;
7096
7097 IF p_detail_serial = TRUE THEN
7098 l_detail_serial := 1;
7099 ELSE
7100 l_detail_serial := 0;
7101 END IF;
7102 ------------ Added new code -----
7103
7104
7105 -- Logic to improve the performance for Material Status Checks
7106 -- Getting Values from INV CACHE and setting the l_detail_serial flag based on the following algoritham
7107 -- Based on the l_detail_falg, Serial_material status would be checked inside the Rule packages or
7108 -- Rules Engine API.
7109 -- ** Serial Mat.Status Check inside Rule Sql(R) / Engine (E)
7110 /*------------------------------------------------------------------------------------------------
7111 Serial Serial Serial MSN Group By Serial Mat.Status l_detail_serial
7112 Allowed Status Rule Objs to be used LOT/SUb/Loc Required Check in RuleSql
7113 -------------------------------------------------------------------------------------------------
7114 Y Y Y Y N Y Engine 1
7115 Y Y N Y N Y Engine 1
7116 Y N Y Y N N - 2
7117 Y N N Y N N - 2
7118 --------------------------------------------------------------------------------------------------
7119 N Y Y Y Y Y Rule 3
7120 N Y N Y Y Y Rule 3
7121 N N Y Y Y N - 4
7122 N N N N(MOQD) N N - 0
7123 --------------------------------------------------------------------------------------------------*/
7124 IF l_is_serial_control = 1 THEN
7125 l_serial_status := INV_CACHE.ITEM_REC.serial_status_enabled;
7126 --l_serial_status_id := INV_CACHE.ITEM_REC.serial_status_id;
7127 l_lot_status := INV_CACHE.ITEM_REC.lot_status_enabled;
7128
7129 IF l_detail_serial = 1 THEN
7130 IF NVL(l_serial_status, 'N') = 'Y' THEN
7131 l_detail_serial := 1;
7132 ELSE
7133 l_detail_serial := 2;
7134 END IF;
7135 ELSE
7136 IF NVL(l_serial_status, 'N') = 'Y' THEN
7137 l_detail_serial := 3;
7138 ELSE
7139 l_detail_serial := 0;
7140 END IF;
7141 END IF;
7142
7143 --- Checking, if any Serial object based attributes used by any Picking rules
7144 IF l_detail_serial = 0 THEN
7145 IF IsSerialObjectUsed( p_organization_id ) THEN
7146 l_detail_serial := 4;
7147 END IF;
7148 END IF;
7149 END IF;
7150 --
7151 -- [ If the org level flag is set to use Custom logic for Serial numbers,
7152 -- the MSNT is used but grouped by sub/loc
7153 If p_type_code = 2 THEN
7154 l_allocate_serial_flag := inv_cache.org_rec.allocate_serial_flag;
7155 END IF;
7156
7157 IF l_allocate_serial_flag = 'C' Then
7158 l_detail_serial := 4;
7159 End If;
7160 -- ]
7161 IF l_debug = 1 THEN
7162 log_statement(l_api_name, 'l_detail_serial', l_detail_serial);
7163 log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
7164 log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
7165 END IF;
7166 /*
7167 --- Bug 5504458
7168 --- Added the following code to handle the entire LPN mode as 'loose LPN'
7169 --- for serial controlled item with serial allocation on
7170 --- Not sure if it correct or not because I don't see the business case.
7171 IF l_detail_serial in (1,2) and l_allocation_mode = 1 THEN
7172 l_allocation_mode := 2;
7173 End if;
7174
7175 --- End of 5504458
7176 */
7177
7178 --get the name of the rule package
7179 getpackagename(l_rule_id, l_package_name);
7180 -- Initialize the pointer to the first trx detail input line
7181 wms_re_common_pvt.initinputpointer;
7182 --
7183 IF l_debug = 1 THEN
7184 log_statement(l_api_name, 'start_input_loop',
7185 'Starting loop through input lines');
7186 END IF;
7187 -- Loop through all the trx detail input lines
7188 WHILE TRUE LOOP
7189 --
7190 l_max_tolerance := 0;
7191 -- Get the next trx detail input line
7192 wms_re_common_pvt.getnextinputline(
7193 l_pp_transaction_temp_id
7194 , l_revision
7195 , l_lot_number
7196 , l_lot_expiration_date
7197 , l_from_subinventory_code
7198 , l_from_locator_id
7199 , l_from_cost_group_id
7200 , l_to_subinventory_code
7201 , l_to_locator_id
7202 , l_to_cost_group_id
7203 , l_needed_quantity
7204 , l_sec_needed_quantity
7205 , l_grade_code
7206 , l_reservation_id
7207 , l_serial_number -- [ new code ]
7208 , l_lpn_id
7209 );
7210 EXIT WHEN l_pp_transaction_temp_id IS NULL;
7211 -- [ roll up the rem_tol_qty for Lot inadvisable items , for picking
7212 -- This logic is not implemented . To be implemented in feature ]
7213
7214 IF l_debug = 1 THEN
7215 log_statement(l_api_name, 'input_rec', 'Got next input line');
7216 log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
7217 log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
7218 log_statement(l_api_name, 'input_serial', 'serial number:' || l_serial_number);
7219 log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
7220 log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
7221 log_statement(l_api_name, 'input_cg', 'cg:' || l_from_cost_group_id);
7222 log_statement(l_api_name, 'input_tsub', 'tsub:' || l_to_subinventory_code);
7223 log_statement(l_api_name, 'input_tloc', 'tloc:' || l_to_locator_id);
7224 log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
7225 log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
7226 log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
7227 log_statement(l_api_name, 'input_qty', 'sec_qty:' || l_sec_needed_quantity);
7228
7229 END IF;
7230 -- [ compute line level tolerances for lot indivisible item for non-reserved lines
7231 -- and the l_needed qty is adjusted to max allowed qty based on the max tol Qty
7232 -- If the tol qty is zero, then the l_needed qty remains unchanged. ]
7233 IF l_lot_divisible_flag = 'N'
7234 and l_lot_control_code <> 1
7235 and p_type_code = 2
7236 and l_reservation_id is null THEN
7237 l_max_tolerance := g_max_tolerance ;
7238 l_needed_quantity := l_needed_quantity + l_max_tolerance;
7239 ELSIF p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
7240 IF g_max_tolerance < 0 THEN
7241 l_max_tolerance := g_max_tolerance;
7242 l_needed_quantity := l_needed_quantity + l_max_tolerance;
7243 ELSIF l_allocation_mode in (1, 5) THEN
7244 l_max_tolerance := g_max_tolerance;
7245 l_needed_quantity := l_needed_quantity + l_max_tolerance;
7246 ELSE
7247 l_max_tolerance := 0;
7248 END IF;
7249 ELSE
7250 l_max_tolerance := 0;
7251 END IF;
7252 IF l_debug = 1 THEN
7253 log_statement(l_api_name, 'New Needed Qty with tolerance ', 'qty:' || l_needed_quantity);
7254 END IF;
7255
7256 IF ((p_project_id IS NOT NULL) AND (l_to_locator_id IS NOT NULL) AND (p_type_code = 1)) THEN
7257 --bug 2400549 - for WIP backflush transfer putaway,
7258 --always use the locator specified on the move order line, even
7259 --if that locator is from common stock (not project)
7260 --Bug 2666620: BackFlush MO Type Removed. It is now 5. Moreover Txn Action ID is 2 which is
7261 --already handled.
7262 IF NOT (wms_engine_pvt.g_move_order_type = 5 AND wms_engine_pvt.g_transaction_action_id = 2) THEN
7263 IF l_debug = 1 THEN
7264 log_statement(l_api_name, 'do_project1', 'Calling do project check');
7265 END IF;
7266 IF doprojectcheck(l_return_status, l_to_locator_id, p_project_id, p_task_id, l_to_locator_id, l_dummy_loc) THEN
7267 IF l_debug = 1 THEN
7268 log_statement(l_api_name, 'do_project1_success', 'Do Project Check passed');
7269 END IF;
7270 NULL;
7271 END IF;
7272 END IF;
7273 END IF;
7274
7275 --
7276 -- Save the initial input qty for later usage
7277 l_initial_pri_quantity := l_needed_quantity;
7278 l_input_lpn_id := l_lpn_id;
7279
7280 IF p_type_code = 2 THEN
7281 --check for null values. NULL produces error in stored procedure,
7282 -- so we treat -9999 as NULL;
7283 -- since revision is varchar(3), use -99
7284 -- we only want to overwrite revision and lot for pick rules, since
7285 -- we use these values in putaway.
7286 IF (l_revision IS NULL) THEN
7287 l_revision := '-99';
7288 END IF;
7289 IF (l_lot_number IS NULL) THEN
7290 l_lot_number := '-9999';
7291 END IF;
7292 END IF;
7293
7294 IF (p_type_code = 2) THEN --pick
7295 l_subinventory_code := l_from_subinventory_code;
7296 l_locator_id := l_from_locator_id;
7297 l_cost_group_id := l_from_cost_group_id;
7298 ELSE --put away
7299 l_subinventory_code := l_to_subinventory_code;
7300 l_locator_id := l_to_locator_id;
7301 l_cost_group_id := l_to_cost_group_id;
7302 END IF;
7303
7304 IF (l_subinventory_code IS NULL) THEN
7305 l_subinventory_code := '-9999';
7306 END IF;
7307
7308 IF (l_locator_id IS NULL) THEN
7309 l_locator_id := -9999;
7310 END IF;
7311
7312 IF (l_cost_group_id IS NULL) THEN
7313 l_cost_group_id := -9999;
7314 END IF;
7315
7316 IF (l_lpn_id IS NULL) THEN
7317 l_lpn_id := -9999;
7318 END IF;
7319
7320 IF (p_project_id IS NULL) THEN
7321 l_project_id := -9999;
7322 ELSE
7323 l_project_id := p_project_id;
7324 END IF;
7325
7326 IF (p_task_id IS NULL) THEN
7327 l_task_id := -9999;
7328 ELSE
7329 l_task_id := p_task_id;
7330 END IF;
7331
7332 IF (p_unit_number IS NULL) THEN
7333 l_unit_number := '-9999';
7334 ELSE
7335 l_unit_number := p_unit_number;
7336 END IF;
7337
7338 IF l_debug = 1 THEN
7339 log_statement(l_api_name, 'Set value for l_sl_rsv_is_detailed', 'if serial number is reserved');
7340 log_statement(l_api_name, 'l_serial_number', l_serial_number);
7341 log_statement(l_api_name, 'l_rule_id', l_rule_id);
7342 log_statement(l_api_name, 'l_reservation_id', l_reservation_id);
7343
7344 END IF;
7345 -- [ new code to check the serial number reservation ]
7346
7347 l_sl_rsv_is_detailed := 'N' ;
7348 IF NVL(l_serial_number, '-999') <> '-999' AND ( NVL(l_rule_id, 777) = -999 or NVL(l_reservation_id , 999) <> 999 ) THEN
7349 l_sl_rsv_is_detailed := 'Y' ;
7350 END IF;
7351
7352
7353 /* LG. Check the txn dtl lines with the control flags, then check the override rule flag
7354 * from the mtl_parameters, allocate directly if res is fully detailed.
7355 */
7356 --[
7357 -- If the Serial Number is reserved, Rules are not called and following code is called
7358 --]
7359 IF ( l_rule_override_flag = 'Y' OR l_sl_rsv_is_detailed = 'Y' ) and p_type_code = 2 THEN
7360 IF l_debug = 1 THEN
7361 log_statement(l_api_name,'detailed', 'Rule Override flag is set ');
7362 END IF;
7363 -- Validate the txn detail
7364 l_reservation_is_detailed := 'Y';
7365 IF (wms_engine_pvt.g_org_loc_control IN (2, 3) -- org level
7366 OR wms_engine_pvt.g_sub_loc_control IN (2, 3) -- sub level
7367 OR (wms_engine_pvt.g_sub_loc_control = 5 -- item level
7368 AND wms_engine_pvt.g_item_loc_control IN (2, 3)
7369 )
7370 )
7371 THEN
7372 IF l_debug = 1 THEN
7373 log_statement(l_api_name,'detailed', 'Locator should be there '|| l_locator_id);
7374 END IF;
7375 IF nvl(l_locator_id,-9999) = -9999 THEN
7376 l_reservation_is_detailed := 'N';
7377 END IF;
7378 END IF;
7379
7380 IF l_lot_control_code <> 1 THEN -- lot controlled
7381 IF l_debug = 1 THEN
7382 log_statement(l_api_name,'detailed', 'Lot should be there'|| l_lot_number);
7383 END IF;
7384 IF nvl(l_lot_number,'-9999') = '-9999' THEN
7385 l_reservation_is_detailed := 'N';
7386 END IF;
7387 END IF;
7388
7389 IF l_revision_control_code <> 1 THEN -- revision controlled
7390 IF l_debug = 1 THEN
7391 log_statement(l_api_name,'detailed', 'Revision should be there'|| l_Revision);
7392 END IF;
7393 IF nvl(l_revision,'-99') = '-99' THEN
7394 l_reservation_is_detailed := 'N';
7395 END IF;
7396 END IF;
7397 /*IF l_grade_control_flag = 'Y' THEN -- grade controlled
7398 IF l_debug = 1 THEN
7399 log_statement(l_api_name,'detailed', 'Grade should be there'|| l_grade_code);
7400 END IF;
7401 IF nvl(l_grade_code,'-9999') = '-9999' THEN
7402 l_reservation_is_detailed := 'N';
7403 END IF;
7404 END IF;*/
7405
7406 IF ( l_reservation_is_detailed = 'Y' OR l_sl_rsv_is_detailed = 'Y' ) THEN
7407 IF l_debug = 1 THEN
7408 log_statement(l_api_name,'detailed', 'Reservation is fully detailed, validate and insert');
7409 END IF;
7410
7411 -- [Checking the material status for serial /lots
7412 -- OPM Convergence project missed the mat-status check
7413 -- Logic : if the lot or serial number's material status is not allowed for transactions
7414 -- even though there is detailed reservations exist in the system, rule engine will
7415 -- ignore the record
7416 -- The mat-status is applicable for serial reserved items too ]
7417
7418 l_sub_loc_lot_trx_allowed := 'Y';
7419 l_serial_trx_allowed := 'Y';
7420 l_serial_status_id := 0;
7421 IF ((l_serial_number IS NOT NULL) AND (NVL(l_serial_status, 'N') = 'Y')) THEN
7422 select status_id
7423 into l_serial_status_id
7424 from mtl_serial_numbers
7425 where inventory_item_id = p_inventory_item_id
7426 and current_organization_id = p_organization_id
7427 and serial_number = l_serial_number;
7428
7429 l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
7430 p_transaction_type_id
7431 ,p_organization_id
7432 ,p_inventory_item_id
7433 ,l_serial_status_id) ;
7434 END IF;
7435 -- Bug 4756156
7436 -- IF ((l_lot_number IS NOT NULL) AND (nvl(l_lot_status, 'Y') = 'Y')) THEN
7437 l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
7438 p_transaction_type_id
7439 ,p_organization_id
7440 ,p_inventory_item_id
7441 ,l_subinventory_code
7442 ,l_locator_id
7443 ,l_lot_number);
7444 -- END IF;
7445 If ( l_serial_trx_allowed <> 'Y' and l_sub_loc_lot_trx_allowed <> 'Y' ) THEN
7446 -- skip the input record and go to next rec , because mat status is not allowed
7447 IF l_debug = 1 THEN
7448 log_statement(l_api_name, 'Mat Status Check failed', 'Skipping the input rec');
7449 END IF;
7450 GOTO nextINputrecord;
7451 END IF;
7452 -- End of mat status check ]
7453
7454 -- [ Allocating this line based on reservation without calling rules
7455 -- Make sure all the following values are either NULL or have some
7456 -- real values but not the defaulted values eg '-99' or '-9999' etc..
7457 -- The default values '-99', '-9999' may cause issues with Qty tree
7458 -- May have to default the value for Project, Task , unit
7459 -- This only applicable for line based on detailed reservation
7460 -- ]
7461
7462 IF l_revision = '-99' THEN
7463 l_revision := NULL;
7464 END IF;
7465
7466 IF l_subinventory_code = '-9999' THEN
7467 l_subinventory_code := NULL;
7468 END IF;
7469
7470 IF l_locator_id = -9999 THEN
7471 l_locator_id := NULL;
7472 END IF;
7473
7474 IF l_cost_group_id = -9999 THEN
7475 l_cost_group_id := NULL;
7476 END IF;
7477
7478 IF l_lpn_id = -9999 THEN
7479 l_lpn_id := NULL;
7480 END IF;
7481
7482 IF (l_lot_number = '-9999' ) THEN
7483 l_lot_number := NULL;
7484 END IF;
7485
7486 g_locs(1).revision := l_revision;
7487 g_locs(1).lot_number := l_lot_number;
7488 g_locs(1).subinventory_code := l_subinventory_code;
7489 g_locs(1).locator_id := l_locator_id;
7490 g_locs(1).quantity := l_needed_quantity;
7491 g_locs(1).secondary_quantity := l_sec_needed_quantity;
7492 g_locs(1).serial_number := l_serial_number; -- [ new code ]
7493
7494
7495 validate_and_insert(
7496 x_return_status => x_return_status
7497 , x_msg_count => x_msg_count
7498 , x_msg_data => x_msg_data
7499 , p_record_id => 1
7500 , p_needed_quantity => l_needed_quantity
7501 , p_use_pick_uom => FALSE
7502 , p_organization_id => p_organization_id
7503 , p_inventory_item_id => p_inventory_item_id
7504 , p_to_subinventory_code => l_to_subinventory_code
7505 , p_to_locator_id => l_to_locator_id
7506 , p_to_cost_group_id => l_to_cost_group_id
7507 , p_primary_uom => p_primary_uom
7508 , p_transaction_uom => p_transaction_uom
7509 , p_transaction_temp_id => p_transaction_temp_id
7510 , p_type_code => p_type_code
7511 , p_rule_id => l_rule_id
7512 , p_reservation_id => l_reservation_id
7513 , p_tree_id => p_tree_id
7514 , p_debug_on => l_debug_on
7515 , p_needed_sec_quantity => l_sec_needed_quantity
7516 , p_secondary_uom => p_secondary_uom
7517 , p_grade_code => p_grade_code
7518 , x_inserted_record => l_inserted_record
7519 , x_allocated_quantity => l_allocated_quantity
7520 , x_remaining_quantity => l_remaining_quantity
7521 , x_sec_allocated_quantity => l_sec_allocated_quantity
7522 , x_sec_remaining_quantity => l_sec_remaining_quantity
7523 );
7524 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7525 IF l_debug = 1 THEN
7526 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
7527 END IF;
7528 RAISE fnd_api.g_exc_unexpected_error;
7529 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7530 IF l_debug = 1 THEN
7531 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
7532 END IF;
7533 RAISE fnd_api.g_exc_error;
7534 END IF;
7535 /* done with this res go to the next */
7536 GOTO nextINputrecord;
7537 END IF;
7538 END IF;
7539
7540 IF l_debug = 1 THEN
7541 IF p_type_code = 1 THEN
7542 log_statement(l_api_name, 'Input Rec :Calling rule with following value of type -', 'Putaway');
7543 ELSE
7544 log_statement(l_api_name, 'Input Rec :Calling rule with following value of type -', 'Picking');
7545 END IF;
7546 log_statement(l_api_name, 'Input Rec :l_rule_id', l_rule_id);
7547 log_statement(l_api_name, 'Input Rec :p_organization_id', p_organization_id);
7548 log_statement(l_api_name, 'Input Rec :p_inventory_item_id', p_inventory_item_id);
7549 log_statement(l_api_name, 'Input Rec :p_transaction_type_id', p_transaction_type_id);
7550 log_statement(l_api_name, 'Input Rec :l_revision', l_revision);
7551 log_statement(l_api_name, 'Input Rec :l_lot_number', l_lot_number);
7552 log_statement(l_api_name, 'Input Rec :l_subinventory_code', l_subinventory_code);
7553 log_statement(l_api_name, 'Input Rec :l_locator_id', l_locator_id);
7554 log_statement(l_api_name, 'Input Rec :l_cost_group_id', l_cost_group_id);
7555 log_statement(l_api_name, 'Input Rec :l_pp_transaction_temp_id',l_pp_transaction_temp_id);
7556 log_statement(l_api_name, 'Input Rec :l_is_serial_control', l_is_serial_control);
7557 log_statement(l_api_name, 'Input Rec :l_detail_serial', l_detail_serial);
7558 log_statement(l_api_name, 'Input Rec :p_detail_any_serial', p_detail_any_serial);
7559 log_statement(l_api_name, 'Input Rec :p_from_serial', p_from_serial);
7560 log_statement(l_api_name, 'Input Rec :p_to_serial', p_to_serial);
7561 log_statement(l_api_name, 'Input Rec :l_unit_number', l_unit_number);
7562 log_statement(l_api_name, 'Input Rec :l_lpn_id', l_lpn_id);
7563 log_statement(l_api_name, 'Input Rec :l_project_id', l_project_id);
7564 log_statement(l_api_name, 'Input Rec :l_task_id', l_task_id);
7565 log_statement(l_api_name, 'Input Rec :l_rule_result ', l_rule_result);
7566 log_statement(l_api_name, 'Input Rec :l_restrict_subs_code ', l_restrict_subs_code);
7567 log_statement(l_api_name, 'Input Rec :l_restrict_locs_code ', l_restrict_locs_code);
7568 END IF;
7569
7570 For l_rule_counter IN 1..2 LOOP
7571 IF p_type_code = 2 THEN
7572 --pick_open_curs
7573 pick_open_rule(
7574 v_pick_cursor
7575 , l_rule_id
7576 , p_organization_id
7577 , p_inventory_item_id
7578 , p_transaction_type_id
7579 , l_revision
7580 , l_lot_number
7581 , l_subinventory_code
7582 , l_locator_id
7583 , l_cost_group_id
7584 , l_pp_transaction_temp_id
7585 , l_is_serial_control
7586 , l_detail_serial
7587 , p_detail_any_serial
7588 , p_from_serial
7589 , p_to_serial
7590 , l_unit_number
7591 , l_lpn_id
7592 , l_project_id
7593 , l_task_id
7594 , l_rule_result
7595 );
7596 ELSIF p_type_code = 1 then
7597 put_open_rule(
7598 v_put_cursor
7599 , l_rule_id
7600 , p_organization_id
7601 , p_inventory_item_id
7602 , p_transaction_type_id
7603 , l_subinventory_code
7604 , l_locator_id
7605 , l_pp_transaction_temp_id
7606 , l_restrict_subs_code
7607 , l_restrict_locs_code
7608 , l_project_id
7609 , l_task_id
7610 , l_rule_result
7611 );
7612 END IF;
7613
7614 IF l_rule_result = 1 then
7615 IF l_debug = 1 THEN
7616 log_statement(l_api_name, 'Open Cursor package called ' , l_rule_counter);
7617 log_statement(l_api_name, 'rule_id ' , l_rule_id);
7618 END IF;
7619 EXIT;
7620 END IF;
7621 --log_statement(l_api_name, ' Before = l_rule_result ' , l_rule_result );
7622 --log_statement(l_api_name, ' Before = wms_rule_pvt.g_rule_list_pick_ctr ' , wms_rule_pvt.g_rule_list_pick_ctr);
7623 IF (l_rule_result = 0) and l_rule_counter = 2 THEN --error
7624 IF l_debug = 1 THEN
7625 log_statement(l_api_name, 'open_curs_err', 'Error calling open_curs');
7626 log_error_msg(l_api_name, 'rule_package_missing');
7627 log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
7628 END IF;
7629 fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
7630 fnd_message.set_token('RULEID', l_rule_id);
7631 fnd_msg_pub.ADD;
7632 RAISE fnd_api.g_exc_unexpected_error;
7633 END IF;
7634 END LOOP;
7635
7636 IF (p_type_code = 2) THEN --pick
7637 g_locs_index := 0;
7638 g_locs.DELETE;
7639 g_consists.DELETE;
7640 g_lpns.DELETE;
7641 g_first_order_by_rank := NULL;
7642 g_first_consist_group := 0;
7643 g_last_consist_group := 0;
7644 l_order_by_rank := 0;
7645 END IF;
7646
7647 --If type code = 2 and allocation mode = 1
7648 --ENTIRE LPN
7649 IF p_type_code = 2
7650 AND l_allocation_mode = 1 THEN
7651 l_cur_lpn_group := 0;
7652 g_first_lpn_group := 0;
7653 g_last_lpn_group := 0;
7654 l_cur_lpn_rec := 0;
7655
7656 l_allocate_serial_flag := inv_cache.org_rec.allocate_serial_flag;
7657
7658 IF l_debug = 1 THEN
7659 log_statement(l_api_name, 'alloc_lpns', 'Allocating Entire LPNs');
7660 log_statement(l_api_name, 'allocate_serial_flag', 'allocate_serial_flag = '||l_allocate_serial_flag);
7661 END IF;
7662
7663 --for each record from rules cursor
7664 LOOP
7665 --Get record from rules cursor
7666 IF l_debug = 1 THEN
7667 log_statement(l_api_name, 'fetch_cursor', 'Getting rec from rule with FetchCursor');
7668 END IF;
7669 -- Added for Mat Stat check
7670 LOOP
7671 if l_debug = 1 THEN
7672 log_statement(l_api_name, 'fetch_cursor', 'inside Mat Stat check LOOP');
7673 END IF;
7674 -- For custom serial
7675 IF ( l_allocate_serial_flag = 'C' ) AND (nvl(l_custom_serial_index,-1) < nvl(l_custom_select_serials.serial_number.LAST,-1)) THEN
7676 -- next record should be next serial from custom API
7677 l_custom_serial_index := l_custom_serial_index + 1;
7678 v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
7679 v_current_row.quantity := 1;
7680 ELSE
7681 --- Mat Stat checking --
7682 fetchcursor(
7683 x_return_status
7684 , x_msg_count
7685 , x_msg_data
7686 , v_pick_cursor
7687 , l_rule_id
7688 , v_current_row.revision
7689 , v_current_row.lot_number
7690 , v_current_row.lot_expiration_date
7691 , v_current_row.subinventory_code
7692 , v_current_row.locator_id
7693 , v_current_row.cost_group_id
7694 , v_current_row.uom_code
7695 , v_current_row.lpn_id
7696 , v_current_row.serial_number
7697 , v_current_row.quantity
7698 , v_current_row.secondary_quantity -- new
7699 , v_current_row.grade_code -- new
7700 , v_current_row.consist_string
7701 , v_current_row.order_by_string
7702 , l_rows
7703 );
7704
7705 EXIT WHEN nvl(l_rows, 0) = 0 ; -- [ Added to to exit , if the rule is not returning any rows
7706 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7707 IF l_debug = 1 THEN
7708 log_error(l_api_name, 'uerr_fetch_cursor', 'Unexpected error in FetchCursor');
7709 END IF;
7710 RAISE fnd_api.g_exc_unexpected_error;
7711 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7712 IF l_debug = 1 THEN
7713 log_error(l_api_name, 'fetch_cursor ', 'Error in FetchCursor');
7714 END IF;
7715 RAISE fnd_api.g_exc_error;
7716 END IF;
7717
7718 IF l_debug = 1 THEN
7719 log_statement(l_api_name, 'Serial Status - l_detail_serial ', l_detail_serial);
7720 log_statement(l_api_name, 'fetch_cursor - l_rows ', l_rows);
7721 log_statement(l_api_name, 'fetch_cursor - v_current_row.lot_number ', v_current_row.lot_number);
7722 log_statement(l_api_name, 'fetch_cursor - v_current_row.serial_number ', v_current_row.serial_number);
7723 END IF;
7724
7725 IF ( l_allocate_serial_flag = 'C' ) THEN
7726 INV_DETAIL_SERIAL_PUB.Get_User_Serial_Numbers (
7727 x_return_status => x_return_status
7728 , x_msg_count => x_msg_count
7729 , x_msg_data => x_msg_data
7730 , p_organization_id => p_organization_id
7731 , p_inventory_item_id => p_inventory_item_id
7732 , p_revision => v_current_row.revision
7733 , p_lot_number => v_current_row.lot_number
7734 , p_subinventory_code => v_current_row.subinventory_code
7735 , p_locator_id => v_current_row.locator_id
7736 , p_required_sl_qty => v_current_row.quantity
7737 , p_from_range => p_from_serial
7738 , p_to_range => p_to_serial
7739 , p_unit_number => l_unit_number
7740 , p_cost_group_id => l_cost_group_id
7741 , p_transaction_type_id => NULL --p_transaction_type_id
7742 , p_demand_source_type_id => NULL --p_demand_source_type_id
7743 , p_demand_source_header_id => NULL --p_demand_source_header_id
7744 , p_demand_source_line_id => NULL --p_demand_source_line_id
7745 , x_serial_numbers => l_custom_select_serials );
7746
7747 IF ( x_return_status = fnd_api.g_ret_sts_unexp_error ) THEN
7748 IF ( l_debug = 1 ) THEN
7749 log_error(l_api_name, 'uerr_Get_User_Serial_Numbers', 'Unexpected error in Get_User_Serial_Numbers');
7750 END IF;
7751 RAISE fnd_api.g_exc_unexpected_error;
7752 ELSIF ( x_return_status = fnd_api.g_ret_sts_error ) THEN
7753 IF ( l_debug = 1 ) THEN
7754 log_error(l_api_name, 'Get_User_Serial_Numbers', 'Error in Get_User_Serial_Numbers');
7755 END IF;
7756 RAISE fnd_api.g_exc_error;
7757 END IF;
7758
7759 l_custom_serial_index := l_custom_select_serials.serial_number.FIRST;
7760 v_current_row.serial_number := l_custom_select_serials.serial_number(l_custom_serial_index);
7761 v_current_row.quantity := 1;
7762 END IF;
7763 END IF; -- custom serial
7764 ------ is_serial_trx_allowed is_sub_loc_lot_trx_allowed
7765 -- EXIT WHEN l_rows = 0 ;
7766 l_sub_loc_lot_trx_allowed := 'Y';
7767 l_serial_trx_allowed := 'Y';
7768 l_serial_status_id := 0;
7769
7770 IF v_current_row.serial_number IS NOT NULL THEN
7771 IF l_detail_serial = 1 THEN
7772 select status_id
7773 into l_serial_status_id
7774 from mtl_serial_numbers
7775 where inventory_item_id = p_inventory_item_id
7776 and current_organization_id = p_organization_id
7777 and serial_number = v_current_row.serial_number;
7778
7779 l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
7780 p_transaction_type_id
7781 ,p_organization_id
7782 ,p_inventory_item_id
7783 ,l_serial_status_id) ;
7784 END IF;
7785 IF l_debug = 1 THEN
7786 log_statement(l_api_name, 'Serial Status - p_transaction_type_id ', p_transaction_type_id);
7787 log_statement(l_api_name, 'Serial Status - p_organization_id ', p_organization_id);
7788 log_statement(l_api_name, 'Serial Status -p_transaction_type_id ', p_organization_id);
7789 log_statement(l_api_name, 'Serial Status - p_inventory_item_id ', p_inventory_item_id);
7790 log_statement(l_api_name, 'Serial Status - serial_number ', v_current_row.serial_number);
7791 log_statement(l_api_name, 'Serial Status - l_serial_status_id ', l_serial_status_id);
7792 log_statement(l_api_name, 'Serial Status - l_serial_trx_allowed ', l_serial_trx_allowed);
7793 END IF;
7794 END IF;
7795 -- Bug 4756156
7796 -- IF ((v_current_row.lot_number IS NOT NULL) AND (nvl(l_lot_status, 'Y') = 'Y')) THEN
7797 -- LPN Status Project
7798
7799 l_onhand_status_trx_allowed := 'Y';
7800
7801 IF l_default_status_id = -1 THEN
7802 IF l_debug = 1 THEN
7803 log_statement(l_api_name, 'before calling trx_allowed: ', l_sub_loc_lot_trx_allowed);
7804 END IF;
7805
7806 l_onhand_status_trx_allowed := 'N';
7807 l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
7808 p_transaction_type_id
7809 ,p_organization_id
7810 ,p_inventory_item_id
7811 ,v_current_row.subinventory_code
7812 ,v_current_row.locator_id
7813 ,v_current_row.lot_number);
7814
7815 IF l_debug = 1 THEN
7816 log_statement(l_api_name, 'fetch_cursor - l_sub_loc_lot_trx_allowed ', l_sub_loc_lot_trx_allowed);
7817 END IF;
7818 ELSE -- IF l_default_status_id = -1 THEN
7819
7820 l_sub_loc_lot_trx_allowed:='N';
7821 IF (inv_cache.item_rec.serial_number_control_code in (1,6)) THEN
7822 l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
7823 p_transaction_type_id
7824 ,p_organization_id
7825 ,p_inventory_item_id
7826 ,v_current_row.subinventory_code
7827 ,v_current_row.locator_id
7828 ,v_current_row.lot_number
7829 , v_current_row.lpn_id);
7830 END IF;
7831 IF l_debug = 1 THEN
7832 log_statement(l_api_name, 'fetch_cursor - l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
7833 END IF;
7834 END IF;
7835
7836 -- END IF;
7837 --- ]
7838 EXIT WHEN ( l_serial_trx_allowed = 'Y'
7839 and (l_sub_loc_lot_trx_allowed = 'Y' OR l_onhand_status_trx_allowed='Y'));
7840 -- >> Else fetch next record from the rule cursor --
7841 END LOOP;
7842 -- End of Mat Stat Check --
7843 -- LPN Status Project
7844
7845 --initialize pointer to next rec
7846 v_current_row.next_rec := 0;
7847 --if no more records
7848 IF l_rows = 0 THEN
7849 IF l_debug = 1 THEN
7850 log_statement(l_api_name, 'no_more_rec', 'No more records from rule');
7851 END IF;
7852 IF l_consist_exists THEN
7853 --loop through consist groups, looking for groups where quantity = needed quantity
7854 l_cur_consist_group := g_first_consist_group;
7855 IF l_debug = 1 THEN
7856 log_statement(l_api_name, 'first_consist_group', 'First Consist Group in list: ' || l_cur_consist_group);
7857 END IF;
7858 LOOP
7859 --EXIT WHEN l_needed_quantity <= 0;
7860 IF g_over_allocation = 'N'
7861 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
7862 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
7863 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
7864 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
7865 IF l_max_tolerance >= 0 THEN
7866 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
7867 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
7868 ELSE
7869 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
7870 END IF;
7871 END IF;
7872 EXIT WHEN l_cur_consist_group = 0;
7873 --IF g_consists(l_cur_consist_group).quantity = l_needed_quantity THEN
7874 IF (g_consists(l_cur_consist_group).quantity BETWEEN (l_needed_quantity - l_max_tolerance) AND l_needed_quantity) THEN
7875 --for each LPN in lpn array
7876 l_cur_lpn_group := g_consists(l_cur_consist_group).first_rec;
7877 IF l_debug = 1 THEN
7878 log_statement(l_api_name, 'first_lpn', 'First LPN in list: ' || l_cur_lpn_group);
7879 END IF;
7880 LOOP --loop through lpn in consist group
7881 EXIT WHEN l_cur_lpn_group = 0;
7882 --if lpn quantity is less than or equal to the needed quantity
7883 -- and the LPN has been entirely allocated, use it
7884 IF l_debug = 1 THEN
7885 log_statement(l_api_name, 'alloc_stored_lpn', 'Allocating LPN. id: ' || l_cur_lpn_group);
7886 END IF;
7887 -- for each record in LPN
7888 l_cur_lpn_rec := g_lpns(l_cur_lpn_group).first_rec;
7889 LOOP
7890 EXIT WHEN l_cur_lpn_rec = 0;
7891 g_trace_recs(l_cur_lpn_rec).entire_lpn_flag := 'Y';
7892 --call validate and insert
7893 l_expected_quantity := g_locs(l_cur_lpn_rec).quantity;
7894 validate_and_insert(
7895 x_return_status => x_return_status
7896 , x_msg_count => x_msg_count
7897 , x_msg_data => x_msg_data
7898 , p_record_id => l_cur_lpn_rec
7899 , p_needed_quantity => l_needed_quantity
7900 , p_use_pick_uom => FALSE
7901 , p_organization_id => p_organization_id
7902 , p_inventory_item_id => p_inventory_item_id
7903 , p_to_subinventory_code => l_to_subinventory_code
7904 , p_to_locator_id => l_to_locator_id
7905 , p_to_cost_group_id => l_to_cost_group_id
7906 , p_primary_uom => p_primary_uom
7907 , p_transaction_uom => p_transaction_uom
7908 , p_transaction_temp_id => p_transaction_temp_id
7909 , p_type_code => p_type_code
7910 , p_rule_id => l_rule_id
7911 , p_reservation_id => l_reservation_id
7912 , p_tree_id => p_tree_id
7913 , p_debug_on => l_debug_on
7914 , p_needed_sec_quantity => l_sec_needed_quantity
7915 , p_secondary_uom => p_secondary_uom
7916 , p_grade_code => p_grade_code
7917 , x_inserted_record => l_inserted_record
7918 , x_allocated_quantity => l_allocated_quantity
7919 , x_remaining_quantity => l_remaining_quantity
7920 , x_sec_allocated_quantity => l_sec_allocated_quantity
7921 , x_sec_remaining_quantity => l_sec_remaining_quantity
7922 );
7923
7924 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7925 IF l_debug = 1 THEN
7926 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
7927 END IF;
7928 RAISE fnd_api.g_exc_unexpected_error;
7929 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7930 IF l_debug = 1 THEN
7931 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
7932 END IF;
7933 RAISE fnd_api.g_exc_error;
7934 END IF;
7935 --if returns false
7936 IF l_inserted_record = FALSE
7937 OR l_allocated_quantity < l_expected_quantity THEN
7938 IF l_debug = 1 THEN
7939 log_statement(l_api_name, 'insert_failed', 'Record failed to allocation. Rolling back and ' || 'invalidating LPN');
7940 -- rollback quantity tree
7941 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
7942 END IF;
7943 inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
7944 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
7945 IF l_debug = 1 THEN
7946 log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
7947 END IF;
7948 RAISE fnd_api.g_exc_unexpected_error;
7949 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
7950 IF l_debug = 1 THEN
7951 log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
7952 END IF;
7953 RAISE fnd_api.g_exc_error;
7954 END IF;
7955 -- delete allocations
7956 DELETE FROM wms_transactions_temp
7957 WHERE line_type_code = 2
7958 AND type_code = p_type_code;
7959 IF l_debug_on THEN
7960 l_cur_rec := g_lpns(l_cur_lpn_group).first_rec;
7961 LOOP
7962 g_trace_recs(l_cur_rec).entire_lpn_flag := 'N';
7963 g_trace_recs(l_cur_rec).suggested_qty := 0;
7964 EXIT WHEN l_cur_rec = l_cur_lpn_rec;
7965 l_cur_rec := g_locs(l_cur_rec).next_rec;
7966 END LOOP;
7967 END IF;
7968 IF l_debug = 1 THEN
7969 log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
7970 END IF;
7971 -- Exit loop for each rec in this LPN
7972 EXIT;
7973 END IF; -- didn't allocate as much as expected
7974 IF l_debug_on THEN
7975 g_trace_recs(l_cur_lpn_rec).consist_string_flag := 'Y';
7976 END IF;
7977 --decrease quantity needed
7978 IF l_debug = 1 THEN
7979 log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
7980 END IF;
7981 l_cur_lpn_rec := g_locs(l_cur_lpn_rec).next_rec;
7982 EXIT WHEN l_cur_lpn_rec = 0;
7983 --end loop through lpn recs
7984 END LOOP; -- loop through recs w/in LPN
7985
7986 -- if no more quantity needed, exit LPN loop
7987 l_needed_quantity := l_needed_quantity - g_lpns(l_cur_lpn_group).quantity;
7988 l_sec_needed_quantity := l_sec_needed_quantity - g_lpns(l_cur_lpn_group).secondary_quantity;
7989
7990 IF l_debug = 1 THEN
7991 log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
7992 END IF;
7993
7994 --EXIT WHEN l_needed_quantity <= 0; -- consist loop
7995 IF g_over_allocation = 'N'
7996 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
7997 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
7998 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
7999 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8000 IF l_max_tolerance >= 0 THEN
8001 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8002 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8003 ELSE
8004 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8005 END IF;
8006 END IF;
8007 l_cur_lpn_group := g_lpns(l_cur_lpn_group).next_consist_lpn_id;
8008 EXIT WHEN l_cur_lpn_group = 0;
8009
8010 IF l_debug = 1 THEN
8011 log_statement(l_api_name, 'next_lpn', 'Next LPN in list: ' || l_cur_lpn_group);
8012 END IF;
8013
8014 END LOOP; --lpns in consist group
8015
8016 -- if no more quantity needed, exit LPN loop
8017 --EXIT WHEN l_needed_quantity <= 0; -- consist loop
8018 IF g_over_allocation = 'N'
8019 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8020 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
8021 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8022 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8023 IF l_max_tolerance >= 0 THEN
8024 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8025 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8026 ELSE
8027 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8028 END IF;
8029 END IF;
8030 END IF; -- enough quantity to allocate
8031
8032 -- end loop through consist groups
8033 l_cur_consist_group := g_consists(l_cur_consist_group).next_group;
8034
8035 IF l_debug = 1 THEN
8036 log_statement(l_api_name, 'next_consist_group', 'Next Consist Group in list: ' || l_cur_consist_group);
8037 END IF;
8038
8039 END LOOP;
8040
8041 --exit outermost loop
8042 IF l_debug = 1 THEN
8043 log_statement(l_api_name, 'lpn_alloc_finished', 'Finished checking all LPNS. Exit LPN allocation.');
8044 END IF;
8045
8046 EXIT; --outermost loop
8047 ELSE -- no consists
8048 --for each LPN in lpn array
8049 l_cur_lpn_group := g_first_lpn_group;
8050
8051 IF l_debug = 1 THEN
8052 log_statement(l_api_name, 'first_lpn', 'First LPN in list: ' || g_first_lpn_group);
8053 END IF;
8054
8055 LOOP
8056 --EXIT WHEN l_needed_quantity <= 0;
8057 IF g_over_allocation = 'N'
8058 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8059 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
8060 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8061 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8062 IF l_max_tolerance >= 0 THEN
8063 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8064 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8065 ELSE
8066 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8067 END IF;
8068 END IF;
8069 EXIT WHEN l_cur_lpn_group = 0;
8070
8071 --if lpn quantity is less than or equal to the needed quantity
8072 -- and the LPN has been entirely allocated, use it
8073 IF g_lpns(l_cur_lpn_group).quantity <= l_needed_quantity
8074 AND g_lpns(l_cur_lpn_group).total_quantity <> -1
8075 AND g_lpns(l_cur_lpn_group).quantity = g_lpns(l_cur_lpn_group).total_quantity THEN
8076
8077 IF l_debug = 1 THEN
8078 log_statement(l_api_name, 'alloc_stored_lpn', 'Allocating LPN. id: ' || l_cur_lpn_group);
8079 END IF;
8080 -- for each record in LPN
8081 l_cur_lpn_rec := g_lpns(l_cur_lpn_group).first_rec;
8082
8083 LOOP
8084 EXIT WHEN l_cur_lpn_rec = 0;
8085 g_trace_recs(l_cur_lpn_rec).entire_lpn_flag := 'Y';
8086 --call validate and insert
8087 l_expected_quantity := g_locs(l_cur_lpn_rec).quantity;
8088 validate_and_insert(
8089 x_return_status => x_return_status
8090 , x_msg_count => x_msg_count
8091 , x_msg_data => x_msg_data
8092 , p_record_id => l_cur_lpn_rec
8093 , p_needed_quantity => l_needed_quantity
8094 , p_use_pick_uom => FALSE
8095 , p_organization_id => p_organization_id
8096 , p_inventory_item_id => p_inventory_item_id
8097 , p_to_subinventory_code => l_to_subinventory_code
8098 , p_to_locator_id => l_to_locator_id
8099 , p_to_cost_group_id => l_to_cost_group_id
8100 , p_primary_uom => p_primary_uom
8101 , p_transaction_uom => p_transaction_uom
8102 , p_transaction_temp_id => p_transaction_temp_id
8103 , p_type_code => p_type_code
8104 , p_rule_id => l_rule_id
8105 , p_reservation_id => l_reservation_id
8106 , p_tree_id => p_tree_id
8107 , p_debug_on => l_debug_on
8108 , p_needed_sec_quantity => l_sec_needed_quantity
8109 , p_secondary_uom => p_secondary_uom
8110 , p_grade_code => p_grade_code
8111 , x_inserted_record => l_inserted_record
8112 , x_allocated_quantity => l_allocated_quantity
8113 , x_remaining_quantity => l_remaining_quantity
8114 , x_sec_allocated_quantity => l_sec_allocated_quantity
8115 , x_sec_remaining_quantity => l_sec_remaining_quantity
8116 );
8117
8118 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8119 IF l_debug = 1 THEN
8120 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
8121 END IF;
8122 RAISE fnd_api.g_exc_unexpected_error;
8123 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8124 IF l_debug = 1 THEN
8125 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
8126 END IF;
8127 RAISE fnd_api.g_exc_error;
8128 END IF;
8129
8130 --if returns false
8131 IF l_inserted_record = FALSE
8132 OR l_allocated_quantity < l_expected_quantity THEN
8133 IF l_debug = 1 THEN
8134 log_statement(l_api_name, 'insert_failed', 'Record failed to allocation. Rolling back and ' || 'invalidating LPN');
8135 -- rollback quantity tree
8136 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
8137 END IF;
8138
8139 inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
8140
8141 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8142 IF l_debug = 1 THEN
8143 log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
8144 END IF;
8145 RAISE fnd_api.g_exc_unexpected_error;
8146 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8147 IF l_debug = 1 THEN
8148 log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
8149 END IF;
8150 RAISE fnd_api.g_exc_error;
8151 END IF;
8152
8153 -- set lpn quantity to -1
8154 --no need to call invalidate, since we'll never see this
8155 -- LPN record again
8156
8157 -- delete allocations
8158 DELETE FROM wms_transactions_temp
8159 WHERE line_type_code = 2
8160 AND type_code = p_type_code;
8161
8162 IF l_debug_on THEN
8163 l_cur_rec := g_lpns(l_cur_lpn_group).first_rec;
8164 LOOP
8165 g_trace_recs(l_cur_rec).entire_lpn_flag := 'N';
8166 g_trace_recs(l_cur_rec).suggested_qty := 0;
8167 EXIT WHEN l_cur_rec = l_cur_lpn_rec;
8168 l_cur_rec := g_locs(l_cur_rec).next_rec;
8169 END LOOP;
8170 END IF;
8171
8172 IF l_debug = 1 THEN
8173 log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
8174 END IF;
8175
8176 -- Exit loop for each rec in this LPN
8177 EXIT;
8178 END IF; -- didn't allocate as much as expected
8179
8180 --decrease quantity needed
8181 l_needed_quantity := l_needed_quantity - l_allocated_quantity;
8182 l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
8183
8184 IF l_debug = 1 THEN
8185 log_statement(l_api_name, 'need_qty', 'New needed quantity: ' || l_needed_quantity);
8186 log_statement(l_api_name, 'need_qty', 'New sec needed quantity: ' || l_sec_needed_quantity);
8187 END IF;
8188
8189 --EXIT WHEN l_needed_quantity <= 0;
8190 IF g_over_allocation = 'N'
8191 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8192 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
8193 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8194 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8195 IF l_max_tolerance >= 0 THEN
8196 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8197 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8198 ELSE
8199 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8200 END IF;
8201 END IF;
8202 l_cur_lpn_rec := g_locs(l_cur_lpn_rec).next_rec;
8203 --end loop through lpn recs
8204
8205 END LOOP; -- loop through recs w/in LPN
8206
8207 -- if no more quantity needed, exit LPN loop
8208 --EXIT WHEN l_needed_quantity <= 0;
8209 IF g_over_allocation = 'N'
8210 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8211 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
8212 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8213 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8214 IF l_max_tolerance >= 0 THEN
8215 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8216 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8217 ELSE
8218 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8219 END IF;
8220 END IF;
8221 END IF; --needed qty > lpn.quantity
8222
8223 l_cur_lpn_group := g_lpns(l_cur_lpn_group).next_group;
8224
8225 IF l_debug = 1 THEN
8226 log_statement(l_api_name, 'next_lpn', 'Next LPN in list: ' || l_cur_lpn_group);
8227 END IF;
8228
8229 -- end loop through lpn groups
8230 END LOOP;
8231
8232 --exit outermost loop
8233 IF l_debug = 1 THEN
8234 log_statement(l_api_name, 'lpn_alloc_finished', 'Finished checking all LPNS. Exit LPN allocation.');
8235 END IF;
8236
8237 EXIT;
8238 END IF; --consists exist
8239 END IF; --if no more records
8240
8241 --add record to table
8242 g_locs_index := g_locs_index + 1;
8243
8244 IF l_debug = 1 THEN
8245 log_statement(l_api_name, 'loc_index', 'loc index: ' || g_locs_index);
8246 END IF;
8247
8248 g_locs(g_locs_index) := v_current_row;
8249
8250 --initialize trace records
8251 IF l_debug_on THEN
8252 log_statement(l_api_name, 'init_trace', 'Init trace record');
8253 g_trace_recs(g_locs_index).revision := v_current_row.revision;
8254 g_trace_recs(g_locs_index).lot_number := v_current_row.lot_number;
8255 g_trace_recs(g_locs_index).lot_expiration_date := v_current_row.lot_expiration_date;
8256 g_trace_recs(g_locs_index).subinventory_code := v_current_row.subinventory_code;
8257 g_trace_recs(g_locs_index).locator_id := v_current_row.locator_id;
8258 g_trace_recs(g_locs_index).cost_group_id := v_current_row.cost_group_id;
8259 g_trace_recs(g_locs_index).lpn_id := v_current_row.lpn_id;
8260 g_trace_recs(g_locs_index).uom_code := v_current_row.uom_code;
8261 g_trace_recs(g_locs_index).quantity := v_current_row.quantity;
8262 g_trace_recs(g_locs_index).secondary_qty := v_current_row.secondary_quantity;
8263 g_trace_recs(g_locs_index).grade_code := v_current_row.grade_code;
8264 g_trace_recs(g_locs_index).secondary_uom_code := v_current_row.secondary_uom_code;
8265 g_trace_recs(g_locs_index).serial_number := v_current_row.serial_number;
8266 --set LPN flag to no
8267 g_trace_recs(g_locs_index).consist_string_flag := 'V';
8268 g_trace_recs(g_locs_index).partial_pick_flag := 'Y';
8269 g_trace_recs(g_locs_index).order_string_flag := 'V';
8270 g_trace_recs(g_locs_index).pick_uom_flag := 'V';
8271 g_trace_recs(g_locs_index).serial_number_used_flag := 'V';
8272 g_trace_recs(g_locs_index).entire_lpn_flag := 'N';
8273 --write to log file
8274 log_statement(l_api_name, 'rev', 'revision: ' || v_current_row.revision);
8275 log_statement(l_api_name, 'lot', 'lot: ' || v_current_row.lot_number);
8276 log_statement(l_api_name, 'sub', 'sub:' || v_current_row.subinventory_code);
8277 log_statement(l_api_name, 'loc', 'loc: ' || v_current_row.locator_id);
8278 log_statement(l_api_name, 'cg', 'cg: ' || v_current_row.cost_group_id);
8279 log_statement(l_api_name, 'lpn', 'lpn: ' || v_current_row.lpn_id);
8280 log_statement(l_api_name, 'sn', 'sn: ' || v_current_row.serial_number);
8281 log_statement(l_api_name, 'qty', 'quantity: ' || v_current_row.quantity);
8282 log_statement(l_api_name, 'sqty', 'secondary_quantity: ' || v_current_row.secondary_quantity);
8283 log_statement(l_api_name, 'uom', 'uom_code: ' || v_current_row.uom_code);
8284 log_statement(l_api_name, 'suom', 'secondary_uom_code: ' || v_current_row.secondary_uom_code);
8285 log_statement(l_api_name, 'ord', 'order:' || v_current_row.order_by_string);
8286 log_statement(l_api_name, 'con', 'consist:' || v_current_row.consist_string);
8287 END IF;
8288
8289 --if lpn already exists
8290 IF g_lpns.EXISTS(v_current_row.lpn_id) THEN
8291 IF l_debug = 1 THEN
8292 log_statement(l_api_name, 'lpn_exists', 'This LPN group already exists');
8293 END IF;
8294 --if lpn consist string is different than rec's consist string,
8295 --this LPN will never be allocated entirely. Remove LPN from list.
8296 IF g_lpns(v_current_row.lpn_id).total_quantity < 0 THEN
8297 IF l_debug = 1 THEN
8298 log_statement(l_api_name, 'invalid_lpn', 'This LPN is invalid');
8299 END IF;
8300 GOTO nextoutputrecord;
8301 ELSIF l_consist_exists
8302 AND g_lpns(v_current_row.lpn_id).consist_string <> v_current_row.consist_string THEN
8303
8304 IF l_debug = 1 THEN
8305 log_statement(l_api_name, 'no_consist', 'This record has a ' || 'different consist string than its LPN. Invalidating LPN');
8306 END IF;
8307
8308 invalidate_lpn_group(v_current_row.lpn_id);
8309
8310 IF l_debug_on THEN
8311 g_trace_recs(g_locs_index).consist_string_flag := 'N';
8312 l_cur_rec := g_lpns(v_current_row.lpn_id).first_rec;
8313
8314 LOOP
8315 EXIT WHEN l_cur_rec = 0;
8316 g_trace_recs(l_cur_rec).consist_string_flag := 'N';
8317 l_cur_rec := g_locs(l_cur_rec).next_rec;
8318 END LOOP;
8319 END IF;
8320
8321 GOTO nextoutputrecord;
8322 --bug 2356370 - need to recheck the LPN total quantity to make
8323 -- sure it doesn't exceed the needed quantity.
8324 ELSIF g_lpns(v_current_row.lpn_id).total_quantity > l_needed_quantity THEN
8325
8326 IF l_debug = 1 THEN
8327 log_statement(
8328 l_api_name
8329 , 'bad_tot_qty2'
8330 , 'The total quantity for' || ' this LPN exceeds the needed quantity. Invalidating LPN.'
8331 );
8332 END IF;
8333
8334 invalidate_lpn_group(v_current_row.lpn_id);
8335 --goto next output record
8336 GOTO nextoutputrecord;
8337 END IF;
8338
8339 --increase LPN quantity
8340 g_lpns(v_current_row.lpn_id).quantity := g_lpns(v_current_row.lpn_id).quantity
8341 + v_current_row.quantity;
8342 g_lpns(v_current_row.lpn_id).secondary_quantity := g_lpns(v_current_row.lpn_id).secondary_quantity
8343 + v_current_row.secondary_quantity;
8344 --set pointers
8345 g_locs(g_lpns(v_current_row.lpn_id).last_rec).next_rec := g_locs_index;
8346 g_lpns(v_current_row.lpn_id).last_rec := g_locs_index;
8347 --else lpn does not already exist
8348 ELSE
8349
8350 IF l_debug = 1 THEN
8351 log_statement(l_api_name, 'new_lpn', 'Creating a new LPN group');
8352 END IF;
8353
8354 g_lpns(v_current_row.lpn_id).lpn_id := v_current_row.lpn_id;
8355 g_lpns(v_current_row.lpn_id).first_rec := g_locs_index;
8356 g_lpns(v_current_row.lpn_id).last_rec := g_locs_index;
8357 g_lpns(v_current_row.lpn_id).quantity := v_current_row.quantity;
8358 g_lpns(v_current_row.lpn_id).secondary_quantity := v_current_row.secondary_quantity;
8359 g_lpns(v_current_row.lpn_id).grade_code := v_current_row.grade_code;
8360 g_lpns(v_current_row.lpn_id).prev_group := 0;
8361 g_lpns(v_current_row.lpn_id).next_group := 0;
8362 g_lpns(v_current_row.lpn_id).prev_consist_lpn_id := 0;
8363 g_lpns(v_current_row.lpn_id).next_consist_lpn_id := 0;
8364 g_lpns(v_current_row.lpn_id).parent_consist_group := 0;
8365 g_lpns(v_current_row.lpn_id).consist_string := v_current_row.consist_string;
8366 --query total quantity for LPN
8367 OPEN c_lpn_quantity;
8368 FETCH c_lpn_quantity INTO g_lpns(v_current_row.lpn_id).total_quantity;
8369
8370 IF l_debug = 1 THEN
8371 log_statement(l_api_name, 'tot_qty', 'Total quantity for this LPN: ' || g_lpns(v_current_row.lpn_id).total_quantity);
8372 END IF;
8373
8374 --IF total quantity > quantity needed
8375 IF c_lpn_quantity%NOTFOUND
8376 OR g_lpns(v_current_row.lpn_id).total_quantity IS NULL
8377 OR g_lpns(v_current_row.lpn_id).total_quantity <= 0
8378 OR g_lpns(v_current_row.lpn_id).total_quantity > l_needed_quantity THEN
8379 CLOSE c_lpn_quantity;
8380
8381 IF l_debug = 1 THEN
8382 log_statement(
8383 l_api_name
8384 , 'bad_tot_qty'
8385 , 'The total quantity for' || ' this LPN keeps it from being allocated. Invalidating LPN.'
8386 );
8387 END IF;
8388
8389 invalidate_lpn_group(v_current_row.lpn_id);
8390 --goto next output record
8391 GOTO nextoutputrecord;
8392 END IF;
8393
8394 CLOSE c_lpn_quantity;
8395
8396 IF NVL(l_cur_order_by_string, '@@@') <> NVL(v_current_row.order_by_string, '@@@') THEN
8397 l_order_by_rank := l_order_by_rank + 1;
8398 l_cur_order_by_string := v_current_row.order_by_string;
8399
8400 IF g_first_order_by_rank IS NULL THEN
8401 g_first_order_by_rank := l_order_by_rank;
8402 END IF;
8403 END IF;
8404
8405 g_lpns(v_current_row.lpn_id).order_by_rank := l_order_by_rank;
8406 --initialize record in LPN array
8407 g_lpns(v_current_row.lpn_id).prev_group := g_last_lpn_group;
8408
8409 IF g_first_lpn_group = 0 THEN
8410 g_first_lpn_group := v_current_row.lpn_id;
8411 ELSE
8412 g_lpns(g_last_lpn_group).next_group := v_current_row.lpn_id;
8413 END IF;
8414
8415 g_last_lpn_group := v_current_row.lpn_id;
8416 END IF; --if lpn already exists
8417
8418 --validate from/to sub/loc
8419 --if fail, invalidate LPN and goto next output record
8420 --first check to make sure picking from dest sub is not allowed;
8421 --then, based on type code, compare src sub to dest sub;
8422 --next, check to see if sub and item are locator controlled;
8423 --if loc control, go to next record only if src loc = dest loc;
8424 --if not loc control, go to next records (since subs are equal);
8425 --all of the global variables are set in
8426 --wms_engine_pvt.create_suggestions
8427 IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
8428 AND v_current_row.subinventory_code = l_to_subinventory_code
8429 ) THEN
8430 IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
8431 OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
8432 OR (wms_engine_pvt.g_sub_loc_control = 5
8433 AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
8434 )
8435 ) THEN
8436 IF (v_current_row.locator_id = l_to_locator_id) THEN
8437
8438 IF l_debug = 1 THEN
8439 log_event(
8440 l_api_name
8441 , 'sub_loc_same'
8442 , 'Cannot use this ' || 'location since source subinventory and locator are' || ' same as destination subinventory and locator'
8443 );
8444 END IF;
8445
8446 IF l_debug_on THEN
8447 g_trace_recs(g_locs_index).same_subinv_loc_flag := 'N';
8448 END IF;
8449
8450 invalidate_lpn_group(v_current_row.lpn_id);
8451 GOTO nextoutputrecord;
8452 END IF;
8453 ELSE
8454
8455 IF l_debug = 1 THEN
8456 log_event(
8457 l_api_name
8458 , 'sub_same'
8459 , 'Cannot use this ' || 'location since source subinventory is ' || 'same as destination subinventory'
8460 );
8461 END IF;
8462
8463 IF l_debug_on THEN
8464 g_trace_recs(g_locs_index).same_subinv_loc_flag := 'N';
8465 END IF;
8466
8467 invalidate_lpn_group(v_current_row.lpn_id);
8468 GOTO nextoutputrecord;
8469 END IF;
8470 END IF;
8471
8472 IF l_debug_on THEN
8473 g_trace_recs(g_locs_index).same_subinv_loc_flag := 'Y';
8474 END IF;
8475
8476 --query quantity tree
8477 --If att < rec quantity, invalidate LPN and goto next output record
8478
8479 IF l_debug = 1 THEN
8480 log_statement(l_api_name, 'query tree', 'Calling Query Tree');
8481 END if;
8482 -- BUG 3609380
8483 -- Allocation was being treated as a subinventory transfer, and hence not honoring
8484 -- reservations alredy made on any level higher than SUB. Changes to treat as Issue
8485 -- by removing l_to_subinevntory_code.
8486 inv_quantity_tree_pvt.query_tree
8487 (
8488 p_api_version_number => g_qty_tree_api_version
8489 , p_init_msg_lst => fnd_api.g_false -- p_init_msg_lst
8490 , x_return_status => x_return_status
8491 , x_msg_count => x_msg_count
8492 , x_msg_data => x_msg_data
8493 , p_tree_id => p_tree_id
8494 , p_revision => v_current_row.revision
8495 , p_lot_number => v_current_row.lot_number
8496 , p_subinventory_code => v_current_row.subinventory_code
8497 , p_locator_id => v_current_row.locator_id
8498 , x_qoh => l_qoh
8499 , x_sqoh => l_sqoh
8500 , x_rqoh => l_rqoh
8501 , x_srqoh => l_srqoh
8502 , x_qr => l_qr
8503 , x_sqr => l_sqr
8504 , x_qs => l_qs
8505 , x_sqs => l_sqs
8506 , x_att => l_att
8507 , x_satt => l_satt
8508 , x_atr => l_atr
8509 , x_satr => l_satr
8510 , p_transfer_subinventory_code => chk_for_passing_xfer_sub ( p_transaction_temp_id , l_to_subinventory_code) -- Bug# 4099907
8511 , p_cost_group_id => v_current_row.cost_group_id
8512 , p_lpn_id => v_current_row.lpn_id
8513 );
8514
8515 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8516 IF l_debug = 1 THEN
8517 log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
8518 END IF;
8519 RAISE fnd_api.g_exc_unexpected_error;
8520 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8521 IF l_debug = 1 THEN
8522 log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
8523 END if;
8524 RAISE fnd_api.g_exc_error;
8525 END IF;
8526
8527 IF l_debug = 1 THEN
8528 log_statement(l_api_name, 'att_qty', 'Available quantity = ' || l_att);
8529 END IF;
8530
8531 --If not all of the record is available, then we can't allocate
8532 --the entire LPN
8533 IF l_att < v_current_row.quantity THEN
8534 IF l_debug = 1 THEN
8535 log_statement(l_api_name, 'not_enough_att', 'Not all the material is available for this rec. Skipping this LPN');
8536 END IF;
8537 IF l_debug_on THEN
8538 g_trace_recs(g_locs_index).att_qty := l_att;
8539 g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
8540 g_trace_recs(g_locs_index).att_qty_flag := 'N';
8541 END IF;
8542 invalidate_lpn_group(v_current_row.lpn_id);
8543 GOTO nextoutputrecord;
8544 END IF;
8545
8546 IF l_debug_on THEN
8547 g_trace_recs(g_locs_index).att_qty := l_att;
8548 g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
8549 g_trace_recs(g_locs_index).att_qty_flag := 'Y';
8550 END IF;
8551
8552 --If LPN is not in first order by group OR
8553 --goto next output record
8554 IF g_lpns(v_current_row.lpn_id).quantity < g_lpns(v_current_row.lpn_id).total_quantity THEN
8555 IF l_debug = 1 THEN
8556 log_statement(l_api_name, 'not_enough_lpn_qty', 'Not enough quantity allocated for this LPN. Getting next record');
8557 END IF;
8558 -- Bug #5345736
8559 --invalidate_lpn_group(v_current_row.lpn_id); --bug 6831349
8560 GOTO nextoutputrecord;
8561 END IF;
8562
8563 IF l_consist_exists THEN
8564 --find consist group
8565 -- used in get_hash_value. That procedure works best if
8566 -- hashsize is power of 2
8567 l_hash_size := POWER(2, 15);
8568 --get hash index for this consist string
8569 IF l_debug = 1 THEN
8570 log_statement(l_api_name, 'get_hash_value', 'Calling get_hash_value for consist string');
8571 END IF;
8572 l_cur_consist_group :=
8573 DBMS_UTILITY.get_hash_value(NAME => g_lpns(v_current_row.lpn_id).consist_string, base => 1, hash_size => l_hash_size);
8574 --Because the hash function can return the same index for different
8575 -- consist strings, we have to check to see if the group at the index
8576 -- returned above has the same consist string as the current record.
8577 -- If not, look at the next record. Continue on until we find the
8578 -- correct consist group or determine that the group has not been
8579 -- defined yet
8580 LOOP
8581 EXIT WHEN NOT g_consists.EXISTS(l_cur_consist_group);
8582 EXIT WHEN g_consists(l_cur_consist_group).consist_string = g_lpns(v_current_row.lpn_id).consist_string;
8583 l_cur_consist_group := l_cur_consist_group + 1;
8584 END LOOP;
8585
8586 --see if consist group already exists
8587 --If group does exist
8588 IF g_consists.EXISTS(l_cur_consist_group) THEN
8589
8590 IF l_debug = 1 THEN
8591 log_statement(l_api_name, 'group_exists', 'The consist group already exists');
8592 END IF;
8593
8594 --if lpn quantity would exceed needed quantity, invalidate lpn
8595 IF g_consists(l_cur_consist_group).quantity + g_lpns(v_current_row.lpn_id).quantity > l_needed_quantity THEN
8596
8597 IF l_debug = 1 THEN
8598 log_statement(l_api_name, 'too_much_qty', 'LPN quantity would exceed quantity needed.');
8599 END IF;
8600
8601 invalidate_lpn_group(v_current_row.lpn_id);
8602 GOTO nextoutputrecord;
8603 END IF;
8604
8605 --set pointer values
8606 g_lpns(v_current_row.lpn_id).prev_consist_lpn_id := g_consists(l_cur_consist_group).last_rec;
8607 g_lpns(g_consists(l_cur_consist_group).last_rec).next_consist_lpn_id := v_current_row.lpn_id;
8608 g_consists(l_cur_consist_group).last_rec := v_current_row.lpn_id;
8609 --increase group quantity
8610 --g_consists(l_cur_consist_group).quantity :=
8611 -- g_consists(l_cur_consist_group).quantity + l_possible_quantity;
8612 g_consists(l_cur_consist_group).quantity := g_consists(l_cur_consist_group).quantity + g_lpns(v_current_row.lpn_id).quantity;
8613 --If group does not exist
8614 ELSE
8615
8616 IF l_debug = 1 THEN
8617 log_statement(l_api_name, 'new_group', 'Creating a new consist group');
8618 END IF;
8619
8620 --create new group
8621 g_consists(l_cur_consist_group).consist_string := g_lpns(v_current_row.lpn_id).consist_string;
8622 g_consists(l_cur_consist_group).first_rec := v_current_row.lpn_id;
8623 g_consists(l_cur_consist_group).last_rec := v_current_row.lpn_id;
8624 g_consists(l_cur_consist_group).next_group := 0;
8625 g_consists(l_cur_consist_group).quantity := v_current_row.quantity;
8626 g_consists(l_cur_consist_group).secondary_quantity := v_current_row.secondary_quantity;
8627 g_consists(l_cur_consist_group).grade_code := v_current_row.grade_code;
8628 g_consists(l_cur_consist_group).order_by_rank := g_lpns(v_current_row.lpn_id).order_by_rank;
8629
8630 IF g_first_consist_group = 0 THEN
8631 g_first_consist_group := l_cur_consist_group;
8632 ELSE
8633 g_consists(g_last_consist_group).next_group := l_cur_consist_group;
8634 END IF;
8635
8636 g_last_consist_group := l_cur_consist_group;
8637 END IF;
8638
8639 g_lpns(v_current_row.lpn_id).parent_consist_group := l_cur_consist_group;
8640
8641 --only allocate a consist group if the quantity = needed quantity
8642 --exactly
8643 --IF g_consists(l_cur_consist_group).quantity <> l_needed_quantity THEN
8644 IF g_consists(l_cur_consist_group).quantity < l_needed_quantity - l_max_tolerance THEN
8645
8646 IF l_debug = 1 THEN
8647 log_statement(l_api_name, 'not_enough_qty', 'Not enough quantity to allocate consist group');
8648 END IF;
8649
8650 GOTO nextoutputrecord;
8651 END IF;
8652
8653 IF g_consists(l_cur_consist_group).order_by_rank <> g_first_order_by_rank THEN
8654 IF l_debug = 1 THEN
8655 log_statement(l_api_name, 'consist_order_by', 'Consist group is not first based on sort criteria');
8656 END IF;
8657 GOTO nextoutputrecord;
8658 END IF;
8659
8660 l_lpn_id := g_consists(l_cur_consist_group).first_rec;
8661 -- no consists
8662 ELSIF g_lpns(v_current_row.lpn_id).order_by_rank <> g_first_order_by_rank THEN
8663
8664 IF l_debug = 1 THEN
8665 log_statement(l_api_name, 'not_first_order_by', 'Not first LPN based on sort criteria. Getting next record.');
8666 END IF;
8667 GOTO nextoutputrecord;
8668 ELSE
8669 l_lpn_id := v_current_row.lpn_id;
8670 END IF;
8671
8672 LOOP -- loop through LPNS
8673 --Allocation process. If consist exists, we loop through all
8674 -- the lpns in the consist group. If no consistency restrictions,
8675 -- we exit the loop after allocating the first lpn
8676
8677 IF l_debug = 1 THEN
8678 log_statement(l_api_name, 'alloc_lpn', 'Allocation lpn: ' || l_lpn_id);
8679 END IF;
8680
8681 --Allocate the LPN, since the LPN is in the first order by group
8682 -- and the LPN has all possible suggestions
8683 --For each record in LPN
8684 l_cur_lpn_rec := g_lpns(l_lpn_id).first_rec;
8685
8686 LOOP
8687 EXIT WHEN l_cur_lpn_rec = 0;
8688
8689 --Call validate and insert
8690 IF l_debug_on THEN
8691 g_trace_recs(l_cur_lpn_rec).consist_string_flag := 'Y';
8692 g_trace_recs(l_cur_lpn_rec).entire_lpn_flag := 'Y';
8693 END IF;
8694
8695 IF l_debug = 1 THEN
8696 log_statement(l_api_name, 'val_insert', 'Calling validate_and_insert');
8697 END IF;
8698
8699 validate_and_insert(
8700 x_return_status => x_return_status
8701 , x_msg_count => x_msg_count
8702 , x_msg_data => x_msg_data
8703 , p_record_id => l_cur_lpn_rec
8704 , p_needed_quantity => l_needed_quantity
8705 , p_use_pick_uom => FALSE
8706 , p_organization_id => p_organization_id
8707 , p_inventory_item_id => p_inventory_item_id
8708 , p_to_subinventory_code => l_to_subinventory_code
8709 , p_to_locator_id => l_to_locator_id
8710 , p_to_cost_group_id => l_to_cost_group_id
8711 , p_primary_uom => p_primary_uom
8712 , p_transaction_uom => p_transaction_uom
8713 , p_transaction_temp_id => p_transaction_temp_id
8714 , p_type_code => p_type_code
8715 , p_rule_id => l_rule_id
8716 , p_reservation_id => l_reservation_id
8717 , p_tree_id => p_tree_id
8718 , p_debug_on => l_debug_on
8719 , p_needed_sec_quantity => l_sec_needed_quantity
8720 , p_secondary_uom => p_secondary_uom
8721 , p_grade_code => p_grade_code
8722 , x_inserted_record => l_inserted_record
8723 , x_allocated_quantity => l_allocated_quantity
8724 , x_remaining_quantity => l_remaining_quantity
8725 , x_sec_allocated_quantity => l_sec_allocated_quantity
8726 , x_sec_remaining_quantity => l_sec_remaining_quantity
8727 );
8728
8729 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8730
8731 IF l_debug = 1 THEN
8732 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
8733 END IF;
8734
8735 RAISE fnd_api.g_exc_unexpected_error;
8736 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8737
8738 IF l_debug = 1 THEN
8739 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
8740 END IF;
8741
8742 RAISE fnd_api.g_exc_error;
8743 END IF;
8744
8745 --If this fails
8746 IF l_inserted_record = FALSE
8747 OR l_allocated_quantity < g_locs(l_cur_lpn_rec).quantity THEN
8748
8749 IF l_debug = 1 THEN
8750 log_statement(l_api_name, 'insert_fail', 'Record failed to insert.' || 'Invalidating LPN');
8751 END IF;
8752
8753 --invalidate LPN
8754 IF l_consist_exists THEN
8755 l_cur_consist_group := g_lpns(l_lpn_id).parent_consist_group;
8756 l_prev_rec := g_lpns(l_lpn_id).prev_consist_lpn_id;
8757 l_next_rec := g_lpns(l_lpn_id).next_consist_lpn_id;
8758 g_consists(l_cur_consist_group).quantity := g_consists(l_cur_consist_group).quantity - g_lpns(l_lpn_id).quantity;
8759 g_consists(l_cur_consist_group).secondary_quantity :=
8760 g_consists(l_cur_consist_group).secondary_quantity - g_lpns(l_lpn_id).secondary_quantity;
8761
8762 IF g_consists(l_cur_consist_group).first_rec = l_lpn_id THEN
8763 g_consists(l_cur_consist_group).first_rec := l_next_rec;
8764 g_consists(l_cur_consist_group).order_by_rank := g_lpns(l_next_rec).order_by_rank;
8765 END IF;
8766
8767 IF g_consists(l_cur_consist_group).last_rec = l_lpn_id THEN
8768 g_consists(l_cur_consist_group).last_rec := l_prev_rec;
8769 END IF;
8770
8771 g_lpns(l_next_rec).prev_consist_lpn_id := l_prev_rec;
8772 g_lpns(l_prev_rec).next_consist_lpn_id := l_next_rec;
8773 END IF;
8774
8775 invalidate_lpn_group(l_lpn_id);
8776 --restore quantity tree
8777
8778 IF l_debug = 1 THEN
8779 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
8780 END IF;
8781
8782 inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
8783
8784 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8785
8786 IF l_debug = 1 THEN
8787 log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
8788 END IF;
8789
8790 RAISE fnd_api.g_exc_unexpected_error;
8791 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8792
8793 IF l_debug = 1 THEN
8794 log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
8795 END IF;
8796
8797 RAISE fnd_api.g_exc_error;
8798 END IF;
8799
8800 --delete allocations
8801 --is this okay?? what if multiple input lines?
8802 DELETE FROM wms_transactions_temp
8803 WHERE line_type_code = 2
8804 AND type_code = p_type_code;
8805
8806 IF l_debug_on THEN
8807 l_cur_rec := g_lpns(l_lpn_id).first_rec;
8808
8809 LOOP
8810 g_trace_recs(l_cur_rec).entire_lpn_flag := 'N';
8811 g_trace_recs(l_cur_rec).suggested_qty := 0;
8812 EXIT WHEN l_cur_rec = l_cur_lpn_rec;
8813 l_cur_rec := g_locs(l_cur_rec).next_rec;
8814 END LOOP;
8815 END IF;
8816
8817 IF l_debug = 1 THEN
8818 log_statement(l_api_name, 'finish_delete_sugs', 'Finished deleting suggestions and restored quantity tree');
8819 END IF;
8820
8821 -- With this LPN invalidated, go get next record
8822 GOTO nextoutputrecord;
8823 END IF;
8824
8825 l_cur_lpn_rec := g_locs(l_cur_lpn_rec).next_rec;
8826 --end loop (each rec in lpn)
8827 END LOOP;
8828
8829 --decrease quantity needed
8830 l_needed_quantity := l_needed_quantity - g_lpns(l_lpn_id).quantity;
8831 l_sec_needed_quantity := l_sec_needed_quantity - g_lpns(l_lpn_id).secondary_quantity;
8832
8833 IF l_debug = 1 THEN
8834 log_statement(l_api_name, 'need_qty', 'New Needed Quantity: ' || l_needed_quantity);
8835 log_statement(l_api_name, 'need_qty', 'New sec Needed Quantity: ' || l_sec_needed_quantity);
8836 END IF;
8837
8838 --EXIT WHEN l_needed_quantity = 0;
8839 IF g_over_allocation = 'N'
8840 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8841 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
8842 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8843 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8844 IF l_max_tolerance >= 0 THEN
8845 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8846 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8847 ELSE
8848 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8849 END IF;
8850 END IF;
8851
8852 --Once LPN has been allocated, remove it from the LPN list
8853 IF l_consist_exists THEN
8854 l_lpn_id := g_lpns(l_lpn_id).next_consist_lpn_id;
8855 EXIT WHEN l_lpn_id = 0;
8856 ELSE
8857 invalidate_lpn_group(l_lpn_id);
8858 EXIT;
8859 END IF;
8860 END LOOP; -- loop through LPNS
8861
8862 -- EXIT WHEN l_needed_quantity <= 0;
8863 IF g_over_allocation = 'N'
8864 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
8865 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
8866 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
8867 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
8868 IF l_max_tolerance >= 0 THEN
8869 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
8870 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8871 ELSE
8872 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
8873 END IF;
8874 END IF;
8875
8876 <<nextoutputrecord>>
8877 NULL;
8878 --End outermost loop
8879 END LOOP;
8880 --else if type code = 2
8881 --PICK
8882 ELSIF p_type_code = 2 THEN
8883 l_cur_uom_rec := 0;
8884 l_first_uom_rec := 0;
8885 l_last_uom_rec := 0;
8886 l_cur_consist_group := 0;
8887 g_first_consist_group := 0;
8888
8889 IF l_debug = 1 THEN
8890 log_statement(l_api_name, 'start_alloc', 'Start allocation process');
8891 END IF;
8892
8893 --for each record returned from cursor
8894 LOOP --Get record from rules cursor
8895 IF l_debug = 1 THEN
8896 log_statement(l_api_name, 'fetch_cursor', 'Getting rec from rule with FetchCursor');
8897 END IF;
8898 -- Added the loop for Mat Stat check --
8899 LOOP
8900 if l_debug = 1 THEN
8901 log_statement(l_api_name, 'fetch_cursor', 'inside Mat Stat check LOOP');
8902 END IF;
8903 -- Mat Stat --
8904 fetchcursor(
8905 x_return_status
8906 , x_msg_count
8907 , x_msg_data
8908 , v_pick_cursor
8909 , l_rule_id
8910 , v_current_row.revision
8911 , v_current_row.lot_number
8912 , v_current_row.lot_expiration_date
8913 , v_current_row.subinventory_code
8914 , v_current_row.locator_id
8915 , v_current_row.cost_group_id
8916 , v_current_row.uom_code
8917 , v_current_row.lpn_id
8918 , v_current_row.serial_number
8919 , v_current_row.quantity
8920 , v_current_row.secondary_quantity -- new
8921 , v_current_row.grade_code -- new
8922 , v_current_row.consist_string
8923 , v_current_row.order_by_string
8924 , l_rows
8925 );
8926
8927 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
8928 IF l_debug = 1 THEN
8929 log_error(l_api_name, 'uerr_fetch_cursor', 'Unexpected error in FetchCursor');
8930 END IF;
8931 RAISE fnd_api.g_exc_unexpected_error;
8932 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
8933 IF l_debug = 1 THEN
8934 log_error(l_api_name, 'err_fetch_cursor', 'Error in FetchCursor');
8935 END IF;
8936 RAISE fnd_api.g_exc_error;
8937 END IF;
8938
8939 -- is_serial_trx_allowed is_sub_loc_lot_trx_allowed
8940 EXIT WHEN nvl(l_rows, 0) = 0 ; -- [ Added to to exit , if the rule is not returning any rows
8941 l_sub_loc_lot_trx_allowed := 'Y';
8942 l_serial_trx_allowed := 'Y';
8943 l_serial_status_id := 0;
8944
8945 IF l_debug = 1 THEN
8946 log_statement(l_api_name, 'Serial Status - l_detail_serial ', l_detail_serial);
8947 log_statement(l_api_name, 'fetch_cursor - l_rows ', l_rows);
8948 log_statement(l_api_name, 'fetch_cursor - v_current_row.lot_number ', v_current_row.lot_number);
8949 log_statement(l_api_name, 'fetch_cursor - v_current_row.serial_number ', v_current_row.serial_number);
8950 END IF;
8951 IF v_current_row.serial_number IS NOT NULL THEN
8952
8953 IF l_detail_serial = 1 THEN
8954 select status_id
8955 into l_serial_status_id
8956 from mtl_serial_numbers
8957 where inventory_item_id = p_inventory_item_id
8958 and current_organization_id = p_organization_id
8959 and serial_number = v_current_row.serial_number;
8960
8961 l_serial_trx_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
8962 p_transaction_type_id
8963 ,p_organization_id
8964 ,p_inventory_item_id
8965 ,l_serial_status_id) ;
8966 END IF;
8967 IF l_debug = 1 THEN
8968
8969 log_statement(l_api_name, 'Serial Status - p_transaction_type_id ', p_transaction_type_id);
8970 log_statement(l_api_name, 'Serial Status - p_organization_id ', p_organization_id);
8971 log_statement(l_api_name, 'Serial Status - p_inventory_item_id ', p_inventory_item_id);
8972 log_statement(l_api_name, 'Serial Status - serial_number ', v_current_row.serial_number);
8973 log_statement(l_api_name, 'Serial Status - l_serial_status_id ', l_serial_status_id);
8974 log_statement(l_api_name, 'Serial Status - l_serial_trx_allowed ', l_serial_trx_allowed);
8975
8976 END IF;
8977 END IF;
8978 -- Bug 4756156
8979 -- IF ((v_current_row.lot_number IS NOT NULL) AND (l_lot_status = 'Y')) THEN
8980 -- LPN Status Project
8981 l_onhand_status_trx_allowed := 'Y';
8982 IF l_default_status_id = -1 THEN
8983 l_onhand_status_trx_allowed := 'N';
8984 l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
8985 p_transaction_type_id
8986 ,p_organization_id
8987 ,p_inventory_item_id
8988 ,v_current_row.subinventory_code
8989 ,v_current_row.locator_id
8990 ,v_current_row.lot_number);
8991
8992 /*log_statement(l_api_name, 'Stasus', 'Before calling my method-Amrita);
8993 l_sub_loc_lot_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
8994 p_transaction_type_id
8995 ,p_organization_id
8996 ,p_inventory_item_id
8997 ,v_current_row.subinventory_code
8998 ,v_current_row.locator_id
8999 ,v_current_row.lot_number);*/
9000 IF l_debug = 1 THEN
9001 log_statement(l_api_name, 'fetch_cursor - l_sub_loc_lot_trx_allowed: ', l_sub_loc_lot_trx_allowed);
9002 END IF;
9003
9004 ELSE
9005 l_sub_loc_lot_trx_allowed:='N';
9006 if (inv_cache.item_rec.serial_number_control_code in (1,6)) then
9007 l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
9008 p_transaction_type_id
9009 ,p_organization_id
9010 ,p_inventory_item_id
9011 ,v_current_row.subinventory_code
9012 ,v_current_row.locator_id
9013 ,v_current_row.lot_number
9014 , v_current_row.lpn_id);
9015 end if;
9016 IF l_debug = 1 THEN
9017 log_statement(l_api_name, 'fetch_cursor - l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
9018 END IF;
9019 END IF;
9020
9021 -- END IF;
9022 EXIT WHEN ( l_serial_trx_allowed = 'Y'
9023 and (l_sub_loc_lot_trx_allowed = 'Y' OR l_onhand_status_trx_allowed='Y'));
9024
9025 -- >> Else fetch next record from the rule cursor --
9026 END LOOP;
9027 -- End of Mat Stat Check --
9028 -- LPN Status Project
9029
9030 v_current_row.next_rec := 0;
9031
9032 --if no more records
9033 IF l_rows = 0 THEN
9034 IF l_debug = 1 THEN
9035 log_statement(l_api_name, 'no_recs', 'No more records from cursor');
9036 END IF;
9037
9038
9039 -- (FOR R12.1 REPLENISHMENT PROJECT - 6681109) STARTS ---
9040 -- IN R12 BRANCH , the code will not do any harm as the allocation mode = 5 value
9041 -- is only available in R12 Main Line code and the logic in contained WITH value = here
9042
9043 -- if allocation mode = 5
9044 IF l_allocation_mode = 5
9045 AND l_first_uom_rec <> 0 and l_needed_quantity > 0 THEN
9046 -- After all location-based records (from where there was possibility of getting allocation in the
9047 -- first round of scan) gets exhausted, it comes here for the second round of scan. At that point,
9048 -- we know the final unallocated qty after the first round of scan and that is the qty which are
9049 -- candidate for replenishment
9050
9051 IF l_debug = 1 THEN
9052 log_statement(l_api_name, 'exit_final_unallocated_qty',
9053 'Can not allocate any further with pick UOM for current input RECORD - COMING out of the outer loop');
9054 END IF;
9055
9056 EXIT; -- Can not allocate any further; so come out of the outer loop
9057
9058 -- (FOR R12.1 REPLENISHMENT PROJECT - 6681109) ENDS ---
9059
9060 --if allocation mode IN 3,4
9061 ELSIF l_allocation_mode IN (3, 4)
9062 AND l_first_uom_rec <> 0 THEN
9063 --for each record in pick uom list
9064 IF l_debug = 1 THEN
9065 log_statement(l_api_name, 'pick_uom', 'Allocate pick UOM table');
9066 END IF;
9067 LOOP
9068 l_cur_uom_rec := l_first_uom_rec;
9069 EXIT WHEN l_cur_uom_rec = 0;
9070 --remove rec from list
9071 l_first_uom_rec := g_locs(l_cur_uom_rec).next_rec;
9072 g_locs(l_cur_uom_rec).next_rec := 0;
9073
9074 --If consist restrictions
9075 IF l_consist_exists THEN
9076
9077 IF l_debug = 1 THEN
9078 log_statement(l_api_name, 'insert_consist', 'Calling Insert_Consist_Record');
9079 END IF;
9080
9081 --call insert consist record
9082 insert_consist_record(
9083 x_return_status => x_return_status
9084 , x_msg_count => x_msg_count
9085 , x_msg_data => x_msg_data
9086 , p_record_id => l_cur_uom_rec
9087 , p_needed_quantity => l_needed_quantity
9088 , p_use_pick_uom => FALSE
9089 , p_organization_id => p_organization_id
9090 , p_inventory_item_id => p_inventory_item_id
9091 , p_to_subinventory_code => l_to_subinventory_code
9092 , p_to_locator_id => l_to_locator_id
9093 , p_to_cost_group_id => l_to_cost_group_id
9094 , p_primary_uom => p_primary_uom
9095 , p_transaction_uom => p_transaction_uom
9096 , p_transaction_temp_id => p_transaction_temp_id
9097 , p_type_code => p_type_code
9098 , p_rule_id => l_rule_id
9099 , p_reservation_id => l_reservation_id
9100 , p_tree_id => p_tree_id
9101 , p_debug_on => l_debug_on
9102 , p_order_by_rank => l_order_by_rank
9103 , p_needed_sec_quantity => l_sec_needed_quantity
9104 , p_secondary_uom => p_secondary_uom
9105 , p_grade_code => p_grade_code
9106 , x_finished => l_finished
9107 , x_remaining_quantity => l_remaining_quantity
9108 );
9109
9110 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9111 IF l_debug = 1 THEN
9112 log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
9113 END IF;
9114 RAISE fnd_api.g_exc_unexpected_error;
9115 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9116 IF l_debug = 1 THEN
9117 log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
9118 END IF;
9119 RAISE fnd_api.g_exc_error;
9120 END IF;
9121
9122 --if allocated a consist group, exit pick uom loop
9123 IF l_finished THEN
9124 IF l_debug = 1 THEN
9125 log_statement(l_api_name, 'consist_finished', 'Allocated all needed quantity with consist group');
9126 END IF;
9127 l_needed_quantity := 0;
9128 l_sec_needed_quantity := 0;
9129 EXIT;
9130 END IF;
9131 --else no consist restrictions
9132 ELSE
9133 IF l_debug = 1 THEN
9134 log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_Insert');
9135 END IF;
9136 --call Validate and insert
9137 validate_and_insert(
9138 x_return_status => x_return_status
9139 , x_msg_count => x_msg_count
9140 , x_msg_data => x_msg_data
9141 , p_record_id => l_cur_uom_rec
9142 , p_needed_quantity => l_needed_quantity
9143 , p_use_pick_uom => FALSE
9144 , p_organization_id => p_organization_id
9145 , p_inventory_item_id => p_inventory_item_id
9146 , p_to_subinventory_code => l_to_subinventory_code
9147 , p_to_locator_id => l_to_locator_id
9148 , p_to_cost_group_id => l_to_cost_group_id
9149 , p_primary_uom => p_primary_uom
9150 , p_transaction_uom => p_transaction_uom
9151 , p_transaction_temp_id => p_transaction_temp_id
9152 , p_type_code => p_type_code
9153 , p_rule_id => l_rule_id
9154 , p_reservation_id => l_reservation_id
9155 , p_tree_id => p_tree_id
9156 , p_debug_on => l_debug_on
9157 , p_needed_sec_quantity => l_sec_needed_quantity
9158 , p_secondary_uom => p_secondary_uom
9159 , p_grade_code => p_grade_code
9160 , x_inserted_record => l_inserted_record
9161 , x_allocated_quantity => l_allocated_quantity
9162 , x_remaining_quantity => l_remaining_quantity
9163 , x_sec_allocated_quantity => l_sec_allocated_quantity
9164 , x_sec_remaining_quantity => l_sec_remaining_quantity
9165 );
9166
9167 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9168 IF l_debug = 1 THEN
9169 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9170 END IF;
9171 RAISE fnd_api.g_exc_unexpected_error;
9172 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9173 IF l_debug = 1 THEN
9174 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9175 END IF;
9176 RAISE fnd_api.g_exc_error;
9177 END IF;
9178
9179 --If returns true, decrease needed quantity
9180 IF l_inserted_record THEN
9181 l_needed_quantity := l_needed_quantity - l_allocated_quantity;
9182 l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
9183 IF l_debug = 1 THEN
9184 log_statement(l_api_name, 'need_qty', 'New Needed quantity: ' || l_needed_quantity);
9185 log_statement(l_api_name, 'sec need_qty', 'sec New Needed quantity: ' || l_sec_needed_quantity);
9186 END IF;
9187 END IF;
9188 END IF; -- consist records
9189
9190 --exit pick UOM loop when needed qty = 0
9191 --EXIT WHEN l_needed_quantity = 0;
9192 IF g_over_allocation = 'N'
9193 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9194 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
9195 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9196 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9197 IF l_max_tolerance >= 0 THEN
9198 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9199 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9200 ELSE
9201 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9202 END IF;
9203 END IF;
9204 --end loop (pick UOM)
9205 l_cur_uom_rec := g_locs(l_cur_uom_rec).next_rec;
9206 END LOOP; --pick UOM
9207
9208 --if needed qty = 0, exit outer loop
9209 --EXIT WHEN l_needed_quantity = 0;
9210 IF g_over_allocation = 'N'
9211 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9212 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
9213 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9214 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9215 IF l_max_tolerance >= 0 THEN
9216 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9217 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9218 ELSE
9219 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9220 END IF;
9221 END IF;
9222 END IF; --allocation mode in 3,4
9223
9224 --if consist restrictions
9225 IF l_consist_exists THEN
9226
9227 IF l_debug = 1 THEN
9228 log_statement(l_api_name, 'consist', 'Reading from consist groups');
9229 END IF;
9230 --for each record in consist group
9231 l_cur_consist_group := g_first_consist_group;
9232
9233 IF l_debug = 1 THEN
9234 log_statement(l_api_name, 'first_consist', 'First consist group:' || g_first_consist_group);
9235 END IF;
9236
9237 LOOP
9238 EXIT WHEN l_cur_consist_group = 0;
9239
9240 --if group alloc qty > needed qty
9241 IF g_consists(l_cur_consist_group).quantity >= l_needed_quantity THEN
9242 IF l_debug = 1 THEN
9243 log_statement(l_api_name, 'alloc_consist', 'Found a consist group to allocate');
9244 END IF;
9245 --call allocate_consist_group
9246 allocate_consist_group(
9247 x_return_status => x_return_status
9248 , x_msg_count => x_msg_count
9249 , x_msg_data => x_msg_data
9250 , p_group_id => l_cur_consist_group
9251 , p_needed_quantity => l_needed_quantity
9252 , p_use_pick_uom => FALSE
9253 , p_organization_id => p_organization_id
9254 , p_inventory_item_id => p_inventory_item_id
9255 , p_to_subinventory_code => l_to_subinventory_code
9256 , p_to_locator_id => l_to_locator_id
9257 , p_to_cost_group_id => l_to_cost_group_id
9258 , p_primary_uom => p_primary_uom
9259 , p_transaction_uom => p_transaction_uom
9260 , p_transaction_temp_id => p_transaction_temp_id
9261 , p_type_code => p_type_code
9262 , p_rule_id => l_rule_id
9263 , p_reservation_id => l_reservation_id
9264 , p_tree_id => p_tree_id
9265 , p_debug_on => l_debug_on
9266 , p_needed_sec_quantity => l_sec_needed_quantity
9267 , p_secondary_uom => p_secondary_uom
9268 , p_grade_code => p_grade_code
9269 , p_lot_divisible_flag => inv_cache.item_rec.lot_divisible_flag
9270 , x_success => l_finished
9271 );
9272
9273 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9274 IF l_debug = 1 THEN
9275 log_statement(l_api_name, 'uerr_allocate_consist', 'Unexpected error in allocate_consist_group');
9276 END IF;
9277 RAISE fnd_api.g_exc_unexpected_error;
9278 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9279 IF l_debug = 1 THEN
9280 log_statement(l_api_name, 'err_allocate_consist', 'Error in allocate_consist_group');
9281 END IF;
9282 RAISE fnd_api.g_exc_error;
9283 END IF;
9284
9285 --if finished = true
9286 --exit consist restrictions loop
9287 IF l_finished THEN
9288 IF l_debug = 1 THEN
9289 log_statement(l_api_name, 'allocated_consist', 'Successfully allocated consistency group');
9290 END IF;
9291 l_needed_quantity := 0;
9292 l_sec_needed_quantity := 0;
9293 EXIT;
9294 END IF;
9295 END IF;
9296
9297 --end consist loop
9298 l_cur_consist_group := g_consists(l_cur_consist_group).next_group;
9299
9300 IF l_debug = 1 THEN
9301 log_statement(l_api_name, 'next_consist', 'Next consist group: ' || l_cur_consist_group);
9302 END IF;
9303
9304 END LOOP;
9305 --Exit outermost loop
9306 END IF; -- consist records
9307
9308 IF l_debug = 1 THEN
9309 log_statement(l_api_name, 'end_alloc', 'No more pick UOM or ' || 'consistecy records to Allocate.');
9310 END IF;
9311
9312 EXIT;
9313 END IF; --no more record
9314
9315 IF l_debug = 1 THEN
9316 log_statement(l_api_name, 'order_string', 'Checking order string');
9317 END IF;
9318
9319 --if allocation mode = 3 and record has different order by string
9320 IF l_allocation_mode = 3
9321 AND l_first_uom_rec <> 0
9322 AND v_current_row.order_by_string <> l_cur_order_by_string THEN
9323
9324 IF l_debug = 1 THEN
9325 log_statement(l_api_name, 'change string', 'The order_by_string has changed. Reading from pick UOM list');
9326 END IF;
9327
9328 l_cur_uom_rec := l_first_uom_rec;
9329
9330 LOOP
9331 EXIT WHEN l_cur_uom_rec = 0;
9332
9333 --If consist restrictions
9334 IF l_consist_exists THEN
9335
9336 IF l_debug = 1 THEN
9337 log_statement(l_api_name, 'insert_consist', 'Calling insert consist record from pick UOM list');
9338 END IF;
9339
9340 --call insert consist record
9341 insert_consist_record(
9342 x_return_status => x_return_status
9343 , x_msg_count => x_msg_count
9344 , x_msg_data => x_msg_data
9345 , p_record_id => l_cur_uom_rec
9346 , p_needed_quantity => l_needed_quantity
9347 , p_use_pick_uom => FALSE
9348 , p_organization_id => p_organization_id
9349 , p_inventory_item_id => p_inventory_item_id
9350 , p_to_subinventory_code => l_to_subinventory_code
9351 , p_to_locator_id => l_to_locator_id
9352 , p_to_cost_group_id => l_to_cost_group_id
9353 , p_primary_uom => p_primary_uom
9354 , p_transaction_uom => p_transaction_uom
9355 , p_transaction_temp_id => p_transaction_temp_id
9356 , p_type_code => p_type_code
9357 , p_rule_id => l_rule_id
9358 , p_reservation_id => l_reservation_id
9359 , p_tree_id => p_tree_id
9360 , p_debug_on => l_debug_on
9361 , p_order_by_rank => l_order_by_rank
9362 , p_needed_sec_quantity => l_sec_needed_quantity
9363 , p_secondary_uom => p_secondary_uom
9364 , p_grade_code => p_grade_code
9365 , x_finished => l_finished
9366 , x_remaining_quantity => l_remaining_quantity
9367 );
9368
9369 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9370 IF l_debug = 1 THEN
9371 log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
9372 END IF;
9373 RAISE fnd_api.g_exc_unexpected_error;
9374 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9375 IF l_debug = 1 THEN
9376 log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
9377 END IF;
9378 RAISE fnd_api.g_exc_error;
9379 END IF;
9380
9381 --if allocated a consist group, exit pick uom loop
9382 IF l_finished THEN
9383
9384 IF l_debug = 1 THEN
9385 log_statement(l_api_name, 'finish_consist', 'Successfully allocated a consistency group');
9386 END IF;
9387
9388 l_needed_quantity := 0;
9389 l_sec_needed_quantity := 0;
9390 EXIT;
9391 END IF;
9392 --else no consist restrictions
9393 ELSE
9394
9395 IF l_debug = 1 THEN
9396 log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_insert for pick uom list');
9397 END IF;
9398
9399 --call Validate and insert
9400 validate_and_insert(
9401 x_return_status => x_return_status
9402 , x_msg_count => x_msg_count
9403 , x_msg_data => x_msg_data
9404 , p_record_id => l_cur_uom_rec
9405 , p_needed_quantity => l_needed_quantity
9406 , p_use_pick_uom => FALSE
9407 , p_organization_id => p_organization_id
9408 , p_inventory_item_id => p_inventory_item_id
9409 , p_to_subinventory_code => l_to_subinventory_code
9410 , p_to_locator_id => l_to_locator_id
9411 , p_to_cost_group_id => l_to_cost_group_id
9412 , p_primary_uom => p_primary_uom
9413 , p_transaction_uom => p_transaction_uom
9414 , p_transaction_temp_id => p_transaction_temp_id
9415 , p_type_code => p_type_code
9416 , p_rule_id => l_rule_id
9417 , p_reservation_id => l_reservation_id
9418 , p_tree_id => p_tree_id
9419 , p_debug_on => l_debug_on
9420 , p_needed_sec_quantity => l_sec_needed_quantity
9421 , p_secondary_uom => p_secondary_uom
9422 , p_grade_code => p_grade_code
9423 , x_inserted_record => l_inserted_record
9424 , x_allocated_quantity => l_allocated_quantity
9425 , x_remaining_quantity => l_remaining_quantity
9426 , x_sec_allocated_quantity => l_sec_allocated_quantity
9427 , x_sec_remaining_quantity => l_sec_remaining_quantity
9428 );
9429
9430 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9431 IF l_debug = 1 THEN
9432 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9433 END IF;
9434 RAISE fnd_api.g_exc_unexpected_error;
9435 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9436 IF l_debug = 1 THEN
9437 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9438 END IF;
9439 RAISE fnd_api.g_exc_error;
9440 END IF;
9441
9442 --If returns true, decrease needed quantity
9443 IF l_inserted_record THEN
9444 l_needed_quantity := l_needed_quantity - l_allocated_quantity;
9445 l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
9446
9447 IF l_debug = 1 THEN
9448 log_statement(l_api_name, 'success_validate', 'Successfully inserted record. New needed quantity: ' || l_needed_quantity);
9449 log_statement(l_api_name, 'success_validate', 'Successfully inserted record. sec New needed quantity: ' || l_sec_needed_quantity);
9450 END IF;
9451
9452 END IF;
9453 END IF; -- consist records
9454
9455 --exit pick UOM loop when needed qty = 0
9456 --EXIT WHEN l_needed_quantity = 0;
9457 IF g_over_allocation = 'N'
9458 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9459 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
9460 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9461 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9462 IF l_max_tolerance >= 0 THEN
9463 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9464 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9465 ELSE
9466 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9467 END IF;
9468 END IF;
9469 l_cur_uom_rec := g_locs(l_cur_uom_rec).next_rec;
9470 --end loop (pick UOM)
9471 END LOOP; --pick UOM
9472
9473 IF l_debug = 1 THEN
9474 log_statement(l_api_name, 'end_pick_uom', 'End Pick UOM loop');
9475 END IF;
9476
9477 l_first_uom_rec := 0;
9478 l_cur_uom_rec := 0;
9479 l_last_uom_rec := 0;
9480 END IF;
9481
9482 --EXIT WHEN l_needed_quantity = 0;
9483 IF g_over_allocation = 'N'
9484 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
9485 OR WMS_Engine_PVT.g_move_order_type <> 3 THEN
9486 EXIT WHEN l_needed_quantity <= 0 or l_needed_quantity <= l_max_tolerance;
9487 ELSIF g_over_allocation = 'Y' AND p_type_code = 2 AND WMS_Engine_PVT.g_move_order_type = 3 THEN
9488 IF l_max_tolerance >= 0 THEN
9489 EXIT WHEN (l_needed_quantity <= l_max_tolerance)
9490 OR (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9491 ELSE
9492 EXIT WHEN (l_initial_pri_quantity - l_needed_quantity >= WMS_RULE_PVT.g_min_qty_to_allocate);
9493 END IF;
9494 END IF;
9495
9496 IF NVL(l_cur_order_by_string, '@@@') <> NVL(v_current_row.order_by_string, '@@@') THEN
9497
9498 IF l_debug = 1 THEN
9499 log_statement(l_api_name, 'order_rank', 'Setting order rank');
9500 END IF;
9501
9502 l_order_by_rank := l_order_by_rank + 1;
9503 l_cur_order_by_string := v_current_row.order_by_string;
9504
9505 IF g_first_order_by_rank IS NULL THEN
9506 log_statement(l_api_name, 'first_order', 'Setting first order rank');
9507 g_first_order_by_rank := l_order_by_rank;
9508 END IF;
9509 END IF;
9510
9511 g_locs_index := g_locs_index + 1;
9512
9513 IF l_debug = 1 THEN
9514 log_statement(l_api_name, 'loc_index', 'New loc index: ' || g_locs_index);
9515 END IF;
9516
9517 g_locs(g_locs_index) := v_current_row;
9518
9519 --initialize trace records
9520 IF l_debug_on THEN
9521
9522 IF l_debug = 1 THEN
9523 log_statement(l_api_name, 'trace_init', 'Init Trace Record');
9524 END IF;
9525
9526 g_trace_recs(g_locs_index).revision := v_current_row.revision;
9527 g_trace_recs(g_locs_index).lot_number := v_current_row.lot_number;
9528 g_trace_recs(g_locs_index).lot_expiration_date := v_current_row.lot_expiration_date;
9529 g_trace_recs(g_locs_index).subinventory_code := v_current_row.subinventory_code;
9530 g_trace_recs(g_locs_index).locator_id := v_current_row.locator_id;
9531 g_trace_recs(g_locs_index).cost_group_id := v_current_row.cost_group_id;
9532 g_trace_recs(g_locs_index).lpn_id := v_current_row.lpn_id;
9533 g_trace_recs(g_locs_index).uom_code := v_current_row.uom_code;
9534 g_trace_recs(g_locs_index).quantity := v_current_row.quantity;
9535 g_trace_recs(g_locs_index).secondary_qty := v_current_row.secondary_quantity;
9536 g_trace_recs(g_locs_index).grade_code := v_current_row.grade_code;
9537 g_trace_recs(g_locs_index).serial_number := v_current_row.serial_number;
9538 g_trace_recs(g_locs_index).consist_string_flag := 'V';
9539 g_trace_recs(g_locs_index).partial_pick_flag := 'Y';
9540 g_trace_recs(g_locs_index).order_string_flag := 'Y';
9541 g_trace_recs(g_locs_index).pick_uom_flag := 'V';
9542 g_trace_recs(g_locs_index).serial_number_used_flag := 'V';
9543 g_trace_recs(g_locs_index).entire_lpn_flag := 'V';
9544 --write to log file
9545
9546 IF l_debug = 1 THEN
9547 log_statement(l_api_name, 'rev', 'revision: ' || v_current_row.revision);
9548 log_statement(l_api_name, 'lot', 'lot: ' || v_current_row.lot_number);
9549 log_statement(l_api_name, 'sub', 'sub:' || v_current_row.subinventory_code);
9550 log_statement(l_api_name, 'loc', 'loc: ' || v_current_row.locator_id);
9551 log_statement(l_api_name, 'cg', 'cg: ' || v_current_row.cost_group_id);
9552 log_statement(l_api_name, 'lpn', 'lpn: ' || v_current_row.lpn_id);
9553 log_statement(l_api_name, 'sn', 'sn: ' || v_current_row.serial_number);
9554 log_statement(l_api_name, 'qty', 'quantity: ' || v_current_row.quantity);
9555 log_statement(l_api_name, 'sqty', 'sec_quantity: ' || v_current_row.secondary_quantity);
9556 log_statement(l_api_name, 'grade', 'grade_code: ' || v_current_row.grade_code);
9557 log_statement(l_api_name, 'uom', 'uom_code: ' || v_current_row.uom_code);
9558 log_statement(l_api_name, 'suom', 'sec_uom_code: ' || v_current_row.secondary_uom_code);
9559 log_statement(l_api_name, 'ord', 'order:' || v_current_row.order_by_string);
9560 log_statement(l_api_name, 'con', 'consist:' || v_current_row.consist_string);
9561 END IF;
9562
9563 END IF;
9564
9565 IF l_debug = 1 THEN
9566 log_statement(l_api_name, 'valid_sub', 'Validating sub');
9567 END IF;
9568
9569 --validate from/to sub/loc
9570 --if fail, goto next output record
9571 --first check to make sure picking from dest sub is not allowed;
9572 --then, based on type code, compare src sub to dest sub;
9573 --next, check to see if sub and item are locator controlled;
9574 --if loc control, go to next record only if src loc = dest loc;
9575 --if not loc control, go to next records (since subs are equal);
9576 --all of the global variables are set in
9577 --wms_engine_pvt.create_suggestions
9578 IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
9579 AND v_current_row.subinventory_code = l_to_subinventory_code
9580 ) THEN
9581 IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
9582 OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
9583 OR (wms_engine_pvt.g_sub_loc_control = 5
9584 AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
9585 )
9586 ) THEN
9587 IF (v_current_row.locator_id = l_to_locator_id) THEN
9588
9589 IF l_debug = 1 THEN
9590 log_event(
9591 l_api_name
9592 , 'sub_loc_same'
9593 , 'Cannot use this ' || 'location since source subinventory and locator are' || ' same as destination subinventory and locator'
9594 );
9595 END IF;
9596
9597 IF l_debug_on THEN
9598 g_trace_recs(g_locs_index).same_subinv_loc_flag := 'N';
9599 END IF;
9600
9601 GOTO nextoutputrecord2;
9602 END IF;
9603 ELSE
9604
9605 IF l_debug = 1 THEN
9606 log_event(
9607 l_api_name
9608 , 'sub_same'
9609 , 'Cannot use this ' || 'location since source subinventory is ' || 'same as destination subinventory'
9610 );
9611 END IF;
9612
9613 IF l_debug_on THEN
9614 g_trace_recs(g_locs_index).same_subinv_loc_flag := 'N';
9615 END IF;
9616
9617 GOTO nextoutputrecord2;
9618 END IF;
9619 END IF;
9620
9621 IF l_debug_on THEN
9622 g_trace_recs(g_locs_index).same_subinv_loc_flag := 'Y';
9623 END IF;
9624
9625 --If consistency restrictions
9626 IF l_consist_exists THEN
9627
9628 IF l_debug = 1 THEN
9629 log_statement(l_api_name, 'query_tree', 'Querying the quantity tree' || ' to find availability for consist record');
9630 END IF;
9631 -- BUG 3609380 : Removing l_to_subinevntory_code.
9632 --Validate available quantity
9633 inv_quantity_tree_pvt.query_tree
9634 (
9635 p_api_version_number => g_qty_tree_api_version
9636 , p_init_msg_lst => fnd_api.g_false -- p_init_msg_lst
9637 , x_return_status => x_return_status
9638 , x_msg_count => x_msg_count
9639 , x_msg_data => x_msg_data
9640 , p_tree_id => p_tree_id
9641 , p_revision => v_current_row.revision
9642 , p_lot_number => v_current_row.lot_number
9643 , p_subinventory_code => v_current_row.subinventory_code
9644 , p_locator_id => v_current_row.locator_id
9645 , x_qoh => l_qoh
9646 , x_sqoh => l_sqoh
9647 , x_rqoh => l_rqoh
9648 , x_srqoh => l_srqoh
9649 , x_qr => l_qr
9650 , x_sqr => l_sqr
9651 , x_qs => l_qs
9652 , x_sqs => l_sqs
9653 , x_att => l_att
9654 , x_satt => l_satt
9655 , x_atr => l_atr
9656 , x_satr => l_satr
9657 , p_transfer_subinventory_code => chk_for_passing_xfer_sub ( p_transaction_temp_id , l_to_subinventory_code) -- Bug# 4099907
9658 , p_cost_group_id => v_current_row.cost_group_id
9659 , p_lpn_id => v_current_row.lpn_id
9660 );
9661
9662 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9663 IF l_debug = 1 THEN
9664 log_statement(l_api_name, 'uerr_qty_tree', 'Unexpected error in inv_quantity_tree_Pvt.query_tree');
9665 END IF;
9666 RAISE fnd_api.g_exc_unexpected_error;
9667 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9668 IF l_debug = 1 THEN
9669 log_statement(l_api_name, 'err_qty_tree', 'Error in inv_quantity_tree_Pvt.query_tree');
9670 END IF;
9671 RAISE fnd_api.g_exc_error;
9672 END IF;
9673
9674 IF l_debug = 1 THEN
9675 log_statement(l_api_name, 'att', 'ATT : ' || l_att);
9676 END IF;
9677
9678 --If att<=0, goto next output rec
9679 IF l_att <= 0 THEN
9680
9681 IF l_debug = 1 THEN
9682 log_statement(l_api_name, 'no_att', 'No ATT for this record. ' || 'Getting next record');
9683 END IF;
9684
9685 IF l_debug_on THEN
9686 g_trace_recs(g_locs_index).att_qty := l_att;
9687 g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
9688 g_trace_recs(g_locs_index).att_qty_flag := 'N';
9689 END IF;
9690
9691 GOTO nextoutputrecord2;
9692 END IF;
9693
9694 IF l_debug_on THEN
9695 g_trace_recs(g_locs_index).att_qty := l_att;
9696 g_trace_recs(g_locs_index).secondary_att_qty := l_satt;
9697 g_trace_recs(g_locs_index).att_qty_flag := 'Y';
9698 END IF;
9699
9700 IF l_att < v_current_row.quantity THEN
9701
9702 IF l_debug = 1 THEN
9703 log_statement(l_api_name, 'less_att', 'ATT is less than onhand ' || 'quantity. Reducing quantity');
9704 END IF;
9705
9706 g_locs(g_locs_index).quantity := l_att;
9707 END IF;
9708
9709 IF l_debug = 1 THEN
9710 --Insert_consist_record
9711 log_statement(l_api_name, 'insert_consist', 'Calling Insert_Consist_Record');
9712 END IF;
9713
9714 --init consist flag to N. It gets set to yes in Alloc. Consist. Group
9715 IF l_debug_on THEN
9716 g_trace_recs(g_locs_index).consist_string_flag := 'N';
9717 END IF;
9718
9719 insert_consist_record(
9720 x_return_status => x_return_status
9721 , x_msg_count => x_msg_count
9722 , x_msg_data => x_msg_data
9723 , p_record_id => g_locs_index
9724 , p_needed_quantity => l_needed_quantity
9725 , p_use_pick_uom => l_use_pick_uom
9726 , p_organization_id => p_organization_id
9727 , p_inventory_item_id => p_inventory_item_id
9728 , p_to_subinventory_code => l_to_subinventory_code
9729 , p_to_locator_id => l_to_locator_id
9730 , p_to_cost_group_id => l_to_cost_group_id
9731 , p_primary_uom => p_primary_uom
9732 , p_transaction_uom => p_transaction_uom
9733 , p_transaction_temp_id => p_transaction_temp_id
9734 , p_type_code => p_type_code
9735 , p_rule_id => l_rule_id
9736 , p_reservation_id => l_reservation_id
9737 , p_tree_id => p_tree_id
9738 , p_debug_on => l_debug_on
9739 , p_order_by_rank => l_order_by_rank
9740 , p_needed_sec_quantity => l_sec_needed_quantity
9741 , p_secondary_uom => p_secondary_uom
9742 , p_grade_code => p_grade_code
9743 , x_finished => l_finished
9744 , x_remaining_quantity => l_remaining_quantity
9745 );
9746
9747 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9748 IF l_debug = 1 THEN
9749 log_statement(l_api_name, 'uerr_insert_consist', 'Unexpected error in insert_consist_record');
9750 END IF;
9751 RAISE fnd_api.g_exc_unexpected_error;
9752 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9753 IF l_debug = 1 THEN
9754 log_statement(l_api_name, 'err_insert_consist', 'Error in insert_consist_record');
9755 END IF;
9756 RAISE fnd_api.g_exc_error;
9757 END IF;
9758
9759 --if finished, needed qty = 0
9760 IF l_finished THEN
9761 IF l_debug = 1 THEN
9762 log_statement(l_api_name, 'finished', 'Successfully allocated ' || 'consistency group');
9763 END IF;
9764 l_needed_quantity := 0;
9765 l_sec_needed_quantity := 0;
9766 EXIT;
9767 END IF;
9768 --else no consist
9769 ELSE
9770 IF l_debug = 1 THEN
9771 log_statement(l_api_name, 'validate_insert', 'Calling Validate_and_insert');
9772 END IF;
9773 --call validate and insert
9774 validate_and_insert(
9775 x_return_status => x_return_status
9776 , x_msg_count => x_msg_count
9777 , x_msg_data => x_msg_data
9778 , p_record_id => g_locs_index
9779 , p_needed_quantity => l_needed_quantity
9780 , p_use_pick_uom => l_use_pick_uom
9781 , p_organization_id => p_organization_id
9782 , p_inventory_item_id => p_inventory_item_id
9783 , p_to_subinventory_code => l_to_subinventory_code
9784 , p_to_locator_id => l_to_locator_id
9785 , p_to_cost_group_id => l_to_cost_group_id
9786 , p_primary_uom => p_primary_uom
9787 , p_transaction_uom => p_transaction_uom
9788 , p_transaction_temp_id => p_transaction_temp_id
9789 , p_type_code => p_type_code
9790 , p_rule_id => l_rule_id
9791 , p_reservation_id => l_reservation_id
9792 , p_tree_id => p_tree_id
9793 , p_debug_on => l_debug_on
9794 , p_needed_sec_quantity => l_sec_needed_quantity
9795 , p_secondary_uom => p_secondary_uom
9796 , p_grade_code => p_grade_code
9797 , x_inserted_record => l_inserted_record
9798 , x_allocated_quantity => l_allocated_quantity
9799 , x_remaining_quantity => l_remaining_quantity
9800 , x_sec_allocated_quantity => l_sec_allocated_quantity
9801 , x_sec_remaining_quantity => l_sec_remaining_quantity
9802 );
9803
9804 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9805 IF l_debug = 1 THEN
9806 log_statement(l_api_name, 'uerr_validate_insert', 'Unexpected error in validate_and_insert');
9807 END IF;
9808 RAISE fnd_api.g_exc_unexpected_error;
9809 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9810 IF l_debug = 1 THEN
9811 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
9812 END IF;
9813 RAISE fnd_api.g_exc_error;
9814 END IF;
9815
9816 --if returns true, decrease needed qty
9817 IF l_inserted_record THEN
9818 l_needed_quantity := l_needed_quantity - l_allocated_quantity;
9819 l_sec_needed_quantity := l_sec_needed_quantity - l_sec_allocated_quantity;
9820 IF l_debug = 1 THEN
9821 log_statement(l_api_name, 'inserted_rec', 'Inserted record. New needed quantity: ' || l_needed_quantity);
9822 log_statement(l_api_name, 'inserted_rec', 'Inserted record. sec New needed quantity: ' || l_sec_needed_quantity);
9823 END IF;
9824 END IF;
9825 END IF; -- no consist restrictions
9826
9827 -- Just comment here for R12.1 replenishment project, no code change here
9828 -- In case of allocation_mode= 5 we do not need to keep track of left out qty at locations because
9829 -- we will not be using them in the next round. We strictly pick based on the pick UOM code and we
9830 -- do not break. So we do not need to add anything in the following code.
9831
9832
9833 --If remaining qty >0 and allocation mode in 3,4
9834 IF l_allocation_mode IN (3, 4)
9835 AND l_remaining_quantity > 0 THEN
9836 IF l_debug = 1 THEN
9837 log_statement(l_api_name, 'remain_qty', 'Remaining quantity: ' || l_remaining_quantity || '. Creating pick UOM rec');
9838 END IF;
9839 l_cur_rec := g_locs_index;
9840
9841 IF l_remaining_quantity < g_locs(g_locs_index).quantity THEN
9842 --create new location record for remaining quantity
9843 g_locs_index := g_locs_index + 1;
9844 g_locs(g_locs_index) := g_locs(l_cur_rec);
9845 g_locs(g_locs_index).quantity := l_remaining_quantity;
9846 g_locs(l_cur_rec).quantity := g_locs(l_cur_rec).quantity - l_remaining_quantity;
9847 l_cur_uom_rec := g_locs_index;
9848 ELSE
9849 l_cur_uom_rec := l_cur_rec;
9850 END IF;
9851
9852 -- new record is first record in table
9853 IF l_first_uom_rec = 0 THEN
9854 l_first_uom_rec := l_cur_uom_rec;
9855 l_last_uom_rec := l_cur_uom_rec;
9856 g_locs(l_cur_uom_rec).next_rec := 0;
9857 IF l_debug = 1 THEN
9858 log_statement(l_api_name, 'first_rec', 'The saved uom record is the first record in table');
9859 END IF;
9860 -- new record is first record with that uom code
9861 ELSIF g_locs(l_first_uom_rec).uom_code <> g_locs(l_cur_uom_rec).uom_code THEN
9862 g_locs(l_cur_uom_rec).next_rec := l_first_uom_rec;
9863 l_first_uom_rec := l_cur_uom_rec;
9864 l_last_uom_rec := l_cur_uom_rec;
9865 IF l_debug = 1 THEN
9866 log_statement(l_api_name, 'first_rec_uom', 'The saved uom record is the first record for uom in table');
9867 END IF;
9868 -- records with this uom code already exist in table
9869 ELSE
9870 g_locs(l_cur_uom_rec).next_rec := g_locs(l_last_uom_rec).next_rec;
9871 g_locs(l_last_uom_rec).next_rec := l_cur_uom_rec;
9872 l_last_uom_rec := l_cur_uom_rec;
9873 IF l_debug = 1 THEN
9874 log_statement(l_api_name, 'not_first_rec_uom', 'The saved record is not first record for uom in table');
9875 END IF;
9876 END IF;
9877
9878 IF l_debug = 1 THEN
9879 log_statement(l_api_name, 'saving_loc', 'Storing record in uom table');
9880 END IF;
9881
9882 IF l_debug_on THEN
9883 --determine if we created a new record or not
9884 IF l_cur_uom_rec = g_locs_index THEN
9885 g_trace_recs(g_locs_index) := g_trace_recs(l_cur_rec);
9886 g_trace_recs(l_cur_rec).quantity := g_trace_recs(l_cur_rec).quantity - l_remaining_quantity;
9887 g_trace_recs(g_locs_index).quantity := l_remaining_quantity;
9888 g_trace_recs(g_locs_index).suggested_qty := 0;
9889 g_trace_recs(l_cur_rec).pick_uom_flag := 'P';
9890 g_trace_recs(g_locs_index).pick_uom_flag := 'N';
9891 ELSE
9892 g_trace_recs(l_cur_rec).pick_uom_flag := 'N';
9893 END IF;
9894 END IF;
9895 ELSE
9896 IF l_debug_on THEN
9897 g_trace_recs(g_locs_index).pick_uom_flag := 'Y';
9898 END IF;
9899 END IF; --allocation mode in 3,4
9900
9901 --if needed qty = 0 , exit outermost loop
9902 --IF l_needed_quantity <= 0 THEN
9903 IF l_needed_quantity >= 0 and l_needed_quantity <= l_max_tolerance THEN
9904 IF l_debug = 1 THEN
9905 log_statement(l_api_name, 'finished_alloc', 'The requested quantity has been allocated. Exiting loop.');
9906 END IF;
9907 EXIT;
9908 END IF;
9909
9910 <<nextoutputrecord2>>
9911 NULL;
9912 --end outermost loop
9913 END LOOP;
9914 --PUT AWAY
9915 ELSIF (p_type_code = 1) THEN --put away
9916 l_capacity_updated := FALSE;
9917 l_locs_index := 0;
9918
9919 --Loop through each record from the Rule cursor
9920 WHILE TRUE LOOP
9921 IF l_debug = 1 THEN
9922 log_event(l_api_name, 'Loop through each record putaway from the Rule cursor ', 'Start ' || WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE);
9923 END IF;
9924 --l_locs_index := l_locs_index + 1; --bug3673962 moving this assignment as when no rows are returned by fetchputaway
9925 --the index gets incremented unncessarily and fails in WMSSOGBB.pls
9926 fetchputaway(
9927 x_return_status
9928 , x_msg_count
9929 , x_msg_data
9930 , v_put_cursor
9931 , l_rule_id
9932 , l_osubinventory_code
9933 , l_olocator_id
9934 , l_oproject_id
9935 , l_otask_id
9936 , l_rows
9937 );
9938
9939 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
9940 IF l_debug = 1 THEN
9941 log_statement(l_api_name, 'uerr_fetch_cursor',
9942 'Unexpected error in FetchCursor');
9943 END IF;
9944 RAISE fnd_api.g_exc_unexpected_error;
9945 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
9946 IF l_debug = 1 THEN
9947 log_statement(l_api_name,'err_fetch_cursor','Error in FetchCursor');
9948 END IF;
9949 RAISE fnd_api.g_exc_error;
9950 END IF;
9951
9952 -- Exit if no more records from rule cursor
9953 EXIT WHEN nvl(l_rows, 0) = 0 ; -- [ Added to to exit , if the rule is not returning any rows
9954
9955 l_locs_index := l_locs_index + 1; --bug3673962
9956 log_statement(l_api_name, 'org_loc_ctl ', 'org: ' ||wms_engine_pvt.g_org_loc_control);
9957 log_statement(l_api_name, 'sub_loc_ctl ', 'org: ' ||wms_engine_pvt.g_sub_loc_control);
9958 log_statement(l_api_name, 'itm_loc_ctl ', 'org: ' ||wms_engine_pvt.g_item_loc_control);
9959 /* bug 3972784, remove locator_id if no locator control */
9960 IF ( wms_engine_pvt.g_org_loc_control in (1,4) -- no loc ctl org level
9961 AND ( wms_engine_pvt.g_sub_loc_control = 1 -- no loc ctl sub level
9962 OR (wms_engine_pvt.g_sub_loc_control = 5
9963 AND wms_engine_pvt.g_item_loc_control = 1 -- no loc ctl item level
9964 )
9965 )
9966 )
9967 THEN
9968 l_olocator_id := null;
9969 log_statement(l_api_name, 'non locator controled',' Non locator controled');
9970 END IF;
9971
9972 IF l_debug = 1 THEN
9973 log_statement(l_api_name, 'put_sub', 'Subinventory: ' || l_osubinventory_code);
9974 log_statement(l_api_name, 'put_loc', 'Locator: ' || l_olocator_id);
9975 log_statement(l_api_name, 'put_proj', 'Project: ' || l_oproject_id);
9976 log_statement(l_api_name, 'put_task', 'Task: ' || l_otask_id);
9977 END IF;
9978
9979 IF l_debug_on THEN
9980 g_trace_recs(l_locs_index).revision := l_revision;
9981 g_trace_recs(l_locs_index).lot_number := l_lot_number;
9982 g_trace_recs(l_locs_index).lot_expiration_date := l_lot_expiration_date;
9983 g_trace_recs(l_locs_index).subinventory_code := l_osubinventory_code;
9984 g_trace_recs(l_locs_index).locator_id := l_olocator_id;
9985 g_trace_recs(l_locs_index).cost_group_id := l_to_cost_group_id;
9986 g_trace_recs(l_locs_index).uom_code := NULL;
9987 g_trace_recs(l_locs_index).lpn_id := l_input_lpn_id;
9988 g_trace_recs(l_locs_index).quantity := NULL;
9989 g_trace_recs(l_locs_index).serial_number := l_serial_number;
9990 --init to 0, in case of error
9991 g_trace_recs(l_locs_index).suggested_qty := 0;
9992 END IF;
9993
9994
9995 --bug 2589499
9996 --if reservation exists for WIP assembly completion, put away
9997 -- to reservable sub only;
9998 --we know if sub has to be reservable based on global value set in
9999 -- create_suggestions
10000 IF wms_engine_pvt.g_reservable_putaway_sub_only THEN
10001 OPEN c_subinventory;
10002 FETCH c_subinventory INTO l_lpn_controlled_flag,
10003 l_sub_rsv_type;
10004 If c_subinventory%NOTFOUND or l_sub_rsv_type IS NULL Then
10005 l_sub_rsv_type := 1;
10006 l_lpn_controlled_flag := 1;
10007 End If;
10008 CLOSE c_subinventory;
10009
10010 If l_sub_rsv_type <> 1 Then
10011 IF l_debug = 1 THEN
10012 log_statement(l_api_name, 'non_rsv_dest_sub',
10013 'This material cannot be putaway in a non-reservable sub. ' ||
10014 'Getting next record');
10015 END IF;
10016 --set trace flag
10017 GOTO NextOutputRecord;
10018 End If;
10019 END IF;
10020
10021
10022
10023 --3/13/02 - To support PJM, check project and task if supplied.
10024 -- Case 1) Project and Task not supplied do nothing
10025 -- 2) Project and Task Supplied and current record has same
10026 -- project and task continue processing.
10027 -- 3) Project and Task supplied, not in current record
10028 -- then create a new entry in MTL_ITEM_LOCATIONS with
10029 -- properties of current record but with require project and task
10030 -- <This assumes that the results are ordered by Project and Task>
10031 IF p_project_id IS NOT NULL THEN
10032 IF NVL(l_oproject_id, -9999) <> p_project_id
10033 OR NVL(l_otask_id, -9999) <> nvl(p_task_id,-9999) THEN
10034 --bug 2400549 - for WIP backflush transfer putaway,
10035 --always use the locator specified on the move order line, even
10036 --if that locator is from common stock (not project)
10037 -- Bug 2666620: BackFlush MO Type Removed. It is now 5.
10038 -- Moreover Txn Action ID is 2 which is already handled.
10039 IF NOT (wms_engine_pvt.g_move_order_type = 5 AND
10040 wms_engine_pvt.g_transaction_action_id = 2) THEN
10041 IF l_debug = 1 THEN
10042 log_statement(l_api_name, 'do_project2', 'Calling do project check');
10043 END IF;
10044 IF doprojectcheck(l_return_status,
10045 l_olocator_id,
10046 p_project_id,
10047 p_task_id,
10048 l_olocator_id_new,l_dummy_loc) THEN
10049 IF l_debug = 1 THEN
10050 log_statement(l_api_name, 'do_project_success', 'Do project check returned new locator');
10051 END IF;
10052 l_olocator_id_prev := l_olocator_id;
10053 l_olocator_id := l_olocator_id_new;
10054 ELSE
10055 -- Current locator does not have required project/task
10056 -- but it exists
10057 IF l_debug = 1 THEN
10058 log_statement(l_api_name, 'do_project_fail', 'Do project check failed. Getting next record.');
10059 END IF;
10060 GOTO nextoutputrecord;
10061 END IF; --do project check
10062 END IF; -- not wip backflush
10063 END IF; -- allocated project <> needed project
10064 END IF; -- needed project <> -9999
10065
10066 --2/21/02 - Now check available capacity in here in the Pl/Sql
10067 --instead of calling the APIs from the rule sql. This is to
10068 --improve performance. If there are 10000 eligible locators, you
10069 --don't want to check capacity for all of them. You only want to
10070 --check capacity on the one or two that you'll end up allocating
10071 IF l_debug = 1 THEN
10072 log_statement(l_api_name, 'qty_function', 'qty function code: ' || l_quantity_function);
10073 END IF;
10074 IF l_consider_staging_capacity THEN --Added bug3237702
10075 IF l_quantity_function = 530003 THEN
10076 l_possible_quantity := wms_parameter_pvt.getavailableunitcapacity(
10077 p_organization_id => p_organization_id
10078 , p_subinventory_code => l_osubinventory_code
10079 , p_locator_id => l_olocator_id
10080 );
10081 ELSIF l_quantity_function = 530007 THEN
10082 l_possible_quantity := wms_parameter_pvt.getavailablevolumecapacity(
10083 p_organization_id => p_organization_id
10084 , p_subinventory_code => l_osubinventory_code
10085 , p_locator_id => l_olocator_id
10086 , p_inventory_item_id => p_inventory_item_id
10087 , p_unit_volume => p_unit_volume
10088 , p_unit_volume_uom_code => p_volume_uom_code
10089 , p_primary_uom => p_primary_uom
10090 , p_transaction_uom => p_transaction_uom
10091 , p_base_uom => p_base_uom_code
10092 );
10093 ELSIF l_quantity_function = 530011 THEN
10094 l_possible_quantity := wms_parameter_pvt.getavailableweightcapacity(
10095 p_organization_id => p_organization_id
10096 , p_subinventory_code => l_osubinventory_code
10097 , p_locator_id => l_olocator_id
10098 , p_inventory_item_id => p_inventory_item_id
10099 , p_unit_weight => p_unit_weight
10100 , p_unit_weight_uom_code => p_weight_uom_code
10101 , p_primary_uom => p_primary_uom
10102 , p_transaction_uom => p_transaction_uom
10103 , p_base_uom => p_base_uom_code
10104 );
10105 ELSIF l_quantity_function = 530015 THEN
10106 l_possible_quantity := wms_parameter_pvt.getminimumavailablevwcapacity(
10107 p_organization_id => p_organization_id
10108 , p_subinventory_code => l_osubinventory_code
10109 , p_locator_id => l_olocator_id
10110 , p_inventory_item_id => p_inventory_item_id
10111 , p_unit_volume => p_unit_volume
10112 , p_unit_volume_uom_code => p_volume_uom_code
10113 , p_unit_weight => p_unit_weight
10114 , p_unit_weight_uom_code => p_weight_uom_code
10115 , p_primary_uom => p_primary_uom
10116 , p_transaction_uom => p_transaction_uom
10117 , p_base_uom => p_base_uom_code
10118 );
10119 ELSIF l_quantity_function = 530019 THEN
10120 l_possible_quantity := wms_parameter_pvt.getminimumavailableuvwcapacity(
10121 p_organization_id => p_organization_id
10122 , p_subinventory_code => l_osubinventory_code
10123 , p_locator_id => l_olocator_id
10124 , p_inventory_item_id => p_inventory_item_id
10125 , p_unit_volume => p_unit_volume
10126 , p_unit_volume_uom_code => p_volume_uom_code
10127 , p_unit_weight => p_unit_weight
10128 , p_unit_weight_uom_code => p_weight_uom_code
10129 , p_primary_uom => p_primary_uom
10130 , p_transaction_uom => p_transaction_uom
10131 , p_base_uom => p_base_uom_code
10132 );
10133 ELSIF l_quantity_function = 530023 THEN
10134 l_possible_quantity := wms_re_custom_pub.getavailablelocationcapacity(
10135 p_organization_id => p_organization_id
10136 , p_subinventory_code => l_osubinventory_code
10137 , p_locator_id => l_olocator_id
10138 , p_inventory_item_id => p_inventory_item_id
10139 , p_transaction_quantity => l_needed_quantity
10140 , p_transaction_uom => p_transaction_uom
10141 );
10142 ELSE
10143 l_possible_quantity := 0;
10144 IF l_debug = 1 THEN
10145 log_statement(l_api_name, 'bad_qtyf', 'Invalid Quantity Function');
10146 END IF;
10147 --raise error message!!!
10148 END IF;
10149 ELSE
10150 -- capacity should not be considered
10151 l_possible_quantity := 1e125;
10152 l_sec_possible_quantity := 1e125;
10153 END IF;
10154
10155 IF l_debug = 1 THEN
10156 log_statement(l_api_name, 'capacity', 'avail. capacity: ' || l_possible_quantity);
10157 END IF;
10158
10159 --bug 2778814
10160 --For serial controlled items, we should not suggest the putaway
10161 -- of decimal quantities
10162 IF wms_engine_pvt.g_serial_number_control_code > 1 THEN
10163 l_possible_quantity := floor(l_possible_quantity);
10164 IF l_debug = 1 THEN
10165 log_statement(l_api_name, 'no_decimals',
10166 'Cannot putaway a decimal quantity on a serial controlled item.'||
10167 ' New available capacity: ' || l_possible_quantity);
10168 END IF;
10169 END IF;
10170
10171 IF l_debug_on THEN
10172 g_trace_recs(l_locs_index).quantity := l_possible_quantity;
10173 --g_trace_recs(l_locs_index).secondary_quantity := l_sec_possible_quantity;
10174 END IF;
10175
10176 -- [LOT_INDIV
10177 -- For lot indiv item, check if entire line qty can be dropped
10178 -- If not skip the current locator and go to next available locator
10179 --
10180 -- Default behavior is to split the qty and drop the partially
10181 -- and go to the next locator for the remaining qty.
10182
10183 IF l_lot_divisible_flag = 'N' and l_lot_control_code <> 1 and p_type_code = 1 THEN
10184 IF l_possible_quantity < l_needed_quantity THEN
10185 IF l_debug = 1 THEN
10186 log_event(l_api_name, 'Required Capacity = ', l_needed_quantity);
10187 log_event(l_api_name, 'Available capacity =', l_possible_quantity);
10188 log_event(l_api_name, 'Capacity check for Lot indiv item', 'Capacity is not enough !');
10189 END IF;
10190 GOTO nextoutputrecord;
10191 END IF;
10192 END IF;
10193 -- If no quantity for this record, get next record
10194 IF l_possible_quantity <= 0 OR l_possible_quantity IS NULL THEN
10195 IF l_debug = 1 THEN
10196 log_event(l_api_name, 'no_rec_qty_put', 'No available capacity in putaway location');
10197 END IF;
10198 --
10199 -- Patchset 'J' error_message
10200 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_LOC_CAPACITY_FULL' ;
10201 --
10202 --
10203 GOTO nextoutputrecord;
10204 END IF;
10205
10206 --check to see if from sub/loc = to sub/loc
10207 --this is okay if pick wave move order.
10208 --if not pick wave move order and src = dest,
10209 -- skip results
10210
10211 --first check to make sure picking from dest sub is not allowed;
10212 --then, based on type code, compare src sub to dest sub;
10213 --next, check to see if sub and item are locator controlled;
10214 --if loc control, go to next record only if src loc = dest loc
10215 --if not loc control, go to next records (since subs are equal)
10216 --all of the global variables are set in
10217 --wms_engine_pvt.create_suggestions
10218 IF (wms_engine_pvt.g_dest_sub_pick_allowed = 0
10219 AND l_osubinventory_code = l_from_subinventory_code
10220 ) THEN
10221 IF (wms_engine_pvt.g_org_loc_control IN (2, 3)
10222 OR wms_engine_pvt.g_sub_loc_control IN (2, 3)
10223 OR (wms_engine_pvt.g_sub_loc_control = 5
10224 AND (wms_engine_pvt.g_item_loc_control IN (2, 3))
10225 )
10226 ) THEN
10227 IF (l_olocator_id = l_from_locator_id) THEN
10228
10229 IF l_debug = 1 THEN
10230 log_event(
10231 l_api_name
10232 , 'same_sub_loc_put'
10233 , 'Destination '
10234 || 'subinventory and locator for this record are the '
10235 || 'same as the source subinventory and locator. '
10236 || 'Using next record'
10237 );
10238 END IF;
10239
10240 IF l_debug_on THEN
10241 g_trace_recs(l_locs_index).same_subinv_loc_flag := 'N';
10242 END IF;
10243
10244 --
10245 -- Patchset 'J' error_message
10246 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_SAME_SUB_LOC' ;
10247 --
10248 --
10249 GOTO nextoutputrecord;
10250 END IF; -- from loc = to loc
10251 ELSE -- not loc controlled
10252 IF l_debug = 1 THEN
10253 log_event(
10254 l_api_name
10255 , 'same_sub_put'
10256 , 'Destination ' || 'subinventory for this record is the ' || 'same as the source subinventory. ' || 'Using next record'
10257 );
10258 END IF;
10259
10260 IF l_debug_on THEN
10261 g_trace_recs(l_locs_index).same_subinv_loc_flag := 'N';
10262 END IF;
10263
10264 GOTO nextoutputrecord;
10265 END IF;
10266 END IF;
10267
10268 IF l_debug_on THEN
10269 g_trace_recs(l_locs_index).same_subinv_loc_flag := 'Y';
10270 END IF;
10271
10272 --check status to see if putting away to this location is allowed
10273 -- for this transaction type
10274 -- This API checks the status for the subinventory, locator,
10275 -- and lot
10276 IF l_debug = 1 THEN
10277 log_statement(l_api_name, 'checking_status', 'calling is_sub_loc_lot_trx_allowed to check status');
10278 END IF;
10279
10280 --Bug Number :3457530(cheking for a transaction_type_id)
10281
10282 IF ( p_transaction_type_id <> 64) THEN
10283 l_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
10284 p_transaction_type_id => p_transaction_type_id
10285 , p_organization_id => p_organization_id
10286 , p_inventory_item_id => p_inventory_item_id
10287 , p_subinventory_code => l_osubinventory_code
10288 , p_locator_id => l_olocator_id
10289 , p_lot_number => l_lot_number
10290 );
10291 END IF;
10292
10293 IF l_allowed <> 'Y' THEN
10294
10295 IF l_debug = 1 THEN
10296 log_event(
10297 l_api_name
10298 , 'bad_status'
10299 , 'This transaction type is not allowed by the status ' || 'for the subinventory, locator, or lot. Using ' || 'next record.'
10300 );
10301 END IF;
10302
10303 IF l_debug_on THEN
10304 g_trace_recs(l_locs_index).material_status_flag := 'N';
10305 END IF;
10306 --
10307 -- Patchset 'J' error_message
10308 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_MAT_STATUS_NOT_ALLOWED' ;
10309 --
10310 --
10311 GOTO nextoutputrecord;
10312 END IF;
10313
10314 IF l_debug_on THEN
10315 g_trace_recs(l_locs_index).material_status_flag := 'Y';
10316 END IF;
10317
10318 /* Bug 4544717 -Converted l_possible_quantity to primary uom before comparing with
10319 l_needed_quantity which is in primary uom if the transaction uom and
10320 primary uom were different */
10321
10322 IF l_debug = 1 THEN
10323 log_statement(l_api_name, 'poss_put_qty', 'Value of p_transaction_uom:'|| p_transaction_uom);
10324 log_statement(l_api_name, 'poss_put_qty', 'Value of p_primary_uom'|| p_primary_uom);
10325 END IF;
10326
10327 IF p_transaction_uom <> p_primary_uom THEN
10328 IF l_debug = 1 THEN
10329 log_statement(l_api_name, 'poss_put_qty', 'In the condition for transaction_uom and primary uom different');
10330 END IF;
10331 l_possible_quantity := inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_possible_quantity, p_transaction_uom, p_primary_uom , NULL, NULL);
10332 END IF;
10333
10334 IF l_debug = 1 THEN
10335 log_statement(l_api_name, 'poss_put_qty', 'Value of l_possible_quantity' || l_possible_quantity);
10336 log_statement(l_api_name, 'poss_put_qty', 'Value of l_needed_quantity' || l_needed_quantity);
10337 END IF;
10338
10339 /* End of fix for Bug 4544717 */
10340
10341
10342 -- correct possible quantity to what is really requested
10343 IF l_possible_quantity > l_needed_quantity THEN
10344 l_possible_quantity := l_needed_quantity;
10345 l_sec_possible_quantity := l_sec_needed_quantity;
10346 IF l_debug = 1 THEN
10347 log_statement(l_api_name, 'poss_put_qty', 'Possible quantity > needed quantity. New poss qty:' || l_possible_quantity);
10348 END IF;
10349 END IF;
10350
10351 --
10352
10353 --Determine if putaway sub is LPN controlled. If it is not,
10354 --then we need to check cost group commingling always;
10355 -- Check cost group if
10356 -- Cost group is not null AND
10357 -- (sub is not lpn controlled OR
10358 -- No lpn on move order line OR
10359 -- not a staging transfer)
10360 --Never suggest comingling of cost groups, unless we are
10361 -- putting away a LPN.
10362 --When putting away an LPN, we assume that user is putting away
10363 -- whole LPN, which means there will never be comingling.
10364 --bug 1570597 - staging transfers are always put away in an LPN,
10365 -- so we don't need to check for comingling.
10366 --bug 2161565 - need to check for cg commingling if
10367 -- to subinventory is not LPN controlled.
10368 --bug 2492526 - putting away to a project controlled locator
10369 -- will always change the CG. So no need to worry about CG
10370 -- commingling if the dest. loc is project controlled.
10371 IF l_to_cost_group_id IS NULL THEN
10372 l_check_cg := FALSE;
10373 ELSIF l_oproject_id IS NOT NULL THEN
10374 l_check_cg := FALSE;
10375 ELSIF (p_lpn_id IS NOT NULL
10376 OR p_transaction_type_id IN (52, 53)
10377 ) THEN
10378
10379 --only execute query if we did not already find lpn_controlled_flag
10380 -- when determining if sub is reservable
10381 If l_lpn_controlled_flag IS NULL Then
10382 OPEN c_subinventory;
10383 FETCH c_subinventory INTO l_lpn_controlled_flag,
10384 l_sub_rsv_type;
10385 -- by default, assume sub is lpn controlled
10386 If c_subinventory%notfound OR
10387 l_lpn_controlled_flag IS NULL OR
10388 l_lpn_controlled_flag NOT IN (1,2) Then
10389 l_lpn_controlled_flag := 1;
10390 End If;
10391 CLOSE c_subinventory;
10392 End If;
10393
10394 IF l_lpn_controlled_flag = 1 THEN
10395 l_check_cg := FALSE;
10396 ELSE
10397 l_check_cg := TRUE;
10398 END IF;
10399 ELSE
10400 l_check_cg := TRUE;
10401 END IF;
10402
10403 --Check to see if putaway would comingle cost groups.
10404 IF l_check_cg THEN
10405 inv_comingling_utils.comingle_check(
10406 x_return_status => x_return_status
10407 , x_msg_count => x_msg_count
10408 , x_msg_data => x_msg_data
10409 , x_comingling_occurs => l_comingle
10410 , x_count => l_dummy
10411 , p_organization_id => p_organization_id
10412 , p_inventory_item_id => p_inventory_item_id
10413 , p_revision => l_revision
10414 , p_lot_number => l_lot_number
10415 , p_subinventory_code => l_osubinventory_code
10416 , p_locator_id => l_olocator_id
10417 , p_lpn_id => NULL
10418 , p_cost_group_id => l_to_cost_group_id
10419 );
10420
10421 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10422 IF l_debug = 1 THEN
10423 log_statement(l_api_name, 'uerr_comingle_check', 'Unexpected error in comingle_check');
10424 END IF;
10425 RAISE fnd_api.g_exc_unexpected_error;
10426 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10427 IF l_debug = 1 THEN
10428 log_statement(l_api_name, 'err_comingle_check', 'Error in comingle_check');
10429 END IF;
10430 RAISE fnd_api.g_exc_error;
10431 END IF;
10432
10433 -- Skip record if it would cause comingling
10434 IF l_comingle = 'Y' THEN
10435 IF l_debug = 1 THEN
10436 log_event(l_api_name, 'comingle_putaway', 'Putaway to this location would comingle cost groups. ' || 'Using next record');
10437 END IF;
10438 IF l_debug_on THEN
10439 g_trace_recs(l_locs_index).cg_comingle_flag := 'N';
10440 END IF;
10441 --
10442 -- Patchset 'J' error_message
10443 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_COST_GROUP_COMINGLE' ;
10444 GOTO nextoutputrecord;
10445 END IF;
10446
10447 IF l_debug_on THEN
10448 g_trace_recs(l_locs_index).cg_comingle_flag := 'Y';
10449 END IF;
10450 END IF;
10451
10452 -- Update locator capacity to reflect quantity we are putting
10453 -- away. This API executes an autonomous commit. Thus,
10454 -- if any sort of error occurs, we have to explicitly undo
10455 -- this update (we can't just do a rollback).
10456 IF (l_olocator_id IS NOT NULL) AND l_consider_staging_capacity THEN --Added bug3237702
10457 --IF l_olocator_id IS NOT NULL THEN Commented bug3237702
10458 IF l_debug = 1 THEN
10459 log_statement(l_api_name, 'update_capacity', 'Updating suggested capacity');
10460 END IF;
10461 inv_loc_wms_utils.update_loc_suggested_capacity(
10462 x_return_status => x_return_status
10463 , x_msg_count => x_msg_count
10464 , x_msg_data => x_msg_data
10465 , p_organization_id => p_organization_id
10466 , p_inventory_location_id => l_olocator_id
10467 , p_inventory_item_id => p_inventory_item_id
10468 , p_primary_uom_flag => 'Y'
10469 , p_transaction_uom_code => NULL
10470 , p_quantity => l_possible_quantity
10471 );
10472
10473 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10474 IF l_debug = 1 THEN
10475 log_statement(l_api_name, 'uerr_update_capacity', 'Unexpected error in update_loc_suggested_capacity');
10476 END IF;
10477 RAISE fnd_api.g_exc_unexpected_error;
10478 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10479 IF l_debug = 1 THEN
10480 log_statement(l_api_name, 'err_update_capacity', 'Error in update_loc_suggested_capacity');
10481 END IF;
10482 RAISE fnd_api.g_exc_error;
10483 ELSE
10484 l_capacity_updated := TRUE;
10485 END IF;
10486 END IF;
10487
10488 IF l_debug_on THEN
10489 g_trace_recs(l_locs_index).suggested_qty := l_possible_quantity;
10490 g_trace_recs(l_locs_index).secondary_suggested_qty := l_sec_possible_quantity;
10491 END IF;
10492
10493 -- no detail for serial numbers
10494 -- get the transaction quantity
10495 IF p_transaction_uom = p_primary_uom THEN
10496 l_possible_trx_qty := l_possible_quantity;
10497 ELSE
10498 l_possible_trx_qty :=
10499 inv_convert.inv_um_convert(p_inventory_item_id, NULL, l_possible_quantity, p_primary_uom, p_transaction_uom, NULL, NULL);
10500 END IF;
10501
10502 IF l_debug = 1 THEN
10503 log_statement(l_api_name, 'insert_put_wtt_recs', 'Before insert values of l_possible_trx_qty'|| l_possible_trx_qty);
10504 log_statement(l_api_name, 'insert_put_wtt_recs', 'Before insert values of l_possible_quantity'|| l_possible_quantity);
10505 END IF;
10506
10507 IF l_debug = 1 THEN
10508 log_statement(l_api_name, 'insert_put_wtt_recs', 'Inserting putaway records in wtt');
10509 END IF;
10510 -- insert temporary suggestion
10511 INSERT INTO wms_transactions_temp
10512 (
10513 pp_transaction_temp_id
10514 , transaction_temp_id
10515 , type_code
10516 , line_type_code
10517 , transaction_quantity
10518 , primary_quantity
10519 , secondary_quantity
10520 , grade_code
10521 , revision
10522 , lot_number
10523 , lot_expiration_date
10524 , from_subinventory_code
10525 , from_locator_id
10526 , rule_id
10527 , reservation_id
10528 , to_subinventory_code
10529 , to_locator_id
10530 , from_cost_group_id
10531 , to_cost_group_id
10532 , lpn_id
10533 )
10534 VALUES (
10535 wms_transactions_temp_s.NEXTVAL
10536 , p_transaction_temp_id
10537 , p_type_code
10538 , 2 -- line type code is output
10539 , l_possible_trx_qty
10540 , l_possible_quantity
10541 , l_sec_possible_quantity
10542 , l_grade_code
10543 , l_revision
10544 , l_lot_number
10545 , l_lot_expiration_date
10546 , l_from_subinventory_code
10547 , l_from_locator_id
10548 , l_rule_id
10549 , l_reservation_id
10550 , l_osubinventory_code
10551 , l_olocator_id
10552 , l_from_cost_group_id
10553 , l_to_cost_group_id
10554 , l_input_lpn_id
10555 );
10556
10557 --
10558 l_capacity_updated := FALSE;
10559 --END IF;
10560
10561 IF l_debug = 1 THEN
10562 log_event(l_api_name, 'putaway_loc_found', 'Found put away location for quantity ' || l_possible_quantity);
10563 END IF;
10564
10565 -- keep track of the remaining transaction quantity
10566 IF l_needed_quantity > l_possible_quantity THEN
10567 l_needed_quantity := l_needed_quantity - l_possible_quantity;
10568 l_sec_needed_quantity := l_sec_needed_quantity - l_sec_possible_quantity;
10569 ELSE
10570 l_needed_quantity := 0;
10571 l_sec_needed_quantity := 0;
10572 IF l_debug = 1 THEN
10573 log_event(l_api_name, 'finished_putaway', 'Found put away locations for all quantity in this input record');
10574 END IF;
10575 END IF;
10576
10577 --
10578 <<nextoutputrecord>>
10579 EXIT WHEN l_needed_quantity = 0;
10580 END LOOP; -- output records
10581 END IF; -- type_code = 1
10582
10583 -- finally close the rule cursor
10584 IF l_debug = 1 THEN
10585 log_statement(l_api_name, 'close_curs', 'Calling close_curs');
10586 END IF;
10587
10588 -- Bug# 4738161: Close the putaway cursors after each line is allocated if necessary
10589 IF p_type_code = 1 THEN
10590 close_put_rule(l_rule_id, v_put_cursor);
10591 ELSE
10592 close_pick_rule(l_rule_id, v_pick_cursor);
10593 END IF;
10594
10595 IF l_debug = 1 THEN
10596 log_statement(l_api_name, 'finish_close_curs', 'Finished close_curs');
10597 END IF;
10598
10599 IF ((g_over_allocation = 'N'
10600 OR (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
10601 OR WMS_Engine_PVT.g_move_order_type <> 3 or p_type_code <> 2)
10602 AND (l_needed_quantity > 0 OR l_needed_quantity > l_max_tolerance)
10603 )
10604 OR
10605 (g_over_allocation = 'Y' AND NOT (p_type_code = 2 AND l_lot_divisible_flag = 'N' and l_lot_control_code <> 1)
10606 AND WMS_Engine_PVT.g_move_order_type = 3 and p_type_code = 2
10607 AND ((l_max_tolerance >= 0 AND (l_needed_quantity > l_max_tolerance)
10608 AND (l_initial_pri_quantity - l_needed_quantity < WMS_RULE_PVT.g_min_qty_to_allocate))
10609 OR (l_max_tolerance < 0
10610 AND l_initial_pri_quantity - l_needed_quantity < WMS_RULE_PVT.g_min_qty_to_allocate)
10611 )
10612 )
10613 THEN
10614 -- notice, that at least one input record couldn't get satisfied
10615 x_finished := fnd_api.g_false;
10616
10617 IF l_needed_quantity = l_initial_pri_quantity THEN
10618 -- Bug #3396532
10619 IF WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE IS NULL THEN
10620 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_PUT_NO_ROWS';
10621 END IF;
10622 IF l_debug = 1 THEN
10623 log_event(l_api_name, 'no_success', 'Found no locations for this rule');
10624 END IF;
10625 ELSE
10626 IF l_debug = 1 THEN
10627 log_event(l_api_name, 'partial_success', 'Successfully allocated some of the transaction ' || 'quantity with this rule.');
10628 END IF;
10629 END IF;
10630
10631 -- if partials are not allowed, exit after rolling back everything
10632 IF p_partial_success_allowed_flag = 'N' THEN
10633 -- restore qty tree
10634 IF l_debug = 1 THEN
10635 log_event(l_api_name, 'no_partials_allowed', 'Partial success is not allowed for this rule - rolling back');
10636 END IF;
10637 IF p_type_code = 2 THEN
10638 IF l_debug = 1 THEN
10639 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
10640 END IF;
10641 inv_quantity_tree_pvt.restore_tree(x_return_status, p_tree_id);
10642
10643 /*Start of fix for Bug 5251221 */
10644
10645 OPEN l_get_serial;
10646 LOOP
10647 FETCH l_get_serial INTO l_serial_number;
10648 IF l_get_serial%NOTFOUND THEN
10649 IF l_debug = 1 THEN
10650 inv_log_util.trace('Serial not found', 'delete_serial_numbers', 9);
10651 END IF;
10652 exit;
10653 ELSE
10654 IF (inv_detail_util_pvt.g_serial_tbl_ptr > 0) THEN
10655 IF l_debug = 1 THEN
10656 inv_log_util.trace('Org: ' || p_organization_id, 'delete_serial_numbers', 9);
10657 inv_log_util.trace('Item: ' || p_inventory_item_id, 'delete_serial_numbers', 9);
10658 inv_log_util.trace('Serial: ' || l_serial_number, 'delete_serial_numbers', 9);
10659 inv_log_util.trace('inv_detail_util_pvt.g_serial_tbl_ptr ' || inv_detail_util_pvt.g_serial_tbl_ptr, 'delete_serial_numbers', 9);
10660 END IF;
10661
10662 FOR i IN 1..inv_detail_util_pvt.g_serial_tbl_ptr LOOP
10663 IF (inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id = p_inventory_item_id) AND
10664 (inv_detail_util_pvt.g_output_serial_rows(i).organization_id = p_organization_id) AND
10665 (inv_detail_util_pvt.g_output_serial_rows(i).serial_number = l_serial_number) THEN
10666
10667 IF (inv_detail_util_pvt.g_serial_tbl_ptr > 1) THEN
10668 inv_detail_util_pvt.g_output_serial_rows(i).organization_id := inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).organization_id;
10669 inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id := inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).inventory_item_id;
10670 inv_detail_util_pvt.g_output_serial_rows(i).serial_number := inv_detail_util_pvt.g_output_serial_rows(inv_detail_util_pvt.g_serial_tbl_ptr).serial_number;
10671
10672 inv_detail_util_pvt.g_output_serial_rows.DELETE(inv_detail_util_pvt.g_serial_tbl_ptr);
10673 inv_detail_util_pvt.g_serial_tbl_ptr := inv_detail_util_pvt.g_serial_tbl_ptr-1;
10674 IF l_debug = 1 THEN
10675 inv_log_util.trace('inv_detail_util_pvt.g_serial_tbl_ptr ' || inv_detail_util_pvt.g_serial_tbl_ptr, 'delete_serial_numbers', 9);
10676 END IF;
10677
10678 ELSE
10679 inv_detail_util_pvt.g_output_serial_rows.delete;
10680 inv_detail_util_pvt.g_serial_tbl_ptr := inv_detail_util_pvt.g_serial_tbl_ptr-1;
10681 IF l_debug = 1 THEN
10682 inv_log_util.trace('Array cleared', 'delete_serial_numbers', 9);
10683 END IF;
10684
10685 END IF;--End of IF (inv_detail_util_pvt.g_serial_tbl_ptr > 1)
10686 exit; --if a serial has been deleted, needn't check other serials present in g_output_serial_rows
10687 END IF; --End of IF (inv_detail_util_pvt.g_output_serial_rows(i).inventory_item_id = p_inventory_item_id)
10688 END LOOP; --End of FOR loop
10689 END IF;--End of IF (inv_detail_util_pvt.g_serial_tbl_ptr > 0)
10690 END IF;-- End of IF l_get_serial%NOTFOUND
10691 END LOOP;--End of LOOP for CURSOR
10692 CLOSE l_get_serial;
10693 /*End of fix for Bug 5251221 */
10694
10695
10696 --
10697 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10698 IF l_debug = 1 THEN
10699 log_statement(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
10700 END IF;
10701 RAISE fnd_api.g_exc_unexpected_error;
10702 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10703 IF l_debug = 1 THEN
10704 log_statement(l_api_name, 'err_restore_tree', 'Error in restore_tree');
10705 END IF;
10706 RAISE fnd_api.g_exc_error;
10707 END IF;
10708 ELSE --for put away, restore capacity
10709 --this function reduces the suggested units in the location
10710 -- for each record inserted in wms_transaction_temp as a
10711 -- putaway output record
10712 rollback_capacity_update(
10713 x_return_status => x_return_status
10714 , x_msg_count => x_msg_count
10715 , x_msg_data => x_msg_data
10716 , p_organization_id => p_organization_id
10717 , p_inventory_item_id => p_inventory_item_id
10718 );
10719
10720 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10721 IF l_debug = 1 THEN
10722 log_statement(l_api_name, 'uerr_rollback_cap', 'Unexpected error in rollback_capacity_update');
10723 END IF;
10724 RAISE fnd_api.g_exc_unexpected_error;
10725 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10726 IF l_debug = 1 THEN
10727 log_statement(l_api_name, 'err_rollback_cap', 'Error in rollback_capacity_update');
10728 END IF;
10729 RAISE fnd_api.g_exc_error;
10730 END IF;
10731
10732 --if error occurred after capacity got updated but before
10733 -- insertion into WTT, fix the capacity for that record
10734 IF l_capacity_updated THEN
10735 IF l_debug = 1 THEN
10736 log_statement(l_api_name, 'revert_capacity', 'Calling revert_loc_suggested_capacity');
10737 END IF;
10738 inv_loc_wms_utils.revert_loc_suggested_capacity(
10739 x_return_status => x_return_status
10740 , x_msg_count => x_msg_count
10741 , x_msg_data => x_msg_data
10742 , p_organization_id => p_organization_id
10743 , p_inventory_location_id => l_olocator_id
10744 , p_inventory_item_id => p_inventory_item_id
10745 , p_primary_uom_flag => 'Y'
10746 , p_transaction_uom_code => NULL
10747 , p_quantity => l_possible_quantity
10748 );
10749
10750 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
10751 IF l_debug = 1 THEN
10752 log_statement(l_api_name, 'uerr_revert_capacity', 'Unexpected error in revert_loc_suggested_capacity');
10753 END IF;
10754 RAISE fnd_api.g_exc_unexpected_error;
10755 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
10756 IF l_debug = 1 THEN
10757 log_statement(l_api_name, 'err_revert_capacity', 'Error in revert_loc_suggested_capacity');
10758 END IF;
10759 RAISE fnd_api.g_exc_error;
10760 END IF;
10761
10762 l_capacity_updated := FALSE;
10763 END IF;
10764 END IF;
10765
10766 --needs to set the trace flag for partial pick to N.
10767 IF l_debug_on THEN
10768 --first record in g_trace_recs always at index 1
10769 l_cur_rec := 1;
10770
10771 LOOP
10772 EXIT WHEN NOT g_trace_recs.EXISTS(l_cur_rec);
10773
10774 IF g_trace_recs(l_cur_rec).suggested_qty > 0 THEN
10775 g_trace_recs(l_cur_rec).suggested_qty := 0;
10776 g_trace_recs(l_cur_rec).partial_pick_flag := 'N';
10777 END IF;
10778
10779 l_cur_rec := l_cur_rec + 1;
10780 END LOOP;
10781
10782 wms_search_order_globals_pvt.insert_trace_lines(
10783 p_api_version => 1.0
10784 , p_init_msg_list => fnd_api.g_false
10785 , p_validation_level => fnd_api.g_valid_level_full
10786 , x_return_status => l_return_status
10787 , x_msg_count => x_msg_count
10788 , x_msg_data => x_msg_data
10789 , p_header_id => wms_engine_pvt.g_trace_header_id
10790 , p_rule_id => l_rule_id
10791 , p_pre_suggestions => g_trace_recs
10792 );
10793 END IF;
10794
10795 --
10796 ROLLBACK TO applyrulesp;
10797 EXIT;
10798 ELSE
10799 IF l_needed_quantity <> l_initial_pri_quantity THEN
10800 IF l_debug = 1 THEN
10801 log_statement(l_api_name, 'updating_input_rec', 'Updating the input line in WTT and pl/sql table');
10802 END IF;
10803
10804 l_needed_quantity := l_needed_quantity - l_max_tolerance;
10805 UPDATE wms_transactions_temp
10806 SET primary_quantity = l_needed_quantity
10807 , secondary_quantity = l_sec_needed_quantity
10808 WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
10809
10810 wms_re_common_pvt.updateinputline(l_needed_quantity,l_sec_needed_quantity);
10811 END IF;
10812 END IF;
10813 ELSE
10814 x_finished := fnd_api.g_true;
10815 -- if input line could get satisfied
10816 -- delete the input line in the wms_transactions_temp table
10817 IF l_debug = 1 THEN
10818 log_statement(l_api_name, 'deleting_input_rec', 'Deleting the input line in WTT and pl/sql table');
10819 END IF;
10820
10821 DELETE FROM wms_transactions_temp
10822 WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
10823
10824 --
10825 -- and delete input record in PL/SQL table, too
10826 wms_re_common_pvt.deleteinputline;
10827 END IF;
10828
10829 IF l_debug_on THEN
10830 wms_search_order_globals_pvt.insert_trace_lines(
10831 p_api_version => 1.0
10832 , p_init_msg_list => fnd_api.g_false
10833 , p_validation_level => fnd_api.g_valid_level_full
10834 , x_return_status => l_return_status
10835 , x_msg_count => x_msg_count
10836 , x_msg_data => x_msg_data
10837 , p_header_id => wms_engine_pvt.g_trace_header_id
10838 , p_rule_id => l_rule_id
10839 , p_pre_suggestions => g_trace_recs
10840 );
10841 END IF;
10842
10843 <<NextINputRecord>>
10844 NULL;
10845 END LOOP; -- input records
10846
10847 --
10848 -- Standard check of p_commit
10849 IF fnd_api.to_boolean(p_commit) THEN
10850 COMMIT WORK;
10851 END IF;
10852
10853 -- end of debugging section
10854 IF l_debug = 1 THEN
10855 log_procedure(l_api_name, 'end', 'End Apply');
10856 END IF;
10857 --
10858 EXCEPTION
10859 WHEN fnd_api.g_exc_error THEN
10860 --
10861 --if l_pack_exists <>2, then open_curs was never called, so no need to
10862 -- close the cursor
10863 IF (l_pack_exists = 2) THEN
10864 close_pick_rule(l_rule_id, v_pick_cursor);
10865 END IF;
10866
10867 --this function reduces the suggested units in the location
10868 -- for each record inserted in wms_transaction_temp as a
10869 -- putaway output record
10870 rollback_capacity_update(
10871 x_return_status => l_return_status
10872 , x_msg_count => l_msg_count
10873 , x_msg_data => l_msg_data
10874 , p_organization_id => p_organization_id
10875 , p_inventory_item_id => p_inventory_item_id
10876 );
10877
10878 --if error occurred after capacity got updated but before
10879 -- insertion into WTT, fix the capacity for that record
10880 IF l_capacity_updated THEN
10881 inv_loc_wms_utils.revert_loc_suggested_capacity(
10882 x_return_status => l_return_status
10883 , x_msg_count => l_msg_count
10884 , x_msg_data => l_msg_data
10885 , p_organization_id => p_organization_id
10886 , p_inventory_location_id => l_olocator_id
10887 , p_inventory_item_id => p_inventory_item_id
10888 , p_primary_uom_flag => 'Y'
10889 , p_transaction_uom_code => NULL
10890 , p_quantity => l_possible_quantity
10891 );
10892 l_capacity_updated := FALSE;
10893 END IF;
10894
10895 ROLLBACK TO applyrulesp;
10896 freeglobals;
10897 x_return_status := fnd_api.g_ret_sts_error;
10898 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
10899 IF l_debug = 1 THEN
10900 log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
10901 END IF;
10902 --
10903 WHEN fnd_api.g_exc_unexpected_error THEN
10904 --if l_pack_exists <>2, then open_curs was never called, so no need to
10905 -- close the cursor
10906 IF (l_pack_exists = 2) THEN
10907 close_put_rule(l_rule_id, v_put_cursor);
10908 END IF;
10909
10910 --this function reduces the suggested units in the location
10911 -- for each record inserted in wms_transaction_temp as a
10912 -- putaway output record
10913 rollback_capacity_update(
10914 x_return_status => l_return_status
10915 , x_msg_count => l_msg_count
10916 , x_msg_data => l_msg_data
10917 , p_organization_id => p_organization_id
10918 , p_inventory_item_id => p_inventory_item_id
10919 );
10920
10921 --if error occurred after capacity got updated but before
10922 -- insertion into WTT, fix the capacity for that record
10923 IF l_capacity_updated THEN
10924 inv_loc_wms_utils.revert_loc_suggested_capacity(
10925 x_return_status => l_return_status
10926 , x_msg_count => l_msg_count
10927 , x_msg_data => l_msg_data
10928 , p_organization_id => p_organization_id
10929 , p_inventory_location_id => l_olocator_id
10930 , p_inventory_item_id => p_inventory_item_id
10931 , p_primary_uom_flag => 'Y'
10932 , p_transaction_uom_code => NULL
10933 , p_quantity => l_possible_quantity
10934 );
10935 l_capacity_updated := FALSE;
10936 END IF;
10937
10938 ROLLBACK TO applyrulesp;
10939 freeglobals;
10940 x_return_status := fnd_api.g_ret_sts_unexp_error;
10941 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
10942 IF l_debug = 1 THEN
10943 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
10944 END IF;
10945 --
10946 WHEN OTHERS THEN
10947 --if l_pack_exists <>2, then open_curs was never called, so no need to
10948 -- close the cursor
10949 IF (l_pack_exists = 2) THEN
10950 close_put_rule(l_rule_id, v_put_cursor);
10951 END IF;
10952
10953 --this function reduces the suggested units in the location
10954 -- for each record inserted in wms_transaction_temp as a
10955 -- putaway output record
10956 rollback_capacity_update(
10957 x_return_status => l_return_status
10958 , x_msg_count => l_msg_count
10959 , x_msg_data => l_msg_data
10960 , p_organization_id => p_organization_id
10961 , p_inventory_item_id => p_inventory_item_id
10962 );
10963
10964 --if error occurred after capacity got updated but before
10965 -- insertion into WTT, fix the capacity for that record
10966 IF l_capacity_updated THEN
10967 inv_loc_wms_utils.revert_loc_suggested_capacity(
10968 x_return_status => l_return_status
10969 , x_msg_count => l_msg_count
10970 , x_msg_data => l_msg_data
10971 , p_organization_id => p_organization_id
10972 , p_inventory_location_id => l_olocator_id
10973 , p_inventory_item_id => p_inventory_item_id
10974 , p_primary_uom_flag => 'Y'
10975 , p_transaction_uom_code => NULL
10976 , p_quantity => l_possible_quantity
10977 );
10978 l_capacity_updated := FALSE;
10979 END IF;
10980
10981 ROLLBACK TO applyrulesp;
10982 freeglobals;
10983 x_return_status := fnd_api.g_ret_sts_unexp_error;
10984
10985 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
10986 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
10987 END IF;
10988
10989 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
10990 IF l_debug = 1 THEN
10991 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
10992 END IF;
10993 END apply;
10994
10995
10996 --
10997 -- --------------------------------------------------------------------------
10998 -- What does it do:
10999 -- Determines final location control based on location controls defined at
11000 -- organization, subinventory and item level.
11001 -- --------------------------------------------------------------------------
11002 --
11003 FUNCTION loc_control
11004 ( p_org_control IN NUMBER
11005 ,p_sub_control IN NUMBER
11006 ,p_item_control IN NUMBER DEFAULT NULL
11007 ,x_return_status OUT NOCOPY VARCHAR2
11008 ,x_msg_count OUT NOCOPY NUMBER
11009 ,x_msg_data OUT NOCOPY VARCHAR2
11010 ) RETURN NUMBER
11011 IS
11012 --
11013 -- constants
11014 l_api_name CONSTANT VARCHAR(30) := 'loc_control';
11015 --
11016 -- return variable
11017 l_locator_control NUMBER;
11018 --
11019 -- exception
11020 invalid_loc_control_exception EXCEPTION;
11021 --
11022 BEGIN
11023 IF (p_org_control = 1) THEN
11024 l_locator_control := 1;
11025 ELSIF (p_org_control = 2) THEN
11026 l_locator_control := 2;
11027 ELSIF (p_org_control = 3) THEN
11028 l_locator_control := 2 ;
11029 ELSIF (p_org_control = 4) THEN
11030 IF (p_sub_control = 1) THEN
11031 l_locator_control := 1;
11032 ELSIF (p_sub_control = 2) THEN
11033 l_locator_control := 2;
11034 ELSIF (p_sub_control = 3) THEN
11035 l_locator_control := 2;
11036 ELSIF (p_sub_control = 5) THEN
11037 IF (p_item_control = 1) THEN
11038 l_locator_control := 1;
11039 ELSIF (p_item_control = 2) THEN
11040 l_locator_control := 2;
11041 ELSIF (p_item_control = 3) THEN
11042 l_locator_control := 2;
11043 ELSIF (p_item_control IS NULL) THEN
11044 l_locator_control := p_sub_control;
11045 ELSE
11046 RAISE invalid_loc_control_exception;
11047 END IF;
11048 ELSE
11049 RAISE invalid_loc_control_exception;
11050 END IF;
11051 ELSE
11052 RAISE invalid_loc_control_exception;
11053 END IF;
11054 --
11055 x_return_status := fnd_api.g_ret_sts_success;
11056 RETURN l_locator_control;
11057 EXCEPTION
11058 WHEN invalid_loc_control_exception THEN
11059 fnd_message.set_name('INV','INV_INVALID_LOC_CONTROL');
11060 fnd_msg_pub.ADD;
11061 --
11062 x_return_status := fnd_api.g_ret_sts_error ;
11063 l_locator_control := -1 ;
11064 RETURN l_locator_control ;
11065 --
11066 WHEN fnd_api.g_exc_error THEN
11067 x_return_status := fnd_api.g_ret_sts_error ;
11068 l_locator_control := -1 ;
11069 RETURN l_locator_control ;
11070 --
11071 WHEN fnd_api.g_exc_unexpected_error THEN
11072 x_return_status := fnd_api.g_ret_sts_unexp_error ;
11073 l_locator_control := -1 ;
11074 RETURN l_locator_control ;
11075 --
11076 WHEN OTHERS THEN
11077 x_return_status := fnd_api.g_ret_sts_unexp_error ;
11078 --
11079 IF (fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error)) THEN
11080 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
11081 END IF;
11082 --
11083 l_locator_control := -1 ;
11084 RETURN l_locator_control ;
11085 --
11086 END loc_control;
11087 --
11088 -- --------------------------------------------------------------------------
11089 -- What does it do:
11090 -- Fetches default putaway sub/locations.
11091 -- they are retained as putaway sub/locations
11092 -- The following call will be used for Non WMS enabled org where default putaway rules
11093 -- are not used and If the input sub/loc are not null,
11094 -- This Procedure called from Applydef()
11095 -- --------------------------------------------------------------------------
11096 --
11097 PROCEDURE get_putaway_defaults
11098 ( p_organization_id IN NUMBER,
11099 p_inventory_item_id IN NUMBER,
11100 p_to_subinventory_code IN VARCHAR2,
11101 p_to_locator_id IN NUMBER,
11102 p_to_cost_group_id IN NUMBER,
11103 p_org_locator_control_code IN NUMBER,
11104 p_item_locator_control_code IN NUMBER,
11105 p_transaction_type_id IN NUMBER,
11106 x_putaway_sub OUT NOCOPY VARCHAR2,
11107 x_putaway_loc OUT NOCOPY NUMBER,
11108 x_putaway_cost_group_id OUT NOCOPY NUMBER,
11109 x_return_status OUT NOCOPY VARCHAR2,
11110 x_msg_count OUT NOCOPY NUMBER,
11111 x_msg_data OUT NOCOPY VARCHAR2
11112 )
11113 IS
11114 -- constants
11115 l_api_name CONSTANT VARCHAR(30) := 'get_putaway_defaults';
11116 l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
11117 --
11118 -- variable
11119 l_sub_loc_control NUMBER;
11120 l_loc_control NUMBER;
11121 l_putaway_sub VARCHAR2(30);
11122 l_putaway_loc NUMBER;
11123 l_putaway_cg NUMBER := NULL;
11124 l_putaway_cg_org NUMBER;
11125 l_inventory_item_id NUMBER;
11126 l_organization_id NUMBER;
11127 l_sub_status NUMBER;
11128 l_loc_status NUMBER;
11129 l_allowed VARCHAR2(1);
11130 l_primary_cost_method NUMBER;
11131 l_sub_found BOOLEAN;
11132
11133 l_debug NUMBER;
11134 --
11135 CURSOR l_subinventory_code_csr IS
11136 SELECT subinventory_code
11137 FROM mtl_item_sub_defaults
11138 WHERE inventory_item_id = l_inventory_item_id
11139 AND organization_id = l_organization_id
11140 AND default_type = 3; -- default transfer order sub
11141
11142 CURSOR l_locator_status_csr IS
11143 SELECT status_id
11144 FROM mtl_item_locations
11145 WHERE inventory_location_id = l_putaway_loc
11146 AND organization_id = l_organization_id ;
11147 --
11148 CURSOR l_locator_csr IS
11149 SELECT locator_id
11150 FROM mtl_item_loc_defaults mtld,
11151 mtl_item_locations mil
11152 WHERE mtld.locator_id = mil.inventory_location_id
11153 AND mtld.organization_id = mil.organization_id
11154 AND mtld.inventory_item_id = l_inventory_item_id
11155 AND mtld.organization_id = l_organization_id
11156 AND mtld.subinventory_code = l_putaway_sub
11157 AND mtld.default_type = 3
11158 AND nvl(mil.disable_date,sysdate + 1) > sysdate;
11159
11160
11161 BEGIN
11162 l_organization_id := p_organization_id;
11163 l_inventory_item_id := p_inventory_item_id;
11164
11165 IF g_debug IS NOT NULL THEN
11166 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
11167 END IF;
11168 l_debug := g_debug;
11169
11170 IF l_debug = 1 THEN
11171 log_procedure(l_api_name, 'start', 'Start get_putaway_defaults');
11172 END IF;
11173
11174 -- search for default sub if to_sub in input row is null
11175 IF p_to_subinventory_code IS NULL THEN
11176 OPEN l_subinventory_code_csr;
11177 FETCH l_subinventory_code_csr INTO l_putaway_sub;
11178 IF l_subinventory_code_csr%notfound OR
11179 l_putaway_sub IS NULL THEN
11180 CLOSE l_subinventory_code_csr;
11181 fnd_message.set_name('INV','INV_NO_DEFAULT_SUB');
11182 fnd_msg_pub.ADD;
11183 RAISE fnd_api.g_exc_error;
11184 END IF;
11185 CLOSE l_subinventory_code_csr;
11186 ELSE
11187 l_putaway_sub := p_to_subinventory_code ;
11188 END IF;
11189
11190 l_sub_found := INV_CACHE.set_tosub_rec(l_organization_id, l_putaway_sub);
11191
11192 -- now get the locator control and then determine if
11193 -- default locator needs to be selected from item defaults
11194 --
11195 IF NOT l_sub_found THEN
11196 fnd_message.set_name('INV','INV_NO_SUB_LOC_CONTROL');
11197 fnd_msg_pub.ADD;
11198 RAISE fnd_api.g_exc_error;
11199 END if;
11200
11201 l_sub_loc_control := INV_CACHE.tosub_rec.locator_type;
11202
11203 IF l_debug = 1 THEN
11204 log_statement(l_api_name, 'p_org_locator_control_code', p_org_locator_control_code);
11205 log_statement(l_api_name, 'l_sub_loc_control ' , l_sub_loc_control);
11206 log_statement(l_api_name, 'p_item_locator_control_code' , p_item_locator_control_code);
11207 END IF;
11208
11209 -- find out the real locator control
11210
11211 l_loc_control := loc_control
11212 ( p_org_locator_control_code
11213 ,l_sub_loc_control
11214 ,p_item_locator_control_code
11215 ,l_return_status
11216 ,x_msg_count
11217 ,x_msg_data);
11218
11219 IF l_debug = 1 THEN
11220 log_statement(l_api_name, 'l_sub_loc_control ', l_sub_loc_control);
11221 log_statement(l_api_name, 'l_loc_control ' , l_loc_control);
11222 END IF;
11223
11224 IF l_return_status = fnd_api.g_ret_sts_error THEN
11225 RAISE fnd_api.g_exc_error ;
11226 ELSIF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
11227 RAISE fnd_api.g_exc_unexpected_error;
11228 END IF;
11229
11230 --
11231 IF l_loc_control = 2 THEN -- has locator control
11232 -- if no to_loc was supplied then get from defaults
11233 IF p_to_locator_id IS NULL THEN
11234 OPEN l_locator_csr;
11235 FETCH l_locator_csr INTO l_putaway_loc;
11236 IF l_locator_csr%notfound OR l_putaway_loc IS NULL THEN
11237 CLOSE l_locator_csr;
11238 fnd_message.set_name('INV','INV_NO_DEFAULT_LOC');
11239 fnd_msg_pub.ADD;
11240
11241 RAISE fnd_api.g_exc_error;
11242 END IF;
11243 ELSE
11244 l_putaway_loc := p_to_locator_id ;
11245 IF l_debug = 1 THEN
11246 log_statement(l_api_name, 'l_putaway_loc' , l_putaway_loc);
11247 END IF;
11248 END IF;
11249
11250 END IF;
11251
11252 -- Now get the cost group. If the to_cost_group is specified
11253 -- on the move order, then use that. If not, query the default
11254 -- cost group for the subinventory if in a standard costing org.
11255 -- If not defined there, or if avg. costing org
11256 -- try to get the default cost group from the organization
11257
11258 IF p_to_cost_group_id IS NULL THEN
11259 IF INV_CACHE.set_org_rec(l_organization_id) THEN
11260 l_primary_cost_method := INV_CACHE.org_rec.primary_cost_method;
11261 l_putaway_cg_org := INV_CACHE.org_rec.default_cost_group_id;
11262 ELSE
11263 l_primary_cost_method := 2;
11264 l_putaway_cg_org := NULL;
11265 End If;
11266
11267 If l_primary_cost_method = 1 Then
11268 IF l_sub_found THEN
11269 l_putaway_cg := INV_CACHE.tosub_rec.default_cost_group_id;
11270 ELSE
11271 l_putaway_cg := NULL;
11272 end if;
11273 End If;
11274
11275 If l_putaway_cg IS NULL Then
11276 l_putaway_cg := l_putaway_cg_org;
11277 if l_putaway_cg IS NULL then
11278 fnd_message.set_name('INV','INV_NO_DEFAULT_COST_GROUP');
11279 fnd_msg_pub.ADD;
11280 RAISE fnd_api.g_exc_error;
11281 end if;
11282 End If;
11283 ELSE
11284 l_putaway_cg := p_to_cost_group_id;
11285 END IF;
11286
11287 x_putaway_sub := l_putaway_sub;
11288 x_putaway_loc := l_putaway_loc;
11289 x_putaway_cost_group_id := l_putaway_cg;
11290 x_return_status := l_return_status;
11291 /*
11292 IF l_putaway_loc is NULL THEN
11293 x_return_status := 'N' ;
11294 END IF;
11295 */
11296
11297 If l_debug = 1 THEN
11298 log_statement(l_api_name, 'Default Putaway values l_putaway_sub ', l_putaway_sub);
11299 log_statement(l_api_name, 'Default Putaway values l_putaway_loc ', l_putaway_loc);
11300 log_statement(l_api_name, 'Default Putaway values l_putaway_cg ', l_putaway_cg);
11301 log_statement(l_api_name, 'Default Putaway values l_return_status ', l_return_status);
11302 END IF;
11303
11304
11305 EXCEPTION
11306 WHEN fnd_api.g_exc_error THEN
11307 x_return_status := fnd_api.g_ret_sts_error ;
11308 x_putaway_loc := NULL;
11309 x_putaway_sub := NULL;
11310 x_putaway_cost_group_id := NULL;
11311 --
11312 WHEN fnd_api.g_exc_unexpected_error THEN
11313 x_return_status := fnd_api.g_ret_sts_unexp_error ;
11314 x_putaway_loc := NULL;
11315 x_putaway_sub := NULL;
11316 x_putaway_cost_group_id := NULL;
11317 --
11318 WHEN OTHERS THEN
11319 x_return_status := fnd_api.g_ret_sts_unexp_error ;
11320 x_putaway_loc := NULL;
11321 x_putaway_sub := NULL;
11322 x_putaway_cost_group_id := NULL;
11323 --
11324 IF (fnd_msg_pub.check_msg_level
11325 (fnd_msg_pub.g_msg_lvl_unexp_error)) THEN
11326 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
11327 END IF;
11328 --
11329
11330 END get_putaway_defaults ;
11331 --
11332 -- API name : ApplyDefLoc
11333 -- Type : Private
11334 -- Function : Verifies a Putaway location with the given transaction
11335 -- input parameters and creates recommendations
11336 -- This API does not utlize the rules and should only be
11337 -- called when the Inventory Locator is specified on
11338 -- the input transaction and there is no requirement
11339 -- to check capacity.
11340 -- Pre-reqs :
11341 --
11342 -- Parameters :
11343 -- p_api_version Standard Input Parameter
11344 -- p_init_msg_list Standard Input Parameter
11345 -- p_commit Standard Input Parameter
11346 -- p_validation_level Standard Input Parameter
11347 -- p_transaction_temp_id Identifier for the record in view
11348 -- wms_strategy_mat_txn_tmp_v that represents
11349 -- the request for detailing
11350 -- p_organization_id Organization identifier
11351 -- p_inventory_item_id Inventory item identifier
11352 -- p_transaction_uom Transaction UOM code
11353 -- p_primary_uom Primary UOM code
11354 -- p_project_id Project associated with transaction
11355 -- p_task_id Task associated with transaction
11356 --
11357 -- Output Parameters
11358 -- x_return_status Standard Output Parameter
11359 -- x_msg_count Standard Output Parameter
11360 -- x_msg_data Standard Output Parameter
11361 -- x_finished whether the rule has found enough quantity to
11362 -- find a location that completely satisfy
11363 -- the requested quantity (value is 'Y' or 'N')
11364 --
11365 -- Version
11366 -- Currently version is 1.0
11367 --
11368 -- Notes : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
11369 -- This API must be called internally by
11370 -- WMS_Strategy_PVT.Apply only !
11371 --APPLY
11372 PROCEDURE applydefloc(
11373 p_api_version IN NUMBER ,
11374 p_init_msg_list IN VARCHAR2 ,
11375 p_commit IN VARCHAR2 ,
11376 p_validation_level IN NUMBER ,
11377 x_return_status OUT NOCOPY VARCHAR2 ,
11378 x_msg_count OUT NOCOPY NUMBER ,
11379 x_msg_data OUT NOCOPY VARCHAR2 ,
11380 p_transaction_temp_id IN NUMBER ,
11381 p_organization_id IN NUMBER ,
11382 p_inventory_item_id IN NUMBER ,
11383 p_subinventory_code IN VARCHAR2 ,
11384 p_locator_id IN NUMBER ,
11385 p_transaction_uom IN VARCHAR2 ,
11386 p_primary_uom IN VARCHAR2 ,
11387 p_transaction_type_id IN NUMBER ,
11388 x_finished OUT NOCOPY VARCHAR2 ,
11389 p_lpn_id IN NUMBER ,
11390 p_simulation_mode IN NUMBER ,
11391 p_project_id IN NUMBER ,
11392 p_task_id IN NUMBER
11393 )
11394 IS
11395
11396 -- API standard variables
11397 l_api_version constant number := 1.0;
11398 l_api_name constant varchar2(30) := 'ApplyDefLoc';
11399 -- variables needed for dynamic SQL
11400 l_cursor integer;
11401 l_rows integer;
11402 -- rule dynamic SQL input variables
11403 l_pp_transaction_temp_id
11404 WMS_TRANSACTIONS_TEMP.PP_TRANSACTION_TEMP_ID%TYPE;
11405 l_revision WMS_TRANSACTIONS_TEMP.REVISION%TYPE;
11406 l_lot_number WMS_TRANSACTIONS_TEMP.LOT_NUMBER%TYPE;
11407 l_lot_expiration_date WMS_TRANSACTIONS_TEMP.LOT_EXPIRATION_DATE%TYPE;
11408 l_from_subinventory_code WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
11409 l_to_subinventory_code WMS_TRANSACTIONS_TEMP.TO_SUBINVENTORY_CODE%TYPE;
11410 l_from_locator_id WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11411 l_to_locator_id WMS_TRANSACTIONS_TEMP.TO_LOCATOR_ID%TYPE;
11412 l_from_cost_group_id WMS_TRANSACTIONS_TEMP.FROM_COST_GROUP_ID%TYPE;
11413 l_to_cost_group_id WMS_TRANSACTIONS_TEMP.TO_COST_GROUP_ID%TYPE;
11414 l_lpn_id WMS_TRANSACTIONS_TEMP.LPN_ID%TYPE;
11415 l_initial_pri_quantity WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
11416 -- rule dynamic SQL output variables
11417 l_osubinventory_code WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
11418 l_olocator_id WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11419 l_olocator_id_prev WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11420 l_olocator_id_new WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11421 l_olocator_id_exist WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11422 l_possible_quantity WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
11423 l_possible_trx_qty WMS_TRANSACTIONS_TEMP.TRANSACTION_QUANTITY%TYPE;
11424 l_sec_possible_quantity WMS_TRANSACTIONS_TEMP.PRIMARY_QUANTITY%TYPE;
11425 l_sec_possible_trx_qty WMS_TRANSACTIONS_TEMP.TRANSACTION_QUANTITY%TYPE;
11426 l_reservation_id WMS_TRANSACTIONS_TEMP.RESERVATION_ID%TYPE;
11427 l_grade_code VARCHAR2(150);
11428
11429 l_needed_quantity NUMBER;
11430 l_sec_needed_quantity NUMBER;
11431 l_locs_index NUMBER;
11432 l_return_status VARCHAR2(1);
11433 l_allowed VARCHAR2(1);
11434 l_debug_on BOOLEAN;
11435 l_check_cg BOOLEAN;
11436 l_lpn_controlled_flag NUMBER;
11437 l_comingle VARCHAR2(1);
11438 l_dummy NUMBER;
11439
11440 --added to support pjm
11441 l_project_id NUMBER;
11442 l_task_id NUMBER;
11443 l_input_lpn_id NUMBER;
11444 l_debug NUMBER;
11445 l_serial_number NUMBER; -- [ new code ]
11446 use_supplied_loc BOOLEAN;
11447
11448 l_locator_type NUMBER;
11449 x_subinventory_code WMS_TRANSACTIONS_TEMP.FROM_SUBINVENTORY_CODE%TYPE;
11450 x_locator_id WMS_TRANSACTIONS_TEMP.FROM_LOCATOR_ID%TYPE;
11451 x_cost_group_id WMS_TRANSACTIONS_TEMP.FROM_COST_GROUP_ID%TYPE;
11452
11453 --cursor to get lpn controlled flag from subinventory
11454 CURSOR l_lpn_controlled IS
11455 SELECT lpn_controlled_flag
11456 FROM mtl_secondary_inventories
11457 WHERE organization_id = p_organization_id
11458 AND secondary_inventory_name = l_osubinventory_code;
11459
11460
11461 BEGIN
11462
11463 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
11464 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
11465 END IF;
11466 l_debug := g_debug;
11467
11468 If (l_debug = 1) then
11469 log_procedure(l_api_name, 'start', 'Start ApplyDefLoc');
11470 End if;
11471 -- end of debugging section
11472
11473 -- Standard start of API savepoint
11474 SAVEPOINT ApplyRuleSP;
11475 --
11476
11477
11478 -- Standard call to check for call compatibility
11479 IF NOT fnd_api.compatible_api_call( l_api_version
11480 ,p_api_version
11481 ,l_api_name
11482 ,g_pkg_name ) THEN
11483 RAISE fnd_api.g_exc_unexpected_error;
11484 END IF;
11485
11486 -- Initialize message list if p_init_msg_list is set to TRUE
11487 IF fnd_api.to_boolean( p_init_msg_list ) THEN
11488 fnd_msg_pub.initialize;
11489 END IF;
11490 --
11491 -- Initialize API return status to success
11492 x_return_status := fnd_api.g_ret_sts_success;
11493 --
11494 -- Initialize functional return status to completed
11495 x_finished := fnd_api.g_true;
11496 --
11497 -- Validate input parameters and pre-requisites, if validation level
11498 -- requires this
11499 IF p_validation_level <> fnd_api.g_valid_level_none THEN
11500 IF p_transaction_temp_id IS NULL OR
11501 p_transaction_temp_id = fnd_api.g_miss_num THEN
11502 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
11503 fnd_message.set_name('WMS','WMS_TRX_REQ_LINE_ID_MISS');
11504 If (l_debug = 1) then
11505 log_error_msg(l_api_name, 'trx_req_line_id_missing');
11506 End if;
11507 fnd_msg_pub.add;
11508 END IF;
11509 RAISE fnd_api.g_exc_error;
11510 END IF;
11511 IF p_organization_id IS NULL OR
11512 p_organization_id = fnd_api.g_miss_num THEN
11513 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
11514 fnd_message.set_name('INV','INV_NO_ORG_INFORMATION');
11515 If (l_debug = 1) then
11516 log_error_msg(l_api_name, 'org_id_missing');
11517 End if;
11518 fnd_msg_pub.add;
11519 END IF;
11520 RAISE fnd_api.g_exc_error;
11521 END IF;
11522 IF p_inventory_item_id IS NULL OR
11523 p_inventory_item_id = fnd_api.g_miss_num THEN
11524 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
11525 fnd_message.set_name('INV','INV_ITEM_ID_REQUIRED');
11526 If (l_debug = 1) then
11527 log_error_msg(l_api_name, 'item_id_missing');
11528 End if;
11529 fnd_msg_pub.add;
11530 END IF;
11531 RAISE fnd_api.g_exc_error;
11532 END IF;
11533 END IF;
11534 --inv_pp_debug.send_message_to_pipe('finished validations');
11535
11536 --
11537 -- make sure, everything is clean
11538 FreeGlobals;
11539 wms_parameter_pvt.ClearCache;
11540 --
11541 g_trace_recs.DELETE;
11542 l_debug_on := IsRuleDebugOn(p_simulation_mode);
11543
11544 if (l_debug = 1) then
11545 log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
11546 log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
11547 End if;
11548
11549 -- Initialize the pointer to the first trx detail input line
11550 wms_re_common_pvt.InitInputPointer;
11551 --
11552 If (l_debug = 1) then
11553 log_statement(l_api_name, 'start_input_loop',
11554 'Starting loop through input lines');
11555 End if;
11556
11557 -- Set the output locator and Sub to the supplied parameters
11558 l_osubinventory_code := p_subinventory_code;
11559 l_olocator_id := p_locator_id;
11560
11561 -- Loop through all the trx detail input lines
11562 -- Bug # 4637357
11563 use_supplied_loc := TRUE;
11564 WHILE use_supplied_loc LOOP
11565 If (l_debug = 1) then
11566 log_statement(l_api_name, 'getting input line',
11567 'calling wms_re_common_pvt.GetNextInputLine to get input line');
11568 End if;
11569
11570 --
11571 -- Get the next trx detail input line
11572 wms_re_common_pvt.GetNextInputLine ( l_pp_transaction_temp_id
11573 ,l_revision
11574 ,l_lot_number
11575 ,l_lot_expiration_date
11576 ,l_from_subinventory_code
11577 ,l_from_locator_id
11578 ,l_from_cost_group_id
11579 ,l_to_subinventory_code
11580 ,l_to_locator_id
11581 ,l_to_cost_group_id
11582 ,l_needed_quantity
11583 ,l_sec_needed_quantity
11584 ,l_grade_code
11585 ,l_reservation_id
11586 ,l_serial_number -- [ new code ]
11587 ,l_lpn_Id);
11588 EXIT WHEN l_pp_transaction_temp_id IS NULL;
11589
11590
11591 IF ( p_subinventory_code is NULL AND p_locator_id is NULL ) THEN
11592 -- Set the output locator and Sub to the inlput line sub/loc
11593 l_osubinventory_code := l_to_subinventory_code;
11594 l_olocator_id := l_to_locator_id;
11595
11596 END IF;
11597
11598
11599 If (l_debug = 1) then
11600 log_statement(l_api_name, 'input_rec', 'Got next input line');
11601 log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
11602 log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
11603 log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
11604 log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
11605 log_statement(l_api_name, 'input_cg', 'cg:' || l_from_cost_group_id);
11606 log_statement(l_api_name, 'input_tsub','tsub:'|| l_to_subinventory_code);
11607 log_statement(l_api_name, 'input_tloc','tloc:'|| l_to_locator_id);
11608 log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
11609 log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
11610 log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
11611 log_statement(l_api_name, 'input_sec_qty', 'sec qty:' || l_sec_needed_quantity);
11612 End if;
11613 --- Bug#4729564
11614 --- Populate default dest. loct for non-wms org if it is null and raise error if locator is null for dynamic loc controlled.
11615
11616 get_putaway_defaults ( p_organization_id ,
11617 p_inventory_item_id,
11618 l_to_subinventory_code,
11619 l_to_locator_id,
11620 l_to_cost_group_id,
11621 inv_cache.org_rec.stock_locator_control_code,
11622 inv_cache.item_rec.location_control_code,
11623 p_transaction_type_id,
11624 x_subinventory_code ,
11625 x_locator_id,
11626 x_cost_group_id,
11627 x_return_status,
11628 x_msg_count,
11629 x_msg_data );
11630
11631 -- log_statement(l_api_name, 'Default Putaway values l_return_status ', l_return_status);
11632
11633 IF l_return_status = fnd_api.g_ret_sts_error THEN
11634 RAISE fnd_api.g_exc_error ;
11635 -- log_statement(l_api_name, 'ApplyDef()', 'Dest Loct is NUll' );
11636 -- GOTO NextOutputRecord;
11637 ELSIF l_return_status = fnd_api.g_ret_sts_unexp_error THEN
11638 RAISE fnd_api.g_exc_unexpected_error;
11639 END IF;
11640
11641 --log_statement(l_api_name, 'l_to_locator_id',nvl(l_to_locator_id, -9999) );
11642 IF (l_osubinventory_code is NULL AND x_subinventory_code is not NULL ) then
11643 l_osubinventory_code := x_subinventory_code;
11644 If (l_debug = 1 ) then
11645 log_statement(l_api_name, 'Setting default SUB ', l_osubinventory_code);
11646 End if;
11647 END IF;
11648
11649 IF (l_olocator_id is NULL and x_locator_id is not NULL) THEN
11650 l_osubinventory_code := x_subinventory_code;
11651 l_olocator_id := x_locator_id;
11652 If (l_debug = 1 ) then
11653 log_statement(l_api_name, 'Setting default SUB / LOC ', l_osubinventory_code);
11654 log_statement(l_api_name, 'Setting default LOC ', l_olocator_id);
11655 End if;
11656 END IF;
11657
11658 IF (l_to_cost_group_id is NULL and x_cost_group_id is NOT NULL ) THEN
11659 l_to_cost_group_id := x_cost_group_id;
11660 END IF;
11661 -- Bug 5682045 Changed l_to_locator_id to l_olocator_id
11662 IF l_olocator_id is NULL THEN
11663 l_locator_type := NULL;
11664
11665 -- log_statement(l_api_name, 'p_organization_id :', p_organization_id);
11666 log_statement(l_api_name, 'To check dynamic loc : l_to_subinventory_code', l_to_subinventory_code);
11667
11668 select locator_type into l_locator_type
11669 from mtl_secondary_inventories
11670 where organization_id = p_organization_id
11671 and SECONDARY_INVENTORY_NAME = l_to_subinventory_code;
11672
11673 -- log_statement(l_api_name, 'l_locator_type' , l_locator_type);
11674
11675 IF l_locator_type = 3 or l_locator_type = 2 THEN -- Dynamic / Prespecified Loc Control
11676 If (l_debug = 1 ) then
11677 log_statement(l_api_name, 'Default Putaway values l_return_status ', l_return_status);
11678 log_statement(l_api_name, 'ApplyDef()', 'Dest Loct is NUll / Go to Next record ' );
11679 End if;
11680
11681 GOTO NextOutputRecord;
11682 END if;
11683 END IF;
11684 -- end of Bug#4729564
11685 --
11686
11687 -- use_supplied_loc := TRUE;
11688 -- To support PJM, check project and task if supplied.
11689 -- Case 1) Project and Task not supplied do nothing
11690 -- 2) Project and Task Supplied and current record has same
11691 -- project and task continue processing.
11692 -- 3) Project and Task supplied, not in current record
11693 -- then create a new entry in MTL_ITEM_LOCATIONS with
11694 -- properties of current record but with require project and task
11695 -- <This assumes that the results are ordered by Project and Task>
11696 IF p_project_id IS NOT NULL THEN
11697
11698 --bug 2400549 - for WIP backflush transfer putaway,
11699 --always use the locator specified on the move order line, even
11700 --if that locator is from common stock (not project)
11701 IF NOT(wms_engine_pvt.g_move_order_type = 7 and
11702 wms_engine_pvt.g_transaction_action_id = 2) THEN
11703 If (l_debug = 1) then
11704 log_statement(l_api_name, 'do_project2',
11705 'Calling do project check');
11706 End if;
11707 IF DoProjectCheck(l_return_status, l_olocator_id,
11708 p_project_id, p_task_id, l_olocator_id_new, l_olocator_id_exist)
11709 THEN
11710 If (l_debug = 1) then
11711 log_statement(l_api_name, 'do_project_success',
11712 'Do project check returned new locator');
11713 End if;
11714 l_olocator_id_prev := l_olocator_id;
11715 l_olocator_id := l_olocator_id_new;
11716 ELSE
11717 -- Current locator does not have required project/task
11718 -- If it exists use it
11719 If l_olocator_id_exist IS NOT NULL THEN
11720 l_olocator_id := l_olocator_id_exist;
11721 ELSE
11722 use_supplied_loc := false;
11723 x_finished := fnd_api.g_false;
11724 If (l_debug = 1) then
11725 log_statement(l_api_name, 'do_project_fail',
11726 'Do project check failed. Cannot use supplied locator with this Project and Task.');
11727 End if;
11728 End if;
11729 END IF; --do project check
11730 END IF; -- not wip backflush
11731 END IF; -- needed project <> -9999
11732
11733
11734 --check status to see if putting away to this location is allowed
11735 -- for this transaction type
11736 -- This API checks the status for the subinventory, locator,
11737 -- and lot
11738
11739 -- Pass in NULL for lot number as this was checked during Pick
11740 If (l_debug = 1) then
11741 log_statement(l_api_name, 'checking_status',
11742 'calling is_sub_loc_lot_trx_allowed to check status');
11743 End if;
11744 If g_transaction_type_id = p_transaction_type_id AND
11745 g_organization_id = p_organization_id AND
11746 g_inventory_item_id = p_inventory_item_id AND
11747 g_subinventory_code = l_osubinventory_code AND
11748 g_st_locator_id = l_olocator_id THEN
11749 l_allowed := g_allowed;
11750 ELSE
11751
11752 l_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
11753 p_transaction_type_id => p_transaction_type_id
11754 ,p_organization_id => p_organization_id
11755 ,p_inventory_item_id => p_inventory_item_id
11756 ,p_subinventory_code => l_osubinventory_code
11757 ,p_locator_id => l_olocator_id
11758 ,p_lot_number => NULL);
11759
11760
11761 -- When changing SUB value set lpn_controlled_flag to null
11762 IF (g_organization_id = p_organization_id) OR (g_subinventory_code <> l_osubinventory_code) THEN
11763 g_lpn_controlled_flag := NULL;
11764 END IF;
11765
11766 g_transaction_type_id := p_transaction_type_id;
11767 g_organization_id := p_organization_id;
11768 g_inventory_item_id := p_inventory_item_id;
11769 g_subinventory_code := l_osubinventory_code;
11770 g_st_locator_id := l_olocator_id;
11771 g_allowed := l_allowed;
11772 END IF;
11773
11774 IF l_allowed <> 'Y' THEN
11775 use_supplied_loc := false;
11776 x_finished := fnd_api.g_false;
11777 If (l_debug = 1) then
11778 log_event(l_api_name, 'bad_status',
11779 'This transaction type is not allowed by the status ' ||
11780 'for the subinventory, locator. ');
11781 End if;
11782 END IF;
11783
11784 /* Commented and moved the following code above
11785 Check the tag bug # 4637357
11786
11787 -- Loop through all the trx detail input lines
11788 WHILE use_supplied_loc LOOP
11789 If (l_debug = 1) then
11790 log_statement(l_api_name, 'getting input line',
11791 'calling wms_re_common_pvt.GetNextInputLine to get input line');
11792 End if;
11793
11794 --
11795 -- Get the next trx detail input line
11796 wms_re_common_pvt.GetNextInputLine ( l_pp_transaction_temp_id
11797 ,l_revision
11798 ,l_lot_number
11799 ,l_lot_expiration_date
11800 ,l_from_subinventory_code
11801 ,l_from_locator_id
11802 ,l_from_cost_group_id
11803 ,l_to_subinventory_code
11804 ,l_to_locator_id
11805 ,l_to_cost_group_id
11806 ,l_needed_quantity
11807 ,l_sec_needed_quantity
11808 ,l_grade_code
11809 ,l_reservation_id
11810 ,l_serial_number -- [ new code ]
11811 ,l_lpn_Id);
11812 EXIT WHEN l_pp_transaction_temp_id IS NULL;
11813
11814 If (l_debug = 1) then
11815 log_statement(l_api_name, 'input_rec', 'Got next input line');
11816 log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
11817 log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
11818 log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
11819 log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
11820 log_statement(l_api_name, 'input_cg', 'cg:' || l_from_cost_group_id);
11821 log_statement(l_api_name, 'input_tsub','tsub:'|| l_to_subinventory_code);
11822 log_statement(l_api_name, 'input_tloc','tloc:'|| l_to_locator_id);
11823 log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
11824 log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
11825 log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
11826 log_statement(l_api_name, 'input_sec_qty', 'sec qty:' || l_sec_needed_quantity);
11827 End if;
11828 */
11829 -- Save the initial input qty for later usage
11830 l_initial_pri_quantity := l_needed_quantity;
11831 --
11832 l_input_lpn_id := l_lpn_id;
11833
11834 l_locs_index := 0;
11835
11836 IF l_debug_on THEN
11837 g_trace_recs(l_locs_index).revision := l_revision;
11838 g_trace_recs(l_locs_index).lot_number := l_lot_number;
11839 g_trace_recs(l_locs_index).lot_expiration_date := l_lot_expiration_date;
11840 g_trace_recs(l_locs_index).subinventory_code := l_osubinventory_code;
11841 g_trace_recs(l_locs_index).locator_id := l_olocator_id;
11842 g_trace_recs(l_locs_index).cost_group_id := l_to_cost_group_id;
11843 g_trace_recs(l_locs_index).uom_code := NULL;
11844 g_trace_recs(l_locs_index).lpn_id := l_input_lpn_id;
11845 g_trace_recs(l_locs_index).quantity := NULL;
11846 --init to 0, in case of error
11847 g_trace_recs(l_locs_index).suggested_qty := 0;
11848 g_trace_recs(l_locs_index).Material_status_flag := 'Y';
11849
11850 log_statement(l_api_name, 'fetch_put_sub',
11851 'Subinventory: ' || l_osubinventory_code);
11852 log_statement(l_api_name, 'fetch_put_loc',
11853 'Locator: ' || l_olocator_id);
11854 log_statement(l_api_name, 'fetch_put_proj',
11855 'Project: ' || l_project_id);
11856 log_statement(l_api_name, 'fetch_put_task',
11857 'Task: ' || l_task_id);
11858
11859
11860 END IF;
11861
11862 --Determine if putaway sub is LPN controlled. If it is not,
11863 --then we need to check cost group commingling always;
11864 -- Check cost group if
11865 -- Cost group is not null AND
11866 -- (sub is not lpn controlled OR
11867 -- No lpn on move order line OR
11868 -- not a staging transfer)
11869 --Never suggest comingling of cost groups, unless we are
11870 -- putting away a LPN.
11871 --When putting away an LPN, we assume that user is putting away
11872 -- whole LPN, which means there will never be comingling.
11873 --bug 1570597 - staging transfers are always put away in an LPN,
11874 -- so we don't need to check for comingling.
11875 --bug 2161565 - need to check for cg commingling if
11876 -- to subinventory is not LPN controlled.
11877 --bug 2492526 - putting away to a project controlled locator
11878 -- will always change the CG. So no need to worry about CG
11879 -- commingling if the dest. loc is project controlled.
11880 If (l_debug = 1) then
11881 log_statement(l_api_name, 'Check LPN Controlled',
11882 'Check if cost group or project supplied and lpn controlled');
11883 End if;
11884 IF l_to_cost_group_id IS NULL THEN
11885 l_check_cg := FALSE;
11886 ELSIF l_project_id IS NOT NULL THEN
11887 l_check_cg := FALSE;
11888 ELSIF (p_lpn_id IS NOT NULL OR
11889 p_transaction_type_id IN (52,53)) THEN
11890
11891 If (nvl(g_subinventory_code,'-9999') <> l_osubinventory_code OR
11892 g_lpn_controlled_flag IS NULL) THEN
11893 OPEN l_lpn_controlled;
11894 FETCH l_lpn_controlled INTO g_lpn_controlled_flag;
11895 g_subinventory_code := l_osubinventory_code;
11896
11897 -- by default, assume sub is lpn controlled
11898 If l_lpn_controlled%notfound OR
11899 g_lpn_controlled_flag IS NULL OR
11900 g_lpn_controlled_flag NOT IN (1,2) Then
11901 g_lpn_controlled_flag := 1;
11902 End If;
11903 CLOSE l_lpn_controlled;
11904 End If;
11905 l_lpn_controlled_flag := g_lpn_controlled_flag;
11906
11907 If (l_debug = 1) then
11908 log_statement(l_api_name, 'Check LPN Controlled',
11909 'lpn_control_flag : ' || l_lpn_controlled_flag);
11910 End if;
11911
11912 If l_lpn_controlled_flag = 1 Then
11913 l_check_cg := FALSE;
11914 Else
11915 l_check_cg := TRUE;
11916 End If;
11917 ELSE
11918 l_check_cg := TRUE;
11919 END IF;
11920 --Check to see if putaway would comingle cost groups.
11921 IF l_check_cg THEN
11922 If (l_debug = 1) then
11923 log_statement(l_api_name, 'Check comingling',
11924 'calling inv_comingling_utils.comingle_check');
11925 End if;
11926 inv_comingling_utils.comingle_check(
11927 x_return_status => x_return_status
11928 ,x_msg_count => x_msg_count
11929 ,x_msg_data => x_msg_data
11930 ,x_comingling_occurs => l_comingle
11931 ,x_count => l_dummy
11932 ,p_organization_id => p_organization_id
11933 ,p_inventory_item_id => p_inventory_item_id
11934 ,p_revision => l_revision
11935 ,p_lot_number => l_lot_number
11936 ,p_subinventory_code => l_osubinventory_code
11937 ,p_locator_id => l_olocator_id
11938 ,p_lpn_id => NULL
11939 ,p_cost_group_id => l_to_cost_group_id
11940 );
11941 if x_return_status = fnd_api.g_ret_sts_unexp_error then
11942 If (l_debug = 1) then
11943 log_statement(l_api_name, 'uerr_comingle_check',
11944 'Unexpected error in comingle_check');
11945 End if;
11946 RAISE fnd_api.g_exc_unexpected_error;
11947 elsif x_return_status = fnd_api.g_ret_sts_error then
11948 If (l_debug = 1) then
11949 log_statement(l_api_name, 'err_comingle_check',
11950 'Error in comingle_check');
11951 End if;
11952 RAISE fnd_api.g_exc_error;
11953 end if;
11954
11955 -- Skip record if it would cause comingling
11956 if l_comingle = 'Y' then
11957 If (l_debug = 1) then
11958 log_event(l_api_name, 'comingle_putaway',
11959 'Putaway to this location would comingle cost groups. ');
11960 End if;
11961 if l_debug_on then
11962 g_trace_recs(l_locs_index).CG_comingle_flag := 'N';
11963 end if;
11964 GOTO NextOutputRecord;
11965 end if;
11966
11967 if l_debug_on then
11968 g_trace_recs(l_locs_index).CG_comingle_flag := 'Y';
11969 end if;
11970
11971 END IF;
11972
11973 l_possible_quantity := l_needed_quantity;
11974 l_sec_possible_quantity := l_sec_needed_quantity;
11975
11976 IF l_debug_on THEN
11977 g_trace_recs(l_locs_index).suggested_qty := l_possible_quantity;
11978 END IF;
11979
11980 -- get the transaction quantity
11981 IF p_transaction_uom = p_primary_uom THEN
11982 l_possible_trx_qty := l_possible_quantity;
11983 ELSE
11984 l_possible_trx_qty :=
11985 inv_convert.inv_um_convert(
11986 p_inventory_item_id
11987 ,NULL
11988 ,l_possible_quantity
11989 ,p_primary_uom
11990 ,p_transaction_uom
11991 ,NULL
11992 ,NULL);
11993 END IF;
11994 l_sec_possible_trx_qty := l_sec_possible_quantity;
11995 If (l_debug = 1) then
11996 log_statement(l_api_name, 'insert_put_wtt_recs',
11997 'Inserting putaway records in wtt');
11998 End if;
11999 -- insert temporary suggestion
12000 INSERT
12001 INTO WMS_TRANSACTIONS_TEMP
12002 ( PP_TRANSACTION_TEMP_ID
12003 ,TRANSACTION_TEMP_ID
12004 ,TYPE_CODE
12005 ,LINE_TYPE_CODE
12006 ,TRANSACTION_QUANTITY
12007 ,PRIMARY_QUANTITY
12008 ,SECONDARY_QUANTITY
12009 ,GRADE_CODE
12010 ,REVISION
12011 ,LOT_NUMBER
12012 ,LOT_EXPIRATION_DATE
12013 ,FROM_SUBINVENTORY_CODE
12014 ,FROM_LOCATOR_ID
12015 ,RULE_ID
12016 ,RESERVATION_ID
12017 ,TO_SUBINVENTORY_CODE
12018 ,TO_LOCATOR_ID
12019 ,FROM_COST_GROUP_ID
12020 ,TO_COST_GROUP_ID
12021 ,LPN_ID
12022 ) VALUES
12023 ( wms_transactions_temp_s.NEXTVAL
12024 ,p_transaction_temp_id
12025 ,1 -- p_type_code
12026 ,2 -- line type code is output
12027 ,l_possible_trx_qty
12028 ,l_possible_quantity
12029 ,l_sec_possible_quantity
12030 ,l_grade_code
12031 ,l_revision
12032 ,l_lot_number
12033 ,l_lot_expiration_date
12034 ,l_from_subinventory_code
12035 ,l_from_locator_id
12036 ,NULL -- l_rule_id
12037 ,l_reservation_id
12038 ,l_osubinventory_code
12039 ,l_olocator_id
12040 ,l_from_cost_group_id
12041 ,l_to_cost_group_id
12042 ,l_input_lpn_id
12043 );
12044
12045 If (l_debug = 1) then
12046 log_event(l_api_name, 'putaway_loc_found',
12047 'Found put away location for quantity ' || l_possible_quantity);
12048 End if;
12049
12050 l_needed_quantity := 0;
12051
12052 <<NextOutputRecord>>
12053
12054
12055
12056 -- if input line couldn't get satisfied ...
12057 IF l_needed_quantity > 0 THEN
12058 -- notice, that at least one input record couldn't get satisfied
12059 x_finished := fnd_api.g_false;
12060 If (l_debug = 1) then
12061 log_event(l_api_name, 'no_success',
12062 'Locator supplied could not be used');
12063 End if;
12064
12065 ELSE
12066 x_finished := fnd_api.g_true;
12067 -- if input line could get satisfied
12068 -- delete the input line in the wms_transactions_temp table
12069 If (l_debug = 1) then
12070 log_statement(l_api_name, 'deleting_input_rec',
12071 'Deleting the input line in WTT and pl/sql table');
12072 End if;
12073 DELETE
12074 FROM WMS_TRANSACTIONS_TEMP
12075 WHERE pp_transaction_temp_id = l_pp_transaction_temp_id;
12076 --
12077 -- and delete input record in PL/SQL table, too
12078 wms_re_common_pvt.DeleteInputLine;
12079 END IF;
12080 IF l_debug_on THEN
12081 wms_search_order_globals_pvt.insert_trace_lines(
12082 p_api_version => 1.0
12083 ,p_init_msg_list => fnd_api.g_false
12084 ,p_validation_level => fnd_api.g_valid_level_full
12085 ,x_return_status => l_return_status
12086 ,x_msg_count => x_msg_count
12087 ,x_msg_data => x_msg_data
12088 ,p_header_id => wms_engine_pvt.g_trace_header_id
12089 ,p_rule_id => null
12090 ,p_pre_suggestions => g_trace_recs
12091 );
12092 END IF;
12093
12094 END LOOP; -- input records
12095 --
12096 -- Standard check of p_commit
12097 IF fnd_api.to_boolean(p_commit) THEN
12098 COMMIT WORK;
12099 END IF;
12100 --
12101 If (l_debug = 1) then
12102 log_procedure(l_api_name, 'end', 'End Apply');
12103 End if;
12104 l_debug := NULL;
12105 --
12106 EXCEPTION
12107 WHEN fnd_api.g_exc_error THEN
12108
12109 ROLLBACK TO ApplyRuleSP;
12110 FreeGlobals;
12111 x_return_status := fnd_api.g_ret_sts_error;
12112 fnd_msg_pub.count_and_get( p_count => x_msg_count
12113 ,p_data => x_msg_data );
12114 If (l_debug = 1) then
12115 log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
12116 End if;
12117 l_debug := NULL;
12118 --
12119 WHEN fnd_api.g_exc_unexpected_error THEN
12120 ROLLBACK TO ApplyRuleSP;
12121 FreeGlobals;
12122 x_return_status := fnd_api.g_ret_sts_unexp_error;
12123 fnd_msg_pub.count_and_get( p_count => x_msg_count
12124 ,p_data => x_msg_data );
12125 If (l_debug = 1) then
12126 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
12127 End if;
12128 l_debug := NULL;
12129 --
12130 WHEN OTHERS THEN
12131
12132 ROLLBACK TO ApplyRuleSP;
12133 FreeGlobals;
12134 x_return_status := fnd_api.g_ret_sts_unexp_error;
12135 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12136 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
12137 END IF;
12138 fnd_msg_pub.count_and_get( p_count => x_msg_count
12139 ,p_data => x_msg_data );
12140 If (l_debug = 1) then
12141 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
12142 End if;
12143 l_debug := NULL;
12144
12145 END applydefloc;
12146
12147
12148
12149 --
12150 --
12151 -- API name : CheckSyntax
12152 -- Type : Private
12153 -- Function : This wrapper on Generate_Rule_Package is
12154 -- called from the WMS_RULES form
12155 -- Pre-reqs : one record in WMS_RULES_B uniquely identified by parameter
12156 -- p_rule_id
12157 -- Input Parameters :
12158 -- p_api_version Standard Input Parameter
12159 -- p_init_msg_list Standard Input Parameter
12160 -- p_validation_level Standard Input Parameter
12161 -- p_rule_id Identifier of the rule to check
12162 --
12163 -- Output Parameters :
12164 -- x_return_status Standard Output Parameter
12165 -- x_msg_count Standard Output Parameter
12166 -- x_msg_data Standard Output Parameter
12167 --
12168 -- Version :
12169 -- Current version 1.0
12170 --
12171 -- Notes : calls API's of WMS_RE_Common_PVT
12172 --
12173 PROCEDURE checksyntax(
12174 p_api_version IN NUMBER
12175 , p_init_msg_list IN VARCHAR2
12176 , p_validation_level IN NUMBER
12177 , x_return_status OUT NOCOPY VARCHAR2
12178 , x_msg_count OUT NOCOPY NUMBER
12179 , x_msg_data OUT NOCOPY VARCHAR2
12180 , p_rule_id IN NUMBER
12181 ) IS
12182 PRAGMA AUTONOMOUS_TRANSACTION;
12183 -- API standard variables
12184 l_api_version CONSTANT NUMBER := 1.0;
12185 l_api_name CONSTANT VARCHAR2(30) := 'CheckSyntax';
12186 --
12187 --
12188 BEGIN
12189 --
12190 -- Standard call to check for call compatibility
12191 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
12192 RAISE fnd_api.g_exc_unexpected_error;
12193 END IF;
12194
12195 -- Initialize message list if p_init_msg_list is set to TRUE
12196 IF fnd_api.to_boolean(p_init_msg_list) THEN
12197 fnd_msg_pub.initialize;
12198 END IF;
12199
12200 --
12201 -- Initialize API return status to success
12202 x_return_status := fnd_api.g_ret_sts_success;
12203 generaterulepackage(p_api_version, p_init_msg_list, p_validation_level, x_return_status, x_msg_count, x_msg_data, p_rule_id);
12204
12205 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12206 RAISE fnd_api.g_exc_unexpected_error;
12207 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12208 RAISE fnd_api.g_exc_error;
12209 END IF;
12210
12211 EXCEPTION
12212 WHEN fnd_api.g_exc_error THEN
12213 --
12214 x_return_status := fnd_api.g_ret_sts_error;
12215 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12216 --
12217 WHEN fnd_api.g_exc_unexpected_error THEN
12218 x_return_status := fnd_api.g_ret_sts_unexp_error;
12219 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12220 --
12221 WHEN OTHERS THEN
12222 freeglobals;
12223 x_return_status := fnd_api.g_ret_sts_unexp_error;
12224
12225 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12226 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
12227 END IF;
12228
12229 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12230 --
12231 END checksyntax;
12232
12233 --
12234 -- API name : Find_Rule
12235 -- Type : Private
12236 -- Function : find a rule by id
12237 -- Input Parameters :
12238 -- p_api_version Standard Input Parameter
12239 -- p_init_msg_list Standard Input Parameter
12240 -- p_rule_id Identifier of the rule
12241 --
12242 -- Output Parameters:
12243 -- x_return_status Standard Output Parameter
12244 -- x_msg_count Standard Output Parameter
12245 -- x_msg_data Standard Output Parameter
12246 -- x_found true if found ; else false
12247 -- x_rule_rec info of the rule if found
12248
12249 -- Version :
12250 -- Current version 1.0
12251 --
12252 -- Notes : calls API's of WMS_RE_Common_PVT
12253 --
12254 PROCEDURE find_rule(
12255 p_api_version IN NUMBER
12256 , p_init_msg_list IN VARCHAR2
12257 , x_return_status OUT NOCOPY VARCHAR2
12258 , x_msg_count OUT NOCOPY NUMBER
12259 , x_msg_data OUT NOCOPY VARCHAR2
12260 , p_rule_id IN NUMBER
12261 , x_found OUT NOCOPY BOOLEAN
12262 , x_rule_rec OUT NOCOPY rule_rec
12263 ) IS
12264 -- API standard variables
12265 l_api_version CONSTANT NUMBER := 1.0;
12266 l_api_name CONSTANT VARCHAR2(30) := 'Find_Rule';
12267
12268 --
12269 CURSOR l_cur IS
12270 SELECT rule_id
12271 , organization_id
12272 , type_code
12273 , NAME
12274 , description
12275 , qty_function_parameter_id
12276 , enabled_flag
12277 , user_defined_flag
12278 , attribute_category
12279 , attribute1
12280 , attribute2
12281 , attribute3
12282 , attribute4
12283 , attribute5
12284 , attribute6
12285 , attribute7
12286 , attribute8
12287 , attribute9
12288 , attribute10
12289 , attribute11
12290 , attribute12
12291 , attribute13
12292 , attribute14
12293 , attribute15
12294 FROM wms_rules_vl
12295 WHERE rule_id = p_rule_id;
12296
12297 --
12298 l_rule_rec rule_rec;
12299 BEGIN
12300 OPEN l_cur;
12301 FETCH l_cur INTO l_rule_rec;
12302
12303 --
12304 IF l_cur%NOTFOUND THEN
12305 x_found := FALSE;
12306 ELSE
12307 x_found := TRUE;
12308 x_rule_rec := l_rule_rec;
12309 END IF;
12310
12311 CLOSE l_cur;
12312 --
12313 EXCEPTION
12314 WHEN fnd_api.g_exc_error THEN
12315 x_return_status := fnd_api.g_ret_sts_error;
12316 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12317 --
12318 WHEN fnd_api.g_exc_unexpected_error THEN
12319 x_return_status := fnd_api.g_ret_sts_unexp_error;
12320 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12321 --
12322 WHEN OTHERS THEN
12323 x_return_status := fnd_api.g_ret_sts_unexp_error;
12324
12325 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12326 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
12327 END IF;
12328
12329 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
12330 --
12331 END find_rule;
12332
12333 --GetPackageName
12334 --
12335 --This function establishes the naming standard for the rule packages.
12336 --Currently, the naming standard is WMS_RULE_## , where ## is rule id
12337 PROCEDURE getpackagename(p_rule_id IN NUMBER, x_package_name OUT NOCOPY VARCHAR2) IS
12338 BEGIN
12339 x_package_name := 'WMS_RULE_' || p_rule_id;
12340 END getpackagename;
12341
12342 -- InitBuildPackage
12343 -- Called from GenerateRulePackage. Initializes
12344 -- the global variables needed to dynamically build the
12345 -- rule package.
12346 PROCEDURE initbuildpackage IS
12347 BEGIN
12348 g_build_package_row := 0;
12349 g_build_package_tbl.DELETE;
12350 END initbuildpackage;
12351
12352 --Build Package
12353 --This API takes a VARCHAR of undetermined length
12354 -- and breaks it up into varchars of length 255. These
12355 -- smaller strings are stored in the g_build_package_tbl,
12356 -- and compose the sql statement to create the
12357 -- Rules package.
12358 PROCEDURE buildpackage(p_package_string IN VARCHAR2) IS
12359 l_cur_start NUMBER;
12360 l_package_length NUMBER;
12361 l_num_chars NUMBER := 255;
12362 l_row NUMBER;
12363 BEGIN
12364 l_cur_start := 1;
12365 -- get last filled row of table
12366 l_row := g_build_package_row;
12367 l_package_length := LENGTH(p_package_string);
12368 inv_log_util.trace( l_package_length ,'l_package_length' , 9);
12369 inv_log_util.trace( p_package_string ,'p_package_string' , 9);
12370 -- return if string is null
12371 IF l_package_length IS NULL
12372 OR l_package_length = 0 THEN
12373 RETURN;
12374 END IF;
12375
12376 --Loop through string, reading off l_num_chars bytes at a time
12377 LOOP
12378 --When at end of varchar, exit loop;
12379 EXIT WHEN l_cur_start > l_package_length;
12380 l_row := l_row + 1;
12381 --Get substring from package_string
12382 g_build_package_tbl(l_row) := SUBSTR(p_package_string, l_cur_start, l_num_chars);
12383 --Call build package to add row
12384 -- We may need to call this API for AOL standards.
12385 --ad_ddl.build_package(l_cur_string, l_row);
12386
12387 --increment pointers
12388 l_cur_start := l_cur_start + l_num_chars;
12389
12390 IF l_cur_start + l_num_chars > l_package_length THEN
12391 l_num_chars := l_package_length - l_cur_start + 1;
12392 END IF;
12393 END LOOP;
12394
12395 g_build_package_row := l_row;
12396 END buildpackage;
12397
12398 --CreatePackage
12399 -- This API calls dynamic SQL to build the package
12400 -- currently sitting in the g_build_package_tbl.
12401 -- p_package_body = TRUE if the package to be created is a body
12402 PROCEDURE createpackage(x_return_status OUT NOCOPY VARCHAR2, p_package_name IN VARCHAR2, p_package_body IN BOOLEAN) IS
12403 l_schema VARCHAR2(30);
12404 l_status VARCHAR2(1);
12405 l_industry VARCHAR2(1);
12406 l_comp_error VARCHAR2(40);
12407 l_return BOOLEAN;
12408 l_cursor INTEGER;
12409 l_error VARCHAR2(10);
12410
12411 CURSOR c_package_status IS
12412 SELECT status
12413 FROM user_objects
12414 WHERE object_name = UPPER(p_package_name)
12415 AND object_type='PACKAGE'
12416 AND status <> 'VALID'
12417 AND rownum = 1;
12418
12419 CURSOR c_package_body_status IS
12420 SELECT status
12421 FROM user_objects
12422 WHERE object_name = UPPER(p_package_name)
12423 AND object_type = 'PACKAGE BODY'
12424 AND status <> 'VALID'
12425 AND rownum = 1;
12426
12427 BEGIN
12428 x_return_status := fnd_api.g_ret_sts_unexp_error;
12429 --open cursor
12430 l_cursor := DBMS_SQL.open_cursor;
12431 --parse cursor
12432 DBMS_SQL.parse(l_cursor, g_build_package_tbl, 1, g_build_package_row, FALSE, DBMS_SQL.native);
12433 --close cursor
12434 DBMS_SQL.close_cursor(l_cursor);
12435
12436 /* We may need to call this API for AOL standards
12437 --get schema info
12438 l_return := fnd_installation.get_app_info(
12439 application_short_name => 'FND'
12440 ,status => l_status
12441 ,industry => l_industry
12442 ,oracle_schema => l_schema
12443 );
12444 IF l_return = FALSE THEN
12445 RAISE fnd_api.g_exc_error;
12446 END IF;
12447
12448 --Call create package
12449 ad_ddl.create_plsql_object(
12450 applsys_schema => l_schema
12451 ,application_short_name => 'WMS'
12452 ,object_name => p_package_name
12453 ,lb => 1
12454 ,ub => g_build_package_row
12455 ,insert_newlines => 'FALSE'
12456 ,comp_error => l_comp_error
12457 );
12458
12459 IF l_comp_error = 'TRUE' THEN
12460 RAISE fnd_api.g_exc_error;
12461 END IF;
12462 */
12463 --Check status, return error if package that was created
12464 -- is invalid
12465 IF p_package_body THEN
12466 OPEN c_package_body_status;
12467 FETCH c_package_body_status INTO l_error;
12468
12469 IF c_package_body_status%FOUND THEN
12470 x_return_status := fnd_api.g_ret_sts_unexp_error;
12471 ELSE
12472 x_return_status := fnd_api.g_ret_sts_success;
12473 END IF;
12474
12475 CLOSE c_package_body_status;
12476 ELSE
12477 OPEN c_package_status;
12478 FETCH c_package_status INTO l_error;
12479
12480 IF c_package_status%FOUND THEN
12481 x_return_status := fnd_api.g_ret_sts_unexp_error;
12482 ELSE
12483 x_return_status := fnd_api.g_ret_sts_success;
12484 END IF;
12485
12486 CLOSE c_package_status;
12487 END IF;
12488 EXCEPTION
12489 WHEN OTHERS THEN
12490 x_return_status := fnd_api.g_ret_sts_unexp_error;
12491 END createpackage;
12492
12493 -- API name : GenerateRulePackage
12494 -- Type : Private
12495 -- Function : generate a package for a rule that can be used in
12496 -- picking and put away
12497 -- Input Parameters :
12498 -- p_api_version Standard Input Parameter
12499 -- p_init_msg_list Standard Input Parameter
12500 -- p_validation_level Standard Input Parameter
12501 -- p_rule_id Identifier of the rule
12502 --
12503 -- Output Parameters:
12504 -- x_return_status Standard Output Parameter
12505 -- x_msg_count Standard Output Parameter
12506 -- x_msg_data Standard Output Parameter
12507 --
12508 -- Called by the WMS Rules form (WMSRULEF.fmb), this function
12509 -- creates a package for the given rule. The package has three
12510 -- functions, open_curs, fetch_one_row, and close_curs. Open_curs
12511 -- opens the cursor used by picking/put away to find locations for
12512 -- transactions. Fetch_one_row returns the next set of results from
12513 -- the cursor. Close_curs closes the cursor. Much of this function is
12514 -- devoted to building the necessary cursors. For picking, there are
12515 -- three cursors - one for detailing serials, one for serial controlled
12516 -- items when not detailing, and one for non-serial items.
12517 -- For put away, task type, label, and cost group rules,
12518 -- there is only one cursor
12519
12520
12521
12522 PROCEDURE generaterulepackage(
12523 p_api_version IN NUMBER
12524 , p_init_msg_list IN VARCHAR2
12525 , p_validation_level IN NUMBER
12526 , x_return_status OUT NOCOPY VARCHAR2
12527 , x_msg_count OUT NOCOPY NUMBER
12528 , x_msg_data OUT NOCOPY VARCHAR2
12529 , p_rule_id IN NUMBER
12530 ) IS
12531 -- API standard variables
12532 l_api_version CONSTANT NUMBER := 1.0;
12533 l_api_name CONSTANT VARCHAR2(30) := 'GenerateRulePackage';
12534 --
12535 -- variables needed for dynamic SQL
12536 l_cursor INTEGER;
12537 l_rows INTEGER;
12538 --
12539 -- rule dynamic SQL output variables
12540 l_revision wms_transactions_temp.revision%TYPE;
12541 l_lot_number wms_transactions_temp.lot_number%TYPE;
12542 l_lot_expiration_date wms_transactions_temp.lot_expiration_date%TYPE;
12543 l_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
12544 l_locator_id wms_transactions_temp.from_locator_id%TYPE;
12545 l_cost_group_id wms_transactions_temp.from_cost_group_id%TYPE;
12546 l_possible_quantity wms_transactions_temp.primary_quantity%TYPE;
12547 --
12548 -- other variables
12549 l_type_code wms_rules_b.type_code%TYPE;
12550 l_package_name VARCHAR2(128);
12551 l_pack_sql VARCHAR2(32000);
12552 l_pack_body_sql VARCHAR2(32000);
12553 --
12554 l_subinventory_where VARCHAR2(100);
12555 l_locator_where VARCHAR2(100);
12556 l_stmt LONG;
12557 l_allocation_mode_id NUMBER;
12558
12559 l_rest_sql VARCHAR2(32000);
12560 -- cursor for validation of input parameters and pre-requisites
12561 CURSOR rule IS
12562 SELECT type_code
12563 , allocation_mode_id
12564 FROM wms_rules_b mpr
12565 WHERE mpr.rule_id = p_rule_id;
12566 --
12567 BEGIN
12568 --
12569 -- Standard call to check for call compatibility
12570 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
12571 RAISE fnd_api.g_exc_unexpected_error;
12572 END IF;
12573
12574 --
12575 -- Initialize message list if p_init_msg_list is set to TRUE
12576 IF fnd_api.to_boolean(p_init_msg_list) THEN
12577 fnd_msg_pub.initialize;
12578 END IF;
12579
12580 --
12581 -- Initialize API return status to success
12582 x_return_status := fnd_api.g_ret_sts_success;
12583
12584 log_procedure(l_api_name, 'start', 'Start GenerateRulePackage');
12585
12586 -- end of debugging section
12587 --
12588 -- Validate input parameter, if validation level requires this
12589 IF p_validation_level <> fnd_api.g_valid_level_none THEN
12590 IF p_rule_id IS NULL
12591 OR p_rule_id = fnd_api.g_miss_num THEN
12592 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
12593 fnd_message.set_name('WMS', 'WMS_RULE_ID_MISSING');
12594 log_error_msg(l_api_name, 'rule_id_missing');
12595 fnd_msg_pub.ADD;
12596 END IF;
12597
12598 RAISE fnd_api.g_exc_error;
12599 END IF;
12600 END IF;
12601
12602 --
12603 -- Get type code of the rule
12604 OPEN rule;
12605 FETCH rule INTO l_type_code, l_allocation_mode_id;
12606
12607 IF rule%NOTFOUND THEN
12608 CLOSE rule;
12609 RAISE NO_DATA_FOUND;
12610 END IF;
12611
12612 CLOSE rule;
12613 --
12614
12615 -- clean up the global variables holding dynamic SQL text
12616 freeglobals;
12617
12618 --
12619
12620 /* For Task type rule (TTA) and label rule, calculate initial rule weight*/
12621 -- We don't want to pre-calculate rule weight any more, because
12622 -- of the uniqueness check on rule weight
12623 /*
12624 IF l_type_code = 3 OR l_type_code = 4 THEN
12625 calcRuleWeight(p_rule_id);
12626 END IF;
12627 */
12628
12629
12630
12631 --For pick and put away rules, build the Base and Input portions
12632 -- of the SQL statement. Not used in task type, label, and cost group
12633 -- rules
12634 IF l_type_code = 1
12635 OR l_type_code = 2 THEN
12636 -- Build the base part of the SQL statement
12637 buildbasesql(x_return_status, x_msg_count, x_msg_data, l_type_code, l_allocation_mode_id);
12638
12639 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12640 RAISE fnd_api.g_exc_unexpected_error;
12641 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12642 RAISE fnd_api.g_exc_error;
12643 END IF;
12644
12645 -- Build the input parameter dependent part of the SQL statement
12646 buildinputsql(x_return_status, x_msg_count, x_msg_data, l_type_code);
12647
12648 --
12649 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12650 RAISE fnd_api.g_exc_unexpected_error;
12651 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12652 RAISE fnd_api.g_exc_error;
12653 END IF;
12654 END IF;
12655
12656 -- Build the rule dependent part of the SQL statement.
12657 -- Happens for rules of all type
12658 buildrulesql(x_return_status, x_msg_count, x_msg_data, p_rule_id, l_type_code, l_allocation_mode_id);
12659
12660 --
12661 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12662 RAISE fnd_api.g_exc_unexpected_error;
12663 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12664 RAISE fnd_api.g_exc_error;
12665 END IF;
12666
12667 --
12668
12669
12670 --inv_pp_debug.send_long_to_pipe(g_base_from_serial);
12671
12672 --build the sql portion of the cursor for lot-controlled items
12673 IF (l_type_code = 2) THEN --pick only
12674 g_stmt_serial := 'select '
12675 || g_base_select
12676 || g_rule_select_serial
12677 || ' from '
12678 || g_rule_from
12679 || g_base_from_serial
12680 || ' where '
12681 || g_input_where
12682 || g_rule_where
12683 || ' group by '
12684 || g_base_group_by
12685 || g_rule_group_by;
12686
12687 g_stmt_serial_validate := 'select '
12688 || g_base_select
12689 || g_rule_select_serial
12690 || ' from '
12691 || g_rule_from
12692 || g_base_from_serial_v
12693 || ' where '
12694 || g_input_where
12695 || g_rule_where
12696 || ' group by '
12697 || g_base_group_by
12698 || g_rule_group_by;
12699
12700 g_stmt_serial_detail := 'select '
12701 || g_base_select
12702 || g_rule_select
12703 || ' from '
12704 || g_rule_from
12705 || g_base_from_serial
12706 || ' where '
12707 || g_input_where
12708 || g_rule_where;
12709
12710 g_stmt_serial_detail_new := 'select '
12711 || g_base_select
12712 || g_rule_select
12713 || ' from '
12714 || g_rule_from
12715 || g_base_from_serial_detail
12716 || ' where '
12717 || g_input_where
12718 || g_rule_where;
12719
12720 IF g_rule_order IS NOT NULL THEN
12721 g_stmt_serial := g_stmt_serial || ' order by ' || g_rule_order;
12722 g_stmt_serial_validate := g_stmt_serial_validate || ' order by ' || g_rule_order;
12723 g_stmt_serial_detail := g_stmt_serial_detail || ' order by ' || g_rule_order;
12724 g_stmt_serial_detail_new := g_stmt_serial_detail_new || ' order by ' || g_rule_order;
12725 END IF;
12726 -- inv_pp_debug.send_long_to_pipe(g_stmt_serial);
12727 -- inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
12728
12729 ELSE
12730 --if not pick, we don't need these cursors, so we set them to
12731 -- dummy values. Used only so package will compile.
12732 g_stmt_serial := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12733 g_stmt_serial_validate := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12734 g_stmt_serial_detail := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12735 g_stmt_serial_detail_new := 'select 1,1,sysdate,1,1,1,1,1,1,1,1,1 from dual';
12736 END IF;
12737
12738 --get the package name
12739 getpackagename(p_rule_id, l_package_name);
12740 -- Initialize the global variables needed to build package
12741 initbuildpackage;
12742
12743 -- Generate Package for Label Rules
12744 IF (l_type_code = 4) THEN
12745 g_stmt := 'select count(*) '
12746 || ' from '
12747 || NVL(g_rule_from, 'WMS_LABEL_REQUESTS wlr')
12748 || ' where wlr.label_request_id = p_label_request_id '
12749 || g_rule_where;
12750 --assemble create package statement
12751 l_pack_sql :=
12752 'CREATE OR REPLACE PACKAGE '
12753 || l_package_name
12754 || ' AS
12755 procedure Get_label_format (
12756 p_label_request_id IN NUMBER,
12757 x_return_status OUT NOCOPY NUMBER);
12758
12759 end '
12760 || l_package_name
12761 || ';';
12762 --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12763 --open cursor
12764 --l_cursor := dbms_sql.open_cursor;
12765 --parse cursor
12766 --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12767 --close cursor
12768 --dbms_sql.close_cursor(l_cursor);
12769 buildpackage(l_pack_sql);
12770 --create the package spec
12771 createpackage(x_return_status, l_package_name, FALSE);
12772
12773 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12774 RAISE fnd_api.g_exc_unexpected_error;
12775 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12776 RAISE fnd_api.g_exc_error;
12777 END IF;
12778
12779 --re initialize global variables
12780 initbuildpackage;
12781 --inv_pp_debug.send_long_to_pipe(g_stmt);
12782
12783 --assemble the dynamic package creation statment
12784 l_pack_body_sql :=
12785 'CREATE OR REPLACE PACKAGE BODY '
12786 || l_package_name
12787 || ' AS
12788 PROCEDURE Get_Label_Format (
12789 p_label_request_id IN NUMBER,
12790 x_return_status OUT NOCOPY NUMBER) IS
12791
12792 CURSOR get_label_rule_curs IS
12793 ';
12794 buildpackage(l_pack_body_sql);
12795 buildpackage(g_stmt);
12796 l_pack_body_sql :=
12797 ';
12798
12799 BEGIN
12800 x_return_status := 0;
12801 OPEN get_label_rule_curs;
12802 FETCH get_label_rule_curs into x_return_status;
12803 CLOSE get_label_rule_curs;
12804
12805 END Get_Label_Format;
12806
12807 END '
12808 || l_package_name
12809 || ';';
12810 ELSIF (l_type_code = 7) THEN
12811 -- Generate package for Operation Plan Rules
12812 g_stmt := 'select count(*) '
12813 || ' from '
12814 || NVL(g_rule_from, 'MTL_MATERIAL_TRANSACTIONS_TEMP mmtt')
12815 || ' where mmtt.transaction_temp_id = p_pp_transaction_temp_id '
12816 || g_rule_where;
12817 --assemble create package statement
12818 l_pack_sql :=
12819 'CREATE OR REPLACE PACKAGE '
12820 || l_package_name
12821 || ' AS
12822 procedure Get_OP (
12823 p_pp_transaction_temp_id IN NUMBER,
12824 x_return_status OUT NOCOPY NUMBER);
12825
12826 end '
12827 || l_package_name
12828 || ';';
12829 --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12830 --open cursor
12831 --l_cursor := dbms_sql.open_cursor;
12832 --parse cursor
12833 --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12834 --close cursor
12835 --dbms_sql.close_cursor(l_cursor);
12836 buildpackage(l_pack_sql);
12837 createpackage(x_return_status, l_package_name, FALSE);
12838
12839 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12840 RAISE fnd_api.g_exc_unexpected_error;
12841 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12842 RAISE fnd_api.g_exc_error;
12843 END IF;
12844
12845 initbuildpackage;
12846 --inv_pp_debug.send_long_to_pipe(g_stmt);
12847
12848 --assemble the dynamic package creation statment
12849 l_pack_body_sql :=
12850 'CREATE OR REPLACE PACKAGE BODY '
12851 || l_package_name
12852 || ' AS
12853 PROCEDURE Get_OP (
12854 p_pp_transaction_temp_id IN NUMBER,
12855 x_return_status OUT NOCOPY NUMBER) IS
12856
12857 CURSOR g_operation_plan_curs IS
12858 ';
12859 buildpackage(l_pack_body_sql);
12860 buildpackage(g_stmt);
12861 l_pack_body_sql :=
12862 '; -- for OP
12863
12864 BEGIN
12865 x_return_status := 0;
12866 OPEN g_operation_plan_curs;
12867 FETCH g_operation_plan_curs INTO x_return_status;
12868 CLOSE g_operation_plan_curs;
12869 END Get_OP;
12870
12871 END '
12872 || l_package_name
12873 || ';';
12874 ELSIF (l_type_code = 3) THEN
12875 -- Generate package for Task Type Rules
12876 g_stmt := 'select count(*) '
12877 || ' from '
12878 || NVL(g_rule_from, 'MTL_MATERIAL_TRANSACTIONS_TEMP mmtt')
12879 || ' where nvl(mmtt.parent_line_id,mmtt.transaction_temp_id) = p_pp_transaction_temp_id ' -- Bug Fix 5560849
12880 || g_rule_where;
12881 --assemble create package statement
12882 l_pack_sql :=
12883 'CREATE OR REPLACE PACKAGE '
12884 || l_package_name
12885 || ' AS
12886 procedure Get_Task (
12887 p_pp_transaction_temp_id IN NUMBER,
12888 x_return_status OUT NOCOPY NUMBER);
12889
12890 end '
12891 || l_package_name
12892 || ';';
12893 --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12894 --open cursor
12895 --l_cursor := dbms_sql.open_cursor;
12896 --parse cursor
12897 --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12898 --close cursor
12899 --dbms_sql.close_cursor(l_cursor);
12900 buildpackage(l_pack_sql);
12901 createpackage(x_return_status, l_package_name, FALSE);
12902
12903 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12904 RAISE fnd_api.g_exc_unexpected_error;
12905 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12906 RAISE fnd_api.g_exc_error;
12907 END IF;
12908
12909 initbuildpackage;
12910 --inv_pp_debug.send_long_to_pipe(g_stmt);
12911
12912 --assemble the dynamic package creation statment
12913 l_pack_body_sql :=
12914 'CREATE OR REPLACE PACKAGE BODY '
12915 || l_package_name
12916 || ' AS
12917 PROCEDURE Get_Task (
12918 p_pp_transaction_temp_id IN NUMBER,
12919 x_return_status OUT NOCOPY NUMBER) IS
12920
12921 CURSOR g_task_type_curs IS
12922 ';
12923 buildpackage(l_pack_body_sql);
12924 buildpackage(g_stmt);
12925 l_pack_body_sql :=
12926 '; -- for TTA
12927
12928 BEGIN
12929 x_return_status := 0;
12930 OPEN g_task_type_curs;
12931 FETCH g_task_type_curs INTO x_return_status;
12932 CLOSE g_task_type_curs;
12933 END Get_Task;
12934
12935 END '
12936 || l_package_name
12937 || ';';
12938 -- Call CreatePackage after IF statement
12939
12940 ELSIF (l_type_code = 5) THEN
12941 -- Build package for Cost Group Rules
12942 g_stmt := 'select count(*) '
12943 || ' from '
12944 || NVL(g_rule_from, 'WMS_COST_GROUPS_INPUT_V wcgiv')
12945 || ' where wcgiv.line_id = g_line_id '
12946 || g_rule_where;
12947 --assemble create package statement
12948 l_pack_sql :=
12949 'CREATE OR REPLACE PACKAGE '
12950 || l_package_name
12951 || ' AS
12952
12953 PROCEDURE Get_CostGroup(
12954 p_line_id IN NUMBER,
12955 x_return_status OUT NOCOPY NUMBER);
12956
12957 end '
12958 || l_package_name
12959 || ';';
12960 --inv_pp_debug.send_long_to_pipe(l_pack_sql);
12961 --open cursor
12962 --l_cursor := dbms_sql.open_cursor;
12963 --parse cursor
12964 --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
12965 --close cursor
12966 --dbms_sql.close_cursor(l_cursor);
12967 buildpackage(l_pack_sql);
12968 createpackage(x_return_status, l_package_name, FALSE);
12969
12970 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
12971 RAISE fnd_api.g_exc_unexpected_error;
12972 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
12973 RAISE fnd_api.g_exc_error;
12974 END IF;
12975
12976 initbuildpackage;
12977 --inv_pp_debug.send_long_to_pipe(g_stmt);
12978
12979 --assemble the dynamic package creation statment
12980 l_pack_body_sql :=
12981 'CREATE OR REPLACE PACKAGE BODY '
12982 || l_package_name
12983 || ' AS
12984 PROCEDURE Get_CostGroup(
12985 p_line_id IN NUMBER,
12986 x_return_status OUT NOCOPY NUMBER) IS
12987
12988 g_line_id NUMBER;
12989
12990 CURSOR g_cursor_cost_group IS
12991 ';
12992 buildpackage(l_pack_body_sql);
12993 buildpackage(g_stmt);
12994 l_pack_body_sql :=
12995 ';
12996
12997 BEGIN
12998 g_line_id := p_line_id;
12999
13000 OPEN g_cursor_cost_group;
13001
13002 IF g_cursor_cost_group%isopen THEN
13003
13004 FETCH g_cursor_cost_group INTO
13005 x_return_status;
13006
13007 ELSE
13008 x_return_status := 0;
13009 END IF;
13010
13011 IF(g_cursor_cost_group%isopen) THEN
13012
13013 CLOSE g_cursor_cost_group;
13014
13015 END IF;
13016
13017 END Get_CostGroup;
13018 END '
13019 || l_package_name
13020 || ';';
13021 ELSIF l_type_code = 1 THEN
13022 -- Build for Put Away
13023 l_subinventory_where := g_base_table_alias || '.subinventory_code = g_subinventory_code' || g_line_feed;
13024 l_locator_where := g_base_table_alias || '.locator_id = g_locator_id' || g_line_feed;
13025 --build the sql portion of the cursor for non-serial-controlled items
13026 log_procedure(l_api_name, '=>', '********************* 200');
13027 g_stmt :=
13028 'select ' || g_base_select || ' from ' || g_rule_from || g_base_from || ' where ' || g_input_where || g_rule_where;
13029 --inv_pp_debug.send_long_to_pipe('g_base_from : ' || g_base_from);
13030
13031 log_procedure(l_api_name, '=>', '********************* 199');
13032
13033 --assemble create package statement
13034 l_pack_sql :=
13035 'CREATE OR REPLACE PACKAGE '
13036 || l_package_name
13037 || ' AS
13038 procedure open_curs (
13039 p_cursor IN OUT NOCOPY WMS_RULE_PVT.CV_PUT_TYPE,
13040 p_organization_id IN NUMBER,
13041 p_inventory_item_id IN NUMBER,
13042 p_transaction_type_id IN NUMBER,
13043 p_subinventory_code IN VARCHAR2,
13044 p_locator_id IN NUMBER,
13045 p_pp_transaction_temp_id IN NUMBER,
13046 p_restrict_subs_code IN NUMBER,
13047 p_restrict_locs_code IN NUMBER,
13048 p_project_id IN NUMBER,
13049 p_task_id IN NUMBER,
13050 x_result OUT NOCOPY NUMBER);
13051
13052 PROCEDURE fetch_one_row (
13053 p_cursor IN WMS_RULE_PVT.CV_PUT_TYPE,
13054 x_subinventory_code OUT NOCOPY VARCHAR2,
13055 x_locator_id OUT NOCOPY NUMBER,
13056 x_project_id OUT NOCOPY NUMBER,
13057 x_task_id OUT NOCOPY NUMBER,
13058 x_return_status OUT NOCOPY NUMBER);
13059
13060 PROCEDURE close_curs(p_cursor IN WMS_RULE_PVT.CV_PUT_TYPE );
13061
13062 end '
13063 || l_package_name
13064 || ';';
13065 log_procedure(l_api_name, '=>', '********************* 198');
13066 --inv_pp_debug.send_long_to_pipe(l_pack_sql);
13067 --open cursor
13068 --l_cursor := dbms_sql.open_cursor;
13069 --parse cursor
13070 --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
13071 --close cursor
13072 --dbms_sql.close_cursor(l_cursor);
13073 buildpackage(l_pack_sql);
13074 createpackage(x_return_status, l_package_name, FALSE);
13075
13076 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13077 RAISE fnd_api.g_exc_unexpected_error;
13078 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13079 RAISE fnd_api.g_exc_error;
13080 END IF;
13081
13082 initbuildpackage;
13083 -- inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
13084 -- inv_pp_debug.send_long_to_pipe(g_stmt_serial);
13085 --assemble the dynamic package creation statment
13086 log_procedure(l_api_name, '=>', '********************* 197');
13087 l_pack_body_sql :=
13088 'CREATE OR REPLACE PACKAGE BODY '
13089 || l_package_name
13090 || ' AS
13091
13092 PROCEDURE open_curs (
13093 p_cursor IN OUT NOCOPY WMS_RULE_PVT.cv_put_type,
13094 p_organization_id IN NUMBER,
13095 p_inventory_item_id IN NUMBER,
13096 p_transaction_type_id IN NUMBER,
13097 p_subinventory_code IN VARCHAR2,
13098 p_locator_id IN NUMBER,
13099 p_pp_transaction_temp_id IN NUMBER,
13100 p_restrict_subs_code IN NUMBER,
13101 p_restrict_locs_code IN NUMBER,
13102 p_project_id IN NUMBER,
13103 p_task_id IN NUMBER,
13104 x_result OUT NOCOPY NUMBER) IS
13105
13106 g_organization_id NUMBER;
13107 g_inventory_item_id NUMBER;
13108 g_transaction_type_id NUMBER;
13109 g_subinventory_code VARCHAR2(10);
13110 g_locator_id NUMBER;
13111 g_pp_transaction_temp_id NUMBER;
13112 g_restrict_subs_code NUMBER;
13113 g_restrict_locs_code NUMBER;
13114 g_project_id NUMBER;
13115 g_task_id NUMBER;
13116
13117 BEGIN
13118 g_organization_id :=p_organization_id;
13119 g_inventory_item_id := p_inventory_item_id;
13120 g_transaction_type_id := p_transaction_type_id;
13121 IF p_subinventory_code = ''-9999'' THEN
13122 g_subinventory_code := NULL;
13123 ELSE
13124 g_subinventory_code := p_subinventory_code;
13125 END IF;
13126 IF p_locator_id = -9999 THEN
13127 g_locator_id := NULL;
13128 ELSE
13129 g_locator_id := p_locator_id;
13130 END IF;
13131 g_pp_transaction_temp_id := p_pp_transaction_temp_id;
13132 g_restrict_subs_code := p_restrict_subs_code;
13133 g_restrict_locs_code := p_restrict_locs_code;
13134 g_project_id := p_project_id;
13135 g_task_id := p_task_id;
13136
13137 --if no restrictions
13138 IF g_restrict_subs_code = 2 AND
13139 g_restrict_locs_code = 2 THEN
13140
13141 If g_subinventory_code IS NULL Then
13142 --if nothing passed, OPEN c_no_restrict_no_passed;
13143
13144 OPEN p_cursor FOR ';
13145 buildpackage(l_pack_body_sql);
13146 --build correct statement
13147 log_procedure(l_api_name, '=>', '********************* 1961');
13148 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
13149 log_procedure(l_api_name, '=> Lenght ', length(l_stmt));
13150 l_rest_sql := l_stmt;
13151 log_procedure(l_api_name, '=> Lenght ', length(l_stmt));
13152 log_procedure(l_api_name, '=>_rest_sql', l_rest_sql);
13153 IF g_rule_order IS NOT NULL THEN
13154 l_stmt := l_stmt || ' order by ' || g_rule_order;
13155 END IF;
13156 log_procedure(l_api_name, '=>', '********************* 1963');
13157
13158 buildpackage(l_stmt);
13159 log_procedure(l_api_name, '=>', '********************* 1964');
13160 l_pack_body_sql :=
13161 ';
13162
13163 Elsif g_locator_id IS NULL Then
13164
13165 --if only subinventory passed , OPEN c_no_restrict_sub_passed;
13166
13167 OPEN p_cursor FOR ';
13168 buildpackage(l_pack_body_sql);
13169 --build correct statement
13170 log_procedure(l_api_name, '=>', '********************* 195');
13171 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
13172 l_stmt := l_stmt || ' and ' || l_subinventory_where;
13173 log_procedure(l_api_name, '=>', '********************* 194');
13174 IF g_rule_order IS NOT NULL THEN
13175 l_stmt := l_stmt || ' order by ' || g_rule_order;
13176 END IF;
13177
13178 buildpackage(l_stmt);
13179 l_pack_body_sql :=
13180 ';
13181
13182 Else
13183 --if subinventory and locator passed, OPEN c_no_restrict_loc_passed;
13184 OPEN p_cursor FOR ';
13185 buildpackage(l_pack_body_sql);
13186 --build correct statement
13187 log_procedure(l_api_name, '=>', '********************* 99');
13188 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_no_restrict);
13189 log_procedure(l_api_name, '=>', '********************* 98');
13190 l_stmt := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
13191 log_procedure(l_api_name, '=>', '********************* 97');
13192 IF g_rule_order IS NOT NULL THEN
13193 l_stmt := l_stmt || ' order by ' || g_rule_order;
13194 END IF;
13195
13196 buildpackage(l_stmt);
13197 l_pack_body_sql :=
13198 ';
13199 End If;
13200 ELSIF g_restrict_locs_code = 2 THEN
13201 If g_subinventory_code IS NULL Then
13202 --if nothing passed, OPEN c_sub_restrict_no_passed;
13203 OPEN p_cursor FOR ';
13204 buildpackage(l_pack_body_sql);
13205 --build correct statement
13206 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
13207
13208 IF g_rule_order IS NOT NULL THEN
13209 l_stmt := l_stmt || ' order by ' || g_rule_order;
13210 END IF;
13211
13212 buildpackage(l_stmt);
13213 l_pack_body_sql :=
13214 ';
13215 Elsif g_locator_id IS NULL Then
13216 --if only subinventory passed, OPEN c_sub_restrict_sub_passed;
13217 OPEN p_cursor FOR ';
13218 buildpackage(l_pack_body_sql);
13219 --build correct statement
13220 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
13221 l_stmt := l_stmt || ' and ' || l_subinventory_where;
13222
13223 IF g_rule_order IS NOT NULL THEN
13224 l_stmt := l_stmt || ' order by ' || g_rule_order;
13225 END IF;
13226
13227 buildpackage(l_stmt);
13228 l_pack_body_sql :=
13229 ';
13230
13231 Else
13232 --if subinventory and locator passed, OPEN c_sub_restrict_loc_passed;
13233 OPEN p_cursor FOR ';
13234 buildpackage(l_pack_body_sql);
13235 --build correct statement
13236 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_sub_restrict);
13237 l_stmt := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
13238
13239 IF g_rule_order IS NOT NULL THEN
13240 l_stmt := l_stmt || ' order by ' || g_rule_order;
13241 END IF;
13242
13243 buildpackage(l_stmt);
13244 l_pack_body_sql :=
13245 ';
13246 End If;
13247 ELSE
13248 If g_subinventory_code IS NULL Then
13249 --if nothing passed, OPEN c_loc_restrict_no_passed;
13250 OPEN p_cursor FOR ';
13251 buildpackage(l_pack_body_sql);
13252 --build correct statement
13253 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
13254
13255 IF g_rule_order IS NOT NULL THEN
13256 l_stmt := l_stmt || ' order by ' || g_rule_order;
13257 END IF;
13258
13259 buildpackage(l_stmt);
13260 l_pack_body_sql :=
13261 ';
13262
13263 Elsif g_locator_id IS NULL Then
13264 --if only subinventory passed,OPEN c_loc_restrict_sub_passed;
13265 OPEN p_cursor FOR ';
13266 buildpackage(l_pack_body_sql);
13267 --build correct statement
13268 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
13269 l_stmt := l_stmt || ' and ' || l_subinventory_where;
13270
13271 IF g_rule_order IS NOT NULL THEN
13272 l_stmt := l_stmt || ' order by ' || g_rule_order;
13273 END IF;
13274
13275 buildpackage(l_stmt);
13276 l_pack_body_sql :=
13277 ';
13278
13279 Else
13280 --if subinventory and locator passed, OPEN c_loc_restrict_loc_passed;
13281 OPEN p_cursor FOR ';
13282 buildpackage(l_pack_body_sql);
13283 --build correct statement
13284 l_stmt := REPLACE(g_stmt, ':g_put_base', g_put_base_loc_restrict);
13285 l_stmt := l_stmt || ' and ' || l_subinventory_where || ' and ' || l_locator_where;
13286
13287 IF g_rule_order IS NOT NULL THEN
13288 l_stmt := l_stmt || ' order by ' || g_rule_order;
13289 END IF;
13290
13291 buildpackage(l_stmt);
13292 l_pack_body_sql :=
13293 ';
13294 End If;
13295 END IF;
13296
13297 x_result :=1;
13298
13299 END open_curs;
13300
13301 PROCEDURE fetch_one_row(
13302 p_cursor IN WMS_RULE_PVT.cv_put_type,
13303 x_subinventory_code OUT NOCOPY VARCHAR2,
13304 x_locator_id OUT NOCOPY NUMBER,
13305 x_project_id OUT NOCOPY NUMBER,
13306 x_task_id OUT NOCOPY NUMBER,
13307 x_return_status OUT NOCOPY NUMBER) IS
13308
13309
13310 BEGIN
13311 if p_cursor%ISOPEN then
13312 FETCH p_cursor INTO
13313 x_subinventory_code, x_locator_id, x_project_id, x_task_id;
13314 IF p_cursor%FOUND THEN
13315 x_return_status := 1;
13316 ELSE
13317 x_return_status := 0;
13318 END IF;
13319 else
13320 x_return_status := 0;
13321 end if;
13322
13323 END fetch_one_row;
13324
13325 PROCEDURE close_curs( p_cursor IN WMS_RULE_PVT.cv_put_type) IS
13326 BEGIN
13327 if p_cursor%ISOPEN then
13328 CLOSE p_cursor;
13329 end if;
13330 END close_curs;
13331
13332 END '
13333 || l_package_name
13334 || ';';
13335 ELSE
13336 -- Build for Pick
13337 IF l_allocation_mode_id IN (1, 2) THEN
13338 --build the sql portion of the cursor for non-serial-controlled items
13339 g_stmt :=
13340 'select ' || g_base_select || g_rule_select || ' from ' || g_rule_from || g_base_from || ' where ' || g_input_where || g_rule_where;
13341 --Ensures that we only get one rec per rev/lot/sub/loc, grouping
13342 -- all recs together regardless of LPN
13343 -- l_allocation_mode_id IN (3,4)
13344 ELSE
13345 g_stmt := 'select '
13346 || g_base_select
13347 || g_rule_select_serial
13348 || ' from '
13349 || g_rule_from
13350 || g_base_from
13351 || ' where '
13352 || g_input_where
13353 || g_rule_where
13354 || 'group by '
13355 || g_base_group_by
13356 || g_rule_group_by;
13357 END IF;
13358
13359 --inv_pp_debug.send_long_to_pipe('g_base_from : ' || g_base_from);
13360
13361 IF g_rule_order IS NOT NULL THEN
13362 g_stmt := g_stmt || ' order by ' || g_rule_order;
13363 END IF;
13364
13365 --assemble create package statement
13366 l_pack_sql :=
13367 'CREATE OR REPLACE PACKAGE '
13368 || l_package_name
13369 || ' AS
13370 procedure open_curs (
13371 p_cursor IN OUT NOCOPY WMS_RULE_PVT.cv_pick_type,
13372 p_organization_id IN NUMBER,
13373 p_inventory_item_id IN NUMBER,
13374 p_transaction_type_id IN NUMBER,
13375 p_revision IN VARCHAR2,
13376 p_lot_number IN VARCHAR2,
13377 p_subinventory_code IN VARCHAR2,
13378 p_locator_id IN NUMBER,
13379 p_cost_group_id IN NUMBER,
13380 p_pp_transaction_temp_id IN NUMBER,
13381 p_serial_controlled IN NUMBER,
13382 p_detail_serial IN NUMBER,
13383 p_detail_any_serial IN NUMBER,
13384 p_from_serial_number IN VARCHAR2,
13385 p_to_serial_number IN VARCHAR2,
13386 p_unit_number IN VARCHAR2,
13387 p_lpn_id IN NUMBER,
13388 p_project_id IN NUMBER,
13389 p_task_id IN NUMBER,
13390 x_result OUT NOCOPY NUMBER);
13391
13392 PROCEDURE fetch_one_row (
13393 p_cursor IN WMS_RULE_PVT.cv_pick_type,
13394 x_revision OUT NOCOPY VARCHAR2,
13395 x_lot_number OUT NOCOPY VARCHAR2,
13396 x_lot_expiration_date OUT NOCOPY DATE,
13397 x_subinventory_code OUT NOCOPY VARCHAR2,
13398 x_locator_id OUT NOCOPY NUMBER,
13399 x_cost_group_id OUT NOCOPY NUMBER,
13400 x_uom_code OUT NOCOPY VARCHAR2,
13401 x_lpn_id OUT NOCOPY NUMBER,
13402 x_serial_number OUT NOCOPY VARCHAR2,
13403 x_possible_quantity OUT NOCOPY NUMBER,
13404 x_sec_possible_quantity OUT NOCOPY NUMBER,
13405 x_grade_code OUT NOCOPY VARCHAR2,
13406 x_consist_string OUT NOCOPY VARCHAR2,
13407 x_order_by_string OUT NOCOPY VARCHAR2,
13408 x_return_status OUT NOCOPY NUMBER);
13409
13410 PROCEDURE close_curs( p_cursor IN WMS_RULE_PVT.cv_pick_type);
13411
13412 PROCEDURE fetch_available_rows (
13413 p_cursor IN WMS_RULE_PVT.cv_pick_type,
13414 x_return_status OUT NOCOPY NUMBER);
13415
13416
13417
13418 end '
13419 || l_package_name
13420 || ';';
13421 --inv_pp_debug.send_long_to_pipe(l_pack_sql);
13422 --open cursor
13423 --l_cursor := dbms_sql.open_cursor;
13424 --parse cursor
13425 --dbms_sql.parse(l_cursor, l_pack_sql, dbms_sql.native);
13426 --close cursor
13427 --dbms_sql.close_cursor(l_cursor);
13428 buildpackage(l_pack_sql);
13429 createpackage(x_return_status, l_package_name, FALSE);
13430
13431 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13432 RAISE fnd_api.g_exc_unexpected_error;
13433 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13434 RAISE fnd_api.g_exc_error;
13435 END IF;
13436
13437 initbuildpackage;
13438 -- inv_pp_debug.send_long_to_pipe(g_stmt_serial_detail);
13439 -- inv_pp_debug.send_long_to_pipe(g_stmt_serial);
13440 --assemble the dynamic package creation statment
13441
13442 l_pack_body_sql :=
13443 'CREATE OR REPLACE PACKAGE BODY '
13444 || l_package_name
13445 || ' AS
13446
13447 PROCEDURE open_curs
13448 (
13449 p_cursor IN OUT NOCOPY WMS_RULE_PVT.cv_pick_type,
13450 p_organization_id IN NUMBER,
13451 p_inventory_item_id IN NUMBER,
13452 p_transaction_type_id IN NUMBER,
13453 p_revision IN VARCHAR2,
13454 p_lot_number IN VARCHAR2,
13455 p_subinventory_code IN VARCHAR2,
13456 p_locator_id IN NUMBER,
13457 p_cost_group_id IN NUMBER,
13458 p_pp_transaction_temp_id IN NUMBER,
13459 p_serial_controlled IN NUMBER,
13460 p_detail_serial IN NUMBER,
13461 p_detail_any_serial IN NUMBER,
13462 p_from_serial_number IN VARCHAR2,
13463 p_to_serial_number IN VARCHAR2,
13464 p_unit_number IN VARCHAR2,
13465 p_lpn_id IN NUMBER,
13466 p_project_id IN NUMBER,
13467 p_task_id IN NUMBER,
13468 x_result OUT NOCOPY NUMBER
13469 ) IS
13470 g_organization_id NUMBER;
13471 g_inventory_item_id NUMBER;
13472 g_transaction_type_id NUMBER;
13473 g_revision VARCHAR2(3);
13474 g_lot_number VARCHAR2(80);
13475 g_subinventory_code VARCHAR2(10);
13476 g_locator_id NUMBER;
13477 g_cost_group_id NUMBER;
13478 g_pp_transaction_temp_id NUMBER;
13479 g_serial_control NUMBER;
13480 g_detail_serial NUMBER;
13481 g_detail_any_serial NUMBER;
13482 g_from_serial_number VARCHAR2(30);
13483 g_to_serial_number VARCHAR2(30);
13484 g_unit_number VARCHAR2(30);
13485 g_lpn_id NUMBER;
13486 g_project_id NUMBER;
13487 g_task_id NUMBER;
13488
13489
13490 BEGIN
13491 g_organization_id :=p_organization_id;
13492 g_inventory_item_id := p_inventory_item_id;
13493 g_transaction_type_id := p_transaction_type_id;
13494 g_revision := p_revision;
13495 g_lot_number := p_lot_number;
13496 g_subinventory_code :=p_subinventory_code;
13497 g_locator_id := p_locator_id;
13498 g_cost_group_id := p_cost_group_id;
13499 g_pp_transaction_temp_id := p_pp_transaction_temp_id;
13500 g_serial_control:= p_serial_controlled;
13501 g_detail_serial := p_detail_serial;
13502 g_detail_any_serial := p_detail_any_serial;
13503 g_from_serial_number := p_from_serial_number;
13504 g_to_serial_number := p_to_serial_number;
13505 g_unit_number := p_unit_number;
13506 g_lpn_id := p_lpn_id;
13507 g_project_id := p_project_id;
13508 g_task_id := p_task_id;
13509
13510 IF (g_serial_control = 1) AND (g_detail_serial in (1,2)) THEN
13511 OPEN p_cursor FOR ';
13512 buildpackage(l_pack_body_sql);
13513 buildpackage(g_stmt_serial_detail_new);
13514 l_pack_body_sql := ';
13515 Elsif (g_serial_control = 1) AND (g_detail_serial = 3) THEN
13516 OPEN p_cursor FOR ';
13517 buildpackage(l_pack_body_sql);
13518 buildpackage(g_stmt_serial_validate);
13519 l_pack_body_sql := ';
13520 Elsif (g_serial_control = 1) AND (g_detail_serial = 4) THEN
13521 OPEN p_cursor FOR ';
13522 buildpackage(l_pack_body_sql);
13523 buildpackage(g_stmt_serial);
13524 l_pack_body_sql := ';
13525
13526 Elsif ((g_serial_control <> 1) OR (g_detail_serial = 0)) THEN
13527 OPEN p_cursor FOR ';
13528 buildpackage(l_pack_body_sql);
13529 buildpackage(g_stmt);
13530 l_pack_body_sql :=
13531 ';
13532 END IF;
13533
13534 x_result :=1;
13535
13536 END open_curs;
13537
13538 PROCEDURE fetch_one_row(
13539 p_cursor IN WMS_RULE_PVT.cv_pick_type,
13540 x_revision OUT NOCOPY VARCHAR2,
13541 x_lot_number OUT NOCOPY VARCHAR2,
13542 x_lot_expiration_date OUT NOCOPY DATE,
13543 x_subinventory_code OUT NOCOPY VARCHAR2,
13544 x_locator_id OUT NOCOPY NUMBER,
13545 x_cost_group_id OUT NOCOPY NUMBER,
13546 x_uom_code OUT NOCOPY VARCHAR2,
13547 x_lpn_id OUT NOCOPY NUMBER,
13548 x_serial_number OUT NOCOPY VARCHAR2,
13549 x_possible_quantity OUT NOCOPY NUMBER,
13550 x_sec_possible_quantity OUT NOCOPY NUMBER,
13551 x_grade_code OUT NOCOPY VARCHAR2,
13552 x_consist_string OUT NOCOPY VARCHAR2,
13553 x_order_by_string OUT NOCOPY VARCHAR2,
13554 x_return_status OUT NOCOPY NUMBER) IS
13555
13556
13557 BEGIN
13558 IF (p_cursor%ISOPEN) THEN
13559
13560 FETCH p_cursor INTO
13561 x_revision
13562 , x_lot_number
13563 , x_lot_expiration_date
13564 , x_subinventory_code
13565 , x_locator_id
13566 , x_cost_group_id
13567 , x_uom_code
13568 , x_lpn_id
13569 , x_serial_number
13570 , x_possible_quantity
13571 , x_sec_possible_quantity
13572 , x_grade_code
13573 , x_consist_string
13574 , x_order_by_string;
13575 IF p_cursor%FOUND THEN
13576 x_return_status :=1;
13577 ELSE
13578 x_return_status :=0;
13579 END IF;
13580 ELSE
13581 x_return_status:=0;
13582 END IF;
13583
13584
13585 END fetch_one_row;
13586
13587 PROCEDURE close_curs( p_cursor IN WMS_RULE_PVT.cv_pick_type) IS
13588 BEGIN
13589 if (p_cursor%ISOPEN) THEN
13590 CLOSE p_cursor;
13591 END IF;
13592 END close_curs;
13593
13594 -- LG convergence new procedure for the new manual picking select screen
13595 PROCEDURE fetch_available_rows(
13596 p_cursor IN WMS_RULE_PVT.cv_pick_type,
13597 x_return_status OUT NOCOPY NUMBER) IS
13598
13599
13600 BEGIN
13601 IF (p_cursor%ISOPEN) THEN
13602
13603 FETCH p_cursor bulk collect INTO
13604 WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl;
13605 IF p_cursor%FOUND THEN
13606 x_return_status :=1;
13607 ELSE
13608 x_return_status :=0;
13609 END IF;
13610 ELSE
13611 x_return_status:=0;
13612 END IF;
13613
13614
13615 END fetch_available_rows;
13616
13617 -- end LG convergence
13618
13619 END '
13620 || l_package_name
13621 || ';';
13622 END IF; -- type_code = 4
13623
13624 -- Add last part of SQL to the global table, then call
13625 -- CreatePackage to generate package body
13626 buildpackage(l_pack_body_sql);
13627 createpackage(x_return_status, l_package_name, TRUE);
13628
13629 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
13630 RAISE fnd_api.g_exc_unexpected_error;
13631 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
13632 RAISE fnd_api.g_exc_error;
13633 END IF;
13634
13635 initbuildpackage;
13636 -- inv_pp_debug.send_long_to_pipe(l_pack_body_sql);
13637 /*
13638 --open cursor
13639
13640 l_cursor := dbms_sql.open_cursor;
13641 dbms_out
13642 --parse cursor
13643
13644 dbms_sql.parse(l_cursor, l_pack_body_sql, dbms_sql.native);
13645
13646 --close cursor
13647 dbms_sql.close_cursor(l_cursor);
13648 */
13649
13650
13651
13652 --
13653 -- clean up everything again
13654 freeglobals;
13655
13656 --
13657
13658 /*
13659 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_success) THEN
13660 fnd_message.set_name('WMS','WMS_SYNTAX_CHECK_SUCCESS');
13661 fnd_msg_pub.add;
13662 END IF;
13663 */ --
13664 -- end of debugging section
13665 log_procedure(l_api_name, 'end', 'End GenerateRulePackage');
13666 --
13667 EXCEPTION
13668 WHEN fnd_api.g_exc_error THEN
13669 --
13670 -- debugging portion
13671 -- can be commented ut for final code
13672 IF inv_pp_debug.is_debug_mode THEN
13673 -- Note: in debug mode, later call to fnd_msg_pub.get will not get
13674 -- the message retrieved here since it is no longer on the stack
13675 inv_pp_debug.set_last_error_message(SQLERRM);
13676 inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
13677 inv_pp_debug.send_last_error_message;
13678 END IF;
13679
13680 -- end of debugging section
13681 --
13682 IF DBMS_SQL.is_open(l_cursor) THEN
13683 DBMS_SQL.close_cursor(l_cursor);
13684 END IF;
13685
13686 freeglobals;
13687 x_return_status := fnd_api.g_ret_sts_error;
13688 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13689 log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
13690 --
13691 WHEN fnd_api.g_exc_unexpected_error THEN
13692 --
13693 -- debugging portion
13694 -- can be commented ut for final code
13695 IF inv_pp_debug.is_debug_mode THEN
13696 -- Note: in debug mode, later call to fnd_msg_pub.get will not get
13697 -- the message retrieved here since it is no longer on the stack
13698 inv_pp_debug.set_last_error_message(SQLERRM);
13699 inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
13700 inv_pp_debug.send_last_error_message;
13701 END IF;
13702
13703 -- end of debugging section
13704 --
13705 IF DBMS_SQL.is_open(l_cursor) THEN
13706 DBMS_SQL.close_cursor(l_cursor);
13707 END IF;
13708
13709 freeglobals;
13710 fnd_message.set_name('WMS', 'WMS_PACKAGE_GEN_FAILED');
13711 fnd_msg_pub.ADD;
13712 x_return_status := fnd_api.g_ret_sts_unexp_error;
13713 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13714 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
13715 --
13716 WHEN OTHERS THEN
13717 --
13718 -- debugging portion
13719 -- can be commented ut for final code
13720 IF inv_pp_debug.is_debug_mode THEN
13721 -- Note: in debug mode, later call to fnd_msg_pub.get will not get
13722 -- the message retrieved here since it is no longer on the stack
13723 inv_pp_debug.set_last_error_message(SQLERRM);
13724 inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
13725 inv_pp_debug.send_last_error_message;
13726 END IF;
13727
13728 -- end of debugging section
13729 --
13730 IF rule%ISOPEN THEN
13731 CLOSE rule;
13732 END IF;
13733
13734 IF DBMS_SQL.is_open(l_cursor) THEN
13735 DBMS_SQL.close_cursor(l_cursor);
13736 END IF;
13737
13738 freeglobals;
13739 fnd_message.set_name('WMS', 'WMS_PACKAGE_GEN_FAILED');
13740 fnd_msg_pub.ADD;
13741 x_return_status := fnd_api.g_ret_sts_unexp_error;
13742
13743 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
13744 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
13745 END IF;
13746
13747 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
13748 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
13749 --
13750 END generaterulepackage;
13751
13752 -- API name : Assign_operation_plans
13753 -- Type : Private
13754 -- Function : Assign operation plans to records in MMTT
13755 -- Input Parameters :
13756 --
13757 -- Output Parameters:
13758 -- Version :
13759 -- Current version 1.0
13760 --
13761 -- Notes : calls Assign_operation_plan(p_task_id NUMBER)
13762 --
13763 -- This procedure loops through mtl_material_transactions_temp table, assign
13764 -- user defined operation plans to tasks that have not been assigned a operation_plan
13765 -- for the given Move Order Header.
13766 --
13767
13768
13769 PROCEDURE assign_operation_plans(
13770 p_api_version IN NUMBER
13771 , p_init_msg_list IN VARCHAR2
13772 , p_commit IN VARCHAR2
13773 , p_validation_level IN NUMBER
13774 , x_return_status OUT NOCOPY VARCHAR2
13775 , x_msg_count OUT NOCOPY NUMBER
13776 , x_msg_data OUT NOCOPY VARCHAR2
13777 , p_move_order_header_id IN NUMBER
13778 ) IS
13779 CURSOR c_tasks IS
13780 SELECT mmtt.transaction_temp_id
13781 FROM mtl_material_transactions_temp mmtt, mtl_txn_request_lines mol
13782 WHERE mmtt.operation_plan_id IS NULL
13783 AND mmtt.move_order_line_id = mol.line_id
13784 AND mol.header_id = p_move_order_header_id;
13785
13786 l_task_id NUMBER;
13787 l_return_status VARCHAR2(1);
13788 l_msg_count NUMBER;
13789 l_msg_data VARCHAR2(2000);
13790 l_api_name VARCHAR2(30) := 'assign_operation_plans';
13791 l_count NUMBER;
13792 BEGIN
13793 -- Initialize API return status to success
13794 x_return_status := fnd_api.g_ret_sts_success;
13795
13796 -- Bug# 4587423
13797 -- See if there are any enabled rules for Operation Plan Selection.
13798 l_count := 0;
13799 BEGIN
13800 SELECT 1 INTO l_count
13801 FROM dual
13802 WHERE EXISTS (SELECT 1 FROM wms_rules_b rules
13803 WHERE rules.type_code = 7
13804 AND rules.enabled_flag = 'Y'
13805 AND (organization_id = -1
13806 OR organization_id IN (SELECT mmtt.organization_id
13807 FROM mtl_material_transactions_temp mmtt,
13808 mtl_txn_request_lines mol
13809 WHERE mmtt.standard_operation_id IS NULL
13810 AND mmtt.move_order_line_id = mol.line_id
13811 AND mol.header_id = p_move_order_header_id)));
13812 EXCEPTION
13813 WHEN OTHERS THEN
13814 l_count := 0;
13815 END;
13816
13817 -- Bug# 4587423
13818 -- If there is at least one operation plan selection rule enabled,
13819 -- go through the existing logic.
13820 IF (l_count > 0) THEN
13821 OPEN c_tasks;
13822 LOOP
13823 FETCH c_tasks INTO l_task_id;
13824 EXIT WHEN c_tasks%NOTFOUND;
13825
13826 if (inv_control.g_current_release_level >= inv_release.g_j_release_level
13827 and wms_ui_tasks_apis.g_wms_patch_level >= wms_ui_tasks_apis.g_patchset_j)
13828 then
13829 -- ### Outbound for patchset 'J'
13830 wms_rule_pvt_ext_psetj.assign_operation_plan_psetj
13831 (p_api_version => 1.0,
13832 x_return_status => l_return_status,
13833 x_msg_count => l_msg_count,
13834 x_msg_data => l_msg_data,
13835 p_task_id => l_task_id
13836 );
13837 elsif (inv_control.g_current_release_level < inv_release.g_j_release_level
13838 or wms_ui_tasks_apis.g_wms_patch_level < wms_ui_tasks_apis.g_patchset_j)
13839 then
13840 -- ### Outbound for patchset 'I'
13841 assign_operation_plan
13842 (p_api_version => 1.0,
13843 p_task_id => l_task_id,
13844 x_return_status => l_return_status,
13845 x_msg_count => l_msg_count,
13846 x_msg_data => l_msg_data
13847 );
13848 end if;
13849
13850 IF l_return_status <> fnd_api.g_ret_sts_success THEN
13851 x_return_status := fnd_api.g_ret_sts_error;
13852 END IF;
13853 END LOOP;
13854
13855 CLOSE c_tasks;
13856 ELSE
13857 -- Bug# 4587423
13858 -- No rules exist for outbound operaton plan selection.
13859 -- Just stamp the org default outbound operation plan or the default
13860 -- "Locator and LPN Based Consolidation in Staging Lane" seeded outbound operation plan
13861 -- for the MMTT records associated with the move order header.
13862 UPDATE mtl_material_transactions_temp mmtt
13863 SET mmtt.operation_plan_id = (SELECT NVL(default_pick_op_plan_id, 1)
13864 FROM mtl_parameters mp
13865 WHERE mp.organization_id = mmtt.organization_id)
13866 WHERE mmtt.operation_plan_id IS NULL
13867 AND mmtt.move_order_line_id IN (SELECT line_id
13868 FROM mtl_txn_request_lines mol
13869 WHERE mol.header_id = p_move_order_header_id)
13870 AND mmtt.transaction_source_type_id in (2, 8);
13871 END IF;
13872
13873 EXCEPTION
13874 WHEN OTHERS THEN
13875 x_return_status := fnd_api.g_ret_sts_unexp_error;
13876 END assign_operation_plans;
13877
13878 --
13879 -- API name : Assign Operation Plan
13880 -- Type : Private
13881 -- Function : Assign Operation plan to a specific record in MMTT
13882 -- Input Parameters :
13883 -- p_task_id NUMBER
13884 --
13885 -- Output Parameters:
13886 -- Version :
13887 -- Current version 1.0
13888 --
13889 -- Notes :
13890 --
13891 -- This procedure assign user defined operation plan to a specific task in
13892 -- mtl_material_transactions_temp. Operation plan is implemeted by WMS rules.
13893 -- This procedure calls the rule package created for operation plan rules to check
13894 -- which operation plan rule actually matches the task in question.
13895
13896
13897 PROCEDURE assign_operation_plan(
13898 p_api_version IN NUMBER
13899 , p_init_msg_list IN VARCHAR2
13900 , p_commit IN VARCHAR2
13901 , p_validation_level IN NUMBER
13902 , x_return_status OUT NOCOPY VARCHAR2
13903 , x_msg_count OUT NOCOPY NUMBER
13904 , x_msg_data OUT NOCOPY VARCHAR2
13905 , p_task_id IN NUMBER
13906 ) IS
13907 l_rule_id NUMBER;
13908 l_pack_exists NUMBER;
13909 l_package_name VARCHAR2(30);
13910 l_count NUMBER;
13911 l_return_status NUMBER;
13912 l_found BOOLEAN := FALSE;
13913 l_organization_id NUMBER;
13914 l_wms_task_type NUMBER;
13915 l_operation_plan_id NUMBER;
13916 l_api_version CONSTANT NUMBER := 1.0;
13917 l_api_name CONSTANT VARCHAR2(30) := 'Assign_operation_plan';
13918
13919 -- Cursor for task type rule loop
13920 -- Only rules with the same WMS system task type as the task
13921 -- will be selected
13922 -- Rules are ordered by rule weight and creation date
13923
13924 CURSOR c_rules IS
13925 SELECT rules.rule_id
13926 , mmtt.organization_id
13927 , mmtt.wms_task_type
13928 , rules.type_hdr_id
13929 FROM wms_rules_b rules, wms_op_plans_b wop, mtl_material_transactions_temp mmtt
13930 WHERE rules.type_code = 7
13931 AND rules.enabled_flag = 'Y'
13932 AND rules.type_hdr_id = wop.operation_plan_id
13933 AND wop.system_task_type = NVL(mmtt.wms_task_type, wop.system_task_type)
13934 --AND mmtt.transaction_source_type_id <> 5 -- exclude wip issue tasks
13935 AND mmtt.transaction_source_type_id IN (2, 8) --restrict to sales order and internal order mmtts only
13936 AND mmtt.transaction_temp_id = p_task_id
13937 AND rules.organization_id IN (mmtt.organization_id, -1)
13938 AND NVL(wop.organization_id, mmtt.organization_id) = mmtt.organization_id
13939 AND wop.enabled_flag = 'Y'
13940 ORDER BY rules.rule_weight DESC, rules.creation_date;
13941
13942 --cursor used to determine if the rule package exists
13943 CURSOR l_pack_gen IS
13944 SELECT COUNT(object_name)
13945 FROM user_objects
13946 WHERE object_name = l_package_name;
13947
13948 -- Bug# 4587423: If a default outbound operation plan is not defined for the org,
13949 -- default to 1 (Locator and LPN Based Consolidation in Staging Lane)
13950 CURSOR c_default_operation_plan IS
13951 SELECT NVL(default_pick_op_plan_id, 1)
13952 FROM mtl_parameters
13953 WHERE organization_id = l_organization_id;
13954
13955 l_rule_counter INTEGER;
13956 BEGIN
13957 SAVEPOINT assign_operation_plan_sp;
13958
13959 -- Standard call to check for call compatibility
13960 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
13961 RAISE fnd_api.g_exc_unexpected_error;
13962 END IF;
13963
13964 -- Initialize message list if p_init_msg_list is set to TRUE
13965 IF fnd_api.to_boolean(p_init_msg_list) THEN
13966 fnd_msg_pub.initialize;
13967 END IF;
13968
13969 --
13970 -- Initialize API return status to success
13971 x_return_status := fnd_api.g_ret_sts_success;
13972
13973 -- Validate input parameters and pre-requisites, if validation level
13974 -- requires this
13975 IF p_validation_level <> fnd_api.g_valid_level_none THEN
13976 -- in case further needs for validation
13977 NULL;
13978 END IF;
13979
13980 OPEN c_rules; -- open the eligible rules cursor
13981
13982 LOOP -- loop through the rules
13983 FETCH c_rules INTO l_rule_id, l_organization_id, l_wms_task_type, l_operation_plan_id;
13984 EXIT WHEN c_rules%NOTFOUND;
13985
13986 BEGIN
13987 -- get the pre-generated package name for this rule
13988 getpackagename(l_rule_id, l_package_name);
13989
13990 --- Execute op Rule
13991 For l_rule_counter IN 1..2 LOOP
13992 execute_op_rule(l_rule_id, p_task_id, l_return_status);
13993 IF (l_return_status = -1) and l_rule_counter = 2 THEN --error
13994 fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
13995 fnd_message.set_token('RULEID', l_rule_id);
13996 fnd_msg_pub.ADD;
13997 log_error_msg(l_api_name, 'rule_package_missing');
13998 log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
13999 RAISE fnd_api.g_exc_unexpected_error;
14000 ELSIF l_return_status <> -1 THEN
14001 EXIT;
14002 END IF;
14003 END LOOP;
14004
14005 IF l_return_status > 0 THEN -- the rule matches the task
14006 l_found := TRUE;
14007
14008 -- update mmtt table to assign the operation plan
14009
14010
14011 UPDATE mtl_material_transactions_temp mmtt
14012 SET mmtt.operation_plan_id = l_operation_plan_id
14013 WHERE mmtt.transaction_temp_id = p_task_id;
14014
14015 EXIT; -- operation plan assigned, jump out of the rule loop
14016 END IF; -- l_return_status > 0
14017 EXCEPTION -- handle exceptions for matching one rule
14018 WHEN fnd_api.g_exc_error THEN
14019 NULL;
14020 WHEN OTHERS THEN
14021 NULL;
14022 END; -- end matching one rule
14023 END LOOP;
14024
14025 CLOSE c_rules; --close the rule cursor
14026
14027 -- get default operation plan
14028 IF NOT l_found THEN
14029
14030 begin
14031 select organization_id
14032 into l_organization_id
14033 from mtl_material_transactions_temp
14034 where transaction_temp_id = p_task_id
14035 AND transaction_source_type_id IN (2, 8); -- bug fix 3361560
14036 exception
14037 when others then
14038 null;
14039 end;
14040
14041 IF NVL(g_current_organization_id, -1) <> l_organization_id THEN
14042 g_current_organization_id := l_organization_id;
14043 OPEN c_default_operation_plan;
14044 FETCH c_default_operation_plan INTO g_default_operation_plan_id;
14045
14046 IF c_default_operation_plan%NOTFOUND THEN
14047 l_operation_plan_id := NULL;
14048 END IF;
14049
14050 CLOSE c_default_operation_plan;
14051 END IF;
14052
14053 l_operation_plan_id := g_default_operation_plan_id;
14054
14055 UPDATE mtl_material_transactions_temp mmtt
14056 SET mmtt.operation_plan_id = l_operation_plan_id
14057 WHERE mmtt.transaction_temp_id = p_task_id;
14058 END IF;
14059
14060 -- Standard check of p_commit
14061 IF fnd_api.to_boolean(p_commit) THEN
14062 COMMIT WORK;
14063 END IF;
14064 EXCEPTION
14065 WHEN fnd_api.g_exc_error THEN
14066 -- if the rule package not created yet, close the rule cursor
14067 IF c_rules%ISOPEN THEN
14068 CLOSE c_rules;
14069 END IF;
14070
14071 ROLLBACK TO assign_operation_plan_sp;
14072 freeglobals;
14073 x_return_status := fnd_api.g_ret_sts_error;
14074
14075 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14076 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14077 END IF;
14078
14079 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14080 WHEN OTHERS THEN
14081 ROLLBACK TO assign_operation_plan_sp;
14082 freeglobals;
14083 x_return_status := fnd_api.g_ret_sts_unexp_error;
14084
14085 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14086 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14087 END IF;
14088
14089 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14090 END assign_operation_plan;
14091
14092 --**************************************
14093
14094 --
14095 -- API name : AssignTT
14096 -- Type : Private
14097 -- Function : Assign task type to records in MMTT
14098 -- Input Parameters :
14099 --
14100 -- Output Parameters:
14101 -- Version :
14102 -- Current version 1.0
14103 --
14104 -- Notes : calls AssignTTs(p_task_id NUMBER)
14105 --
14106 -- This procedure loops through mtl_material_transactions_temp table, assign
14107 -- user defined task type to tasks that have not been assigned a task type
14108 -- for the given Move Order Header.
14109 --
14110
14111
14112 PROCEDURE assigntts(
14113 p_api_version IN NUMBER
14114 , p_init_msg_list IN VARCHAR2
14115 , p_commit IN VARCHAR2
14116 , p_validation_level IN NUMBER
14117 , x_return_status OUT NOCOPY VARCHAR2
14118 , x_msg_count OUT NOCOPY NUMBER
14119 , x_msg_data OUT NOCOPY VARCHAR2
14120 , p_move_order_header_id IN NUMBER
14121 ) IS
14122 CURSOR c_tasks IS
14123 SELECT mmtt.transaction_temp_id
14124 ,mmtt.organization_id -- Added new
14125 ,mmtt.wms_task_type -- Added new
14126 FROM mtl_material_transactions_temp mmtt, mtl_txn_request_lines mol
14127 WHERE mmtt.standard_operation_id IS NULL
14128 AND mmtt.move_order_line_id = mol.line_id
14129 AND mol.header_id = p_move_order_header_id;
14130
14131 l_task_id NUMBER;
14132 l_organization_id NUMBER; -- Added new
14133 l_wms_task_type NUMBER; -- Added new
14134 l_return_status VARCHAR2(1);
14135 l_msg_count NUMBER;
14136 l_msg_data VARCHAR2(2000);
14137 l_api_name VARCHAR2(30) := 'assignTTs';
14138 l_count NUMBER;
14139 BEGIN
14140 -- Initialize API return status to success
14141 x_return_status := fnd_api.g_ret_sts_success;
14142
14143 -- Bug# 4587423
14144 -- See if there are any enabled rules for Task Type Assignment for
14145 -- all orgs or for the orgs in the set of MMTT records for the given move order header.
14146 l_count := 0;
14147 BEGIN
14148 SELECT 1 INTO l_count
14149 FROM dual
14150 WHERE EXISTS (SELECT 1 FROM wms_rules_b rules
14151 WHERE rules.type_code = 3
14152 AND rules.enabled_flag = 'Y'
14153 AND (organization_id = -1
14154 OR organization_id IN (SELECT mmtt.organization_id
14155 FROM mtl_material_transactions_temp mmtt,
14156 mtl_txn_request_lines mol
14157 WHERE mmtt.standard_operation_id IS NULL
14158 AND mmtt.move_order_line_id = mol.line_id
14159 AND mol.header_id = p_move_order_header_id)));
14160 EXCEPTION
14161 WHEN OTHERS THEN
14162 l_count := 0;
14163 END;
14164
14165 -- Bug# 4587423
14166 -- If there is at least one task type assignment rule enabled,
14167 -- go through the existing logic.
14168 IF (l_count > 0) THEN
14169 OPEN c_tasks;
14170 LOOP
14171 FETCH c_tasks INTO l_task_id
14172 ,l_organization_id -- new
14173 ,l_wms_task_type; -- new
14174 EXIT WHEN c_tasks%NOTFOUND;
14175 assigntt
14176 (p_api_version => 1.0,
14177 p_task_id => l_task_id,
14178 x_return_status => l_return_status,
14179 x_msg_count => l_msg_count,
14180 x_msg_data => l_msg_data
14181 );
14182
14183 IF l_return_status <> fnd_api.g_ret_sts_success THEN
14184 x_return_status := fnd_api.g_ret_sts_error;
14185 END IF;
14186 END LOOP;
14187
14188 CLOSE c_tasks;
14189 ELSE
14190 -- Bug# 4587423
14191 -- No valid rules exist for task type assignment so just stamp the org level
14192 -- default task type for the given WMS task type on the MMTT record.
14193 UPDATE mtl_material_transactions_temp mmtt
14194 SET standard_operation_id =
14195 (SELECT DECODE(mmtt.wms_task_type, 1, default_pick_task_type_id,
14196 2, default_putaway_task_type_id,
14197 3, default_cc_task_type_id,
14198 4, default_repl_task_type_id,
14199 5, default_moxfer_task_type_id,
14200 6, default_moissue_task_type_id,
14201 NULL)
14202 FROM mtl_parameters mp WHERE mp.organization_id = mmtt.organization_id)
14203 WHERE mmtt.standard_operation_id IS NULL
14204 AND mmtt.move_order_line_id IN (SELECT line_id
14205 FROM mtl_txn_request_lines mol
14206 WHERE mol.header_id = p_move_order_header_id);
14207 END IF;
14208
14209 EXCEPTION
14210 WHEN OTHERS THEN
14211 x_return_status := fnd_api.g_ret_sts_unexp_error;
14212 END assigntts;
14213
14214 --
14215 -- API name : AssignTT
14216 -- Type : Private
14217 -- Function : Assign task type to a specific record in MMTT
14218 -- Input Parameters :
14219 -- p_task_id NUMBER
14220 --
14221 -- Output Parameters:
14222 -- Version :
14223 -- Current version 1.0
14224 --
14225 -- Notes :
14226 --
14227 -- This procedure assign user defined task types to a specific task in
14228 -- mtl_material_transactions_temp. Task type is implemeted by WMS rules.
14229 -- This procedure calls the rule package created for task type rules to check
14230 -- which task type rule actually matches the task in question.
14231 --
14232
14233 PROCEDURE assigntt(
14234 p_api_version IN NUMBER
14235 , p_init_msg_list IN VARCHAR2
14236 , p_commit IN VARCHAR2
14237 , p_validation_level IN NUMBER
14238 , x_return_status OUT NOCOPY VARCHAR2
14239 , x_msg_count OUT NOCOPY NUMBER
14240 , x_msg_data OUT NOCOPY VARCHAR2
14241 , p_task_id IN NUMBER
14242 ) IS
14243 l_rule_id NUMBER;
14244 l_pack_exists NUMBER;
14245 l_package_name VARCHAR2(30);
14246 l_rule_func_sql LONG;
14247 l_rule_result NUMBER;
14248 l_cursor INTEGER;
14249 l_dummy NUMBER;
14250 l_count NUMBER;
14251 l_return_status NUMBER;
14252 l_revision_dummy VARCHAR2(10);
14253 l_lot_number_dummy VARCHAR2(80);
14254 l_lot_expiration_date_dummy DATE;
14255 l_subinventory_code_dummy VARCHAR2(10);
14256 l_locator_id_dummy NUMBER;
14257 l_possible_qty_dummy NUMBER;
14258 l_uom_code_dummy VARCHAR2(3);
14259 l_order_by_string_dummy VARCHAR2(1000);
14260 l_found BOOLEAN := FALSE;
14261 l_organization_id NUMBER;
14262 l_wms_task_type NUMBER;
14263 l_task_type_id NUMBER;
14264 l_type_hdr_id NUMBER;
14265
14266 l_api_version CONSTANT NUMBER := 1.0;
14267 l_api_name CONSTANT VARCHAR2(30) := 'AssignTT';
14268
14269 l_debug NUMBER;
14270
14271
14272 -- Cursor for task type rule loop
14273 -- Only rules with the same WMS system task type as the task
14274 -- will be selected
14275 -- Rules are ordered by rule weight and creation date
14276
14277 CURSOR c_rules IS
14278 SELECT rules.rule_id
14279 , rules.type_hdr_id /* Added this Column */
14280 , mmtt.organization_id
14281 , mmtt.wms_task_type
14282 FROM wms_rules_b rules, bom_standard_operations bso , mtl_material_transactions_temp mmtt
14283 WHERE rules.type_code = 3
14284 AND rules.enabled_flag = 'Y'
14285 AND rules.type_hdr_id = bso.standard_operation_id
14286 AND bso.wms_task_type = NVL(mmtt.wms_task_type, bso.wms_task_type)
14287 AND mmtt.transaction_temp_id = p_task_id
14288 AND rules.organization_id IN (mmtt.organization_id, -1)
14289 AND bso.organization_id = mmtt.organization_id
14290 ORDER BY rules.rule_weight DESC, rules.creation_date;
14291
14292 /*CURSOR c_rules_new IS
14293 SELECT rules.rule_id , rules.type_hdr_id
14294 FROM wms_rules_b rules, bom_standard_operations bso
14295 WHERE rules.type_code = 3
14296 AND rules.enabled_flag = 'Y'
14297 AND rules.type_hdr_id = bso.standard_operation_id
14298 AND bso.wms_task_type = NVL(p_wms_task_type, bso.wms_task_type)
14299 AND rules.organization_id IN (p_organization_id, -1)
14300 AND bso.organization_id = p_organization_id
14301 ORDER BY rules.rule_weight DESC, rules.creation_date; */
14302
14303
14304 --cursor used to determine if the rule package exists
14305 CURSOR l_pack_gen IS
14306 SELECT COUNT(object_name)
14307 FROM user_objects
14308 WHERE object_name = l_package_name;
14309
14310 -- Following Code is commented because now we need to get 2 more default task_type..MOISSUE and MOXFER
14311 /*CURSOR c_default_task_type IS
14312 SELECT default_pick_task_type_id
14313 ,default_cc_task_type_id
14314 ,default_putaway_task_type_id
14315 ,default_repl_task_type_id
14316 FROM mtl_parameters
14317 WHERE organization_id = l_organization_id;
14318 */
14319
14320 CURSOR c_default_task_type IS
14321 SELECT default_pick_task_type_id
14322 , default_cc_task_type_id
14323 , default_putaway_task_type_id
14324 , default_repl_task_type_id
14325 , default_moxfer_task_type_id
14326 , default_moissue_task_type_id
14327 , default_pick_op_plan_id
14328 FROM mtl_parameters
14329 WHERE organization_id = l_organization_id;
14330
14331 l_rule_counter INTEGER;
14332 BEGIN
14333 SAVEPOINT assignttsp;
14334
14335 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
14336 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
14337 END IF;
14338 l_debug := g_debug;
14339
14340 -- Standard call to check for call compatibility
14341 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
14342 RAISE fnd_api.g_exc_unexpected_error;
14343 END IF;
14344
14345 -- Initialize message list if p_init_msg_list is set to TRUE
14346 IF fnd_api.to_boolean(p_init_msg_list) THEN
14347 fnd_msg_pub.initialize;
14348 END IF;
14349
14350 --
14351 -- Initialize API return status to success
14352 x_return_status := fnd_api.g_ret_sts_success;
14353
14354 -- Validate input parameters and pre-requisites, if validation level
14355 -- requires this
14356 IF p_validation_level <> fnd_api.g_valid_level_none THEN
14357 -- in case further needs for validation
14358 NULL;
14359 END IF;
14360
14361 OPEN c_rules; -- open the eligible rules cursor
14362
14363 LOOP -- loop through the rules
14364 FETCH c_rules INTO l_rule_id, l_type_hdr_id, l_organization_id, l_wms_task_type;
14365 EXIT WHEN c_rules%NOTFOUND;
14366
14367 --inv_log_util.TRACE('found the rule', 'RULE_ENGINE', 4);
14368
14369 BEGIN
14370 -- get the pre-generated package name for this rule
14371 getpackagename(l_rule_id, l_package_name);
14372
14373 --- Execute Task Rule
14374
14375 -- execute_task_rule(l_rule_id, p_task_id, l_return_status);
14376 For l_rule_counter IN 1..2 LOOP
14377 IF l_debug = 1 THEN
14378 log_error(l_api_name, 'Assigntt', 'Inside Loop :l_rule_counter ' || l_rule_counter);
14379 log_error(l_api_name, 'Assigntt', 'Calling execute_Task :l_rul e_id ' || l_rule_id);
14380 log_error(l_api_name, 'Assigntt', 'Calling execute_Task :p_Tas k_id ' || p_task_id);
14381 END IF;
14382 execute_task_rule(l_rule_id, p_task_id, l_return_status);
14383 IF (l_return_status = -1) and l_rule_counter = 2 THEN --error
14384 fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
14385 fnd_message.set_token('RULEID', l_rule_id);
14386 fnd_msg_pub.ADD;
14387 IF l_debug = 1 THEN
14388 log_error_msg(l_api_name, 'rule_package_missing');
14389 log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
14390 END IF;
14391 RAISE fnd_api.g_exc_unexpected_error;
14392 ELSIF l_return_status <> -1 THEN
14393 EXIT;
14394 END IF;
14395 END LOOP;
14396 If l_debug = 1 THEN
14397 log_error(l_api_name, 'Assigntt', 'After Execute_Task :l_return_s tatus ' || l_return_status);
14398 END IF;
14399
14400 IF l_return_status > 0 THEN -- the rule matches the task
14401 l_found := TRUE;
14402
14403 -- update mmtt table to assign the task type
14404
14405 UPDATE mtl_material_transactions_temp mmtt
14406 SET mmtt.standard_operation_id = l_type_hdr_id
14407 WHERE mmtt.transaction_temp_id = p_task_id;
14408 /*
14409 UPDATE mtl_material_transactions_temp mmtt
14410 SET mmtt.standard_operation_id = (SELECT type_hdr_id
14411 FROM wms_rules_b
14412 WHERE rule_id = l_rule_id)
14413 WHERE mmtt.transaction_temp_id = p_task_id
14414 */
14415
14416 EXIT; -- task assigned, jump out of the rule loop
14417 END IF; -- l_return_status > 0
14418 EXCEPTION -- handle exceptions for matching one rule
14419 WHEN fnd_api.g_exc_error THEN
14420 NULL;
14421 WHEN OTHERS THEN
14422 NULL;
14423 END; -- end matching one rule
14424 END LOOP;
14425
14426 CLOSE c_rules; --close the rule cursor
14427
14428 -- get default task type
14429 IF NOT l_found THEN
14430 -- bug 2737846
14431 begin
14432 select organization_id, wms_task_type
14433 into l_organization_id, l_wms_task_type
14434 from mtl_material_transactions_temp
14435 where transaction_temp_id = p_task_id;
14436 exception
14437 when others then
14438 null;
14439 end;
14440
14441 --inv_log_util.TRACE('NOT found the rule: g_current_organization_id'||g_current_organization_id, 'RULE_ENGINE', 4);
14442 --inv_log_util.TRACE('NOT found the rule: l_organization_id:'||l_organization_id, 'RULE_ENGINE', 4);
14443 IF NVL(g_current_organization_id, -1) <> l_organization_id THEN
14444 g_current_organization_id := l_organization_id;
14445
14446
14447 OPEN c_default_task_type;
14448 /*FETCH c_default_task_type INTO g_default_pick_task_type_id
14449 ,g_default_cc_task_type_id
14450 ,g_default_putaway_task_type_id
14451 ,g_default_repl_task_type_id;
14452 */
14453 FETCH c_default_task_type INTO g_default_pick_task_type_id
14454 , g_default_cc_task_type_id
14455 , g_default_putaway_task_type_id
14456 , g_default_repl_task_type_id
14457 , g_default_moxfer_task_type_id
14458 , g_default_moissue_task_type_id
14459 , g_default_operation_plan_id;
14460
14461 IF c_default_task_type%NOTFOUND THEN
14462 g_current_organization_id := NULL;
14463 g_default_pick_task_type_id := NULL;
14464 g_default_cc_task_type_id := NULL;
14465 g_default_putaway_task_type_id := NULL;
14466 g_default_repl_task_type_id := NULL;
14467 g_default_moxfer_task_type_id := NULL;
14468 g_default_moissue_task_type_id := NULL;
14469 g_default_operation_plan_id := NULL;
14470 --inv_log_util.TRACE('default_task_type not found', 'RULE_ENGINE', 4);
14471 END IF;
14472
14473 CLOSE c_default_task_type;
14474 END IF;
14475
14476 --inv_log_util.TRACE('inside cursor c_defualt_task_type', 'RULE_ENGINE', 4);
14477
14478
14479 IF l_wms_task_type = 1 THEN
14480 l_task_type_id := g_default_pick_task_type_id;
14481 ELSIF l_wms_task_type = 2 THEN
14482 l_task_type_id := g_default_putaway_task_type_id;
14483 ELSIF l_wms_task_type = 3 THEN
14484 l_task_type_id := g_default_cc_task_type_id; --g_default_repl_task_type_id; --Bug# 3110550
14485 ELSIF l_wms_task_type = 4 THEN
14486 l_task_type_id := g_default_repl_task_type_id; --g_default_cc_task_type_id; --Bug# 3110550
14487 ELSIF l_wms_task_type = 5 THEN
14488 l_task_type_id := g_default_moxfer_task_type_id;
14489 ELSIF l_wms_task_type = 6 THEN
14490 l_task_type_id := g_default_moissue_task_type_id;
14491 ELSE
14492 l_task_type_id := NULL;
14493 END IF;
14494
14495 --inv_log_util.TRACE('wms_task_type = 1, task_type_id=:' || l_task_type_id, 'RULE_ENGINE', 4);
14496 --inv_log_util.TRACE('before update statement', 'RULE_ENGINE', 4);
14497
14498 UPDATE mtl_material_transactions_temp mmtt
14499 SET mmtt.standard_operation_id = l_task_type_id
14500 WHERE mmtt.transaction_temp_id = p_task_id;
14501
14502 --inv_log_util.TRACE('after update statement: standard_operation_id:'||jxlu_soi, 'RULE_ENGINE', 4);
14503 END IF;
14504
14505 -- Standard check of p_commit
14506 IF fnd_api.to_boolean(p_commit) THEN
14507 COMMIT WORK;
14508 END IF;
14509 EXCEPTION
14510 WHEN fnd_api.g_exc_error THEN
14511 -- if the rule package not created yet, close the rule cursor
14512 IF c_rules%ISOPEN THEN
14513 CLOSE c_rules;
14514 END IF;
14515
14516 ROLLBACK TO assignttsp;
14517 freeglobals;
14518 x_return_status := fnd_api.g_ret_sts_error;
14519
14520 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14521 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14522 END IF;
14523
14524 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14525 WHEN OTHERS THEN
14526 ROLLBACK TO assignttsp;
14527 freeglobals;
14528 x_return_status := fnd_api.g_ret_sts_unexp_error;
14529
14530 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14531 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
14532 END IF;
14533
14534 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14535 END assigntt;
14536
14537 --
14538 -- API name : CalcRuleWeight
14539 -- Type : Private
14540 -- Function : Calculate initial rule weight based on number of distinct restriction
14541 -- parameters. This is currently the requirement for task type assignment
14542 --
14543 -- Input Parameters :
14544 -- p_task_id NUMBER
14545 --
14546 -- Output Parameters:
14547 -- Version :
14548 -- Current version 1.0
14549 --
14550 -- Notes :
14551 --
14552 -- This procedure will be called by Define Rule form through generate rule package call
14553
14554 PROCEDURE calcruleweight(p_rule_id NUMBER) IS
14555 BEGIN
14556
14557 UPDATE wms_rules_b
14558 SET rule_weight = (SELECT 100 * COUNT(parameter_id)
14559 FROM (SELECT DISTINCT rules.rule_id
14560 , par.parameter_id
14561 FROM wms_rules_b rules, wms_restrictions rest, wms_parameters_b par
14562 WHERE rules.rule_id = p_rule_id
14563 AND rules.rule_id = rest.rule_id(+)
14564 AND rest.parameter_id = par.parameter_id(+)
14565 AND (NVL(par.use_for_tt_assn_flag, 'Y') = 'Y'
14566 OR NVL(par.use_for_label_rest_flag, 'Y') = 'Y'
14567 )))
14568 WHERE rule_id = p_rule_id
14569 AND rule_weight IS NULL;
14570
14571
14572 EXCEPTION
14573 WHEN OTHERS THEN
14574 NULL;
14575 END calcruleweight;
14576
14577 --===========================================================================================
14578 --
14579 -- API name : ApplyLabel
14580 -- Type : Private
14581 -- Function : Retrieve Label based on Label request
14582 -- Input Parameters :
14583 -- p_label_request_id NUMBER
14584 -- p_document_id NUMBER
14585 --
14586 -- Output Parameters: x_label_format_id
14587 -- Version :
14588 -- Current version 1.0
14589 --
14590 -- Notes :
14591 --
14592 -- This procedure retrieves a specific label for a label request in
14593 -- wms_label_requests.
14594 -- This procedure calls the rule package created for Label rules to check
14595 -- which label rule actually matches the label request in question.
14596 --===========================================================================
14597 PROCEDURE applylabel(
14598 p_api_version IN NUMBER
14599 , p_init_msg_list IN VARCHAR2
14600 , p_commit IN VARCHAR2
14601 , p_validation_level IN NUMBER
14602 , p_label_request_id IN NUMBER
14603 , x_return_status OUT NOCOPY VARCHAR2
14604 , x_msg_count OUT NOCOPY NUMBER
14605 , x_msg_data OUT NOCOPY VARCHAR2
14606 , x_label_format_id OUT NOCOPY NUMBER
14607 , x_label_format_name OUT NOCOPY VARCHAR2
14608 ) IS
14609 l_rule_id NUMBER;
14610 l_rule_weight NUMBER;
14611 l_pack_exists NUMBER;
14612 l_package_name VARCHAR2(30);
14613 l_rule_func_sql LONG;
14614 l_rule_result NUMBER;
14615 l_cursor INTEGER;
14616 l_dummy NUMBER;
14617 l_count NUMBER;
14618 l_return_status NUMBER;
14619 l_label_format_id NUMBER;
14620 l_document_id NUMBER;
14621 l_label_format_name wms_label_formats.label_format_name%TYPE;
14622 l_api_version CONSTANT NUMBER := 1.0;
14623 l_api_name CONSTANT VARCHAR2(30) := 'ApplyLabel';
14624 l_msg_data VARCHAR2(2000);
14625 l_strategy_id NUMBER := NULL;
14626
14627
14628 -- Cursor for label rule loop
14629 -- Only rules with the type_code = 4
14630 -- will be selected
14631 -- Rules are ordered by rule weight and creation date
14632
14633 CURSOR c_rules IS
14634 SELECT rules.rule_id
14635 , rules.rule_weight
14636 , rules.type_hdr_id
14637 , wl.label_format_name
14638 , wl.document_id
14639 FROM wms_rules_b rules, wms_label_formats wl, wms_label_requests wlr
14640 WHERE rules.type_code = 4
14641 AND rules.type_hdr_id = wl.label_format_id
14642 AND wl.label_format_id = NVL(wlr.label_format_id, wl.label_format_id)
14643 AND NVL(format_disable_date, SYSDATE + 1) > SYSDATE --Bug #3452076
14644 AND wlr.document_id = wl.document_id
14645 AND wlr.label_request_id = p_label_request_id
14646 AND rules.enabled_flag = 'Y'
14647 AND (rules.organization_id = wlr.organization_id
14648 OR rules.organization_id = -1
14649 ) -- Common to All Org.
14650 ORDER BY rules.rule_weight DESC, rules.creation_date;
14651
14652 --cursor used to determine if the rule package exists
14653 CURSOR l_pack_gen IS
14654 SELECT COUNT(object_name)
14655 FROM user_objects
14656 WHERE object_name = l_package_name;
14657
14658 CURSOR l_default_label_curs IS
14659 SELECT label_format_id
14660 , label_format_name
14661 FROM wms_label_formats
14662 WHERE document_id = l_document_id
14663 AND default_format_flag IN ('Y', 'y');
14664
14665 CURSOR l_label_requests_curs IS
14666 SELECT *
14667 FROM wms_label_requests
14668 WHERE label_request_id = p_label_request_id;
14669
14670 l_label_req_rc wms_label_requests%ROWTYPE;
14671 l_rule_counter INTEGER;
14672 l_debug NUMBER;
14673 ll_ctr NUMBER;
14674 BEGIN
14675 SAVEPOINT assignlabelsp;
14676 ----
14677 SELECT count(rules.rule_id ) into ll_ctr
14678 FROM wms_rules_b rules, wms_label_formats wl, wms_label_requests wlr
14679 WHERE rules.type_code = 4
14680 AND rules.type_hdr_id = wl.label_format_id
14681 AND wl.label_format_id = NVL(wlr.label_format_id, wl.label_format_id)
14682 AND NVL(format_disable_date, SYSDATE + 1) > SYSDATE --Bug # 3452076
14683 AND wlr.document_id = wl.document_id
14684 AND wlr.label_request_id = p_label_request_id
14685 AND rules.enabled_flag = 'Y'
14686 AND (rules.organization_id = wlr.organization_id
14687 OR rules.organization_id = -1
14688 ) ;
14689 ----
14690 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
14691 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
14692 END IF;
14693 l_debug := g_debug;
14694 IF l_debug = 1 THEN
14695 TRACE('Executing ApplyLabel()...Label_request_ID : '|| p_label_request_id);
14696 TRACE('Number of rules to process(LL_CTR) :' || ll_ctr);
14697 END IF;
14698
14699 -- Standard call to check for call compatibility
14700 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
14701 RAISE fnd_api.g_exc_unexpected_error;
14702 END IF;
14703
14704 -- Initialize message list if p_init_msg_list is set to TRUE
14705 IF fnd_api.to_boolean(p_init_msg_list) THEN
14706 fnd_msg_pub.initialize;
14707 END IF;
14708
14709 --
14710 -- Initialize API return status to success
14711 x_return_status := fnd_api.g_ret_sts_success;
14712
14713 -- Validate input parameters and pre-requisites, if validation level
14714 -- requires this
14715 IF p_validation_level <> fnd_api.g_valid_level_none THEN
14716 -- in case further needs for validation
14717 NULL;
14718 END IF;
14719
14720 -- Retrieve document_id based on P_label_request_id
14721
14722 OPEN l_label_requests_curs;
14723 FETCH l_label_requests_curs INTO l_label_req_rc;
14724
14725 --dummy should = 2, one for package, one for package body
14726 IF (l_label_requests_curs%NOTFOUND) THEN
14727 CLOSE l_label_requests_curs;
14728 IF l_debug = 1 THEN
14729 TRACE('Invalid Label Request Id : '|| p_label_request_id);
14730 END IF;
14731 fnd_message.set_name('WMS', 'INVALID_LABEL_REQ');
14732 fnd_msg_pub.ADD;
14733 RAISE fnd_api.g_exc_error;
14734 END IF;
14735
14736 CLOSE l_label_requests_curs;
14737
14738 l_document_id := l_label_req_rc.document_id;
14739 IF l_debug = 1 THEN
14740 TRACE('Label request document Id : '|| l_document_id);
14741 END IF;
14742 l_return_status := 0; -- Initialize to 0
14743 OPEN c_rules; -- open the eligible rules cursor
14744
14745 LOOP -- loop through the rules
14746 FETCH c_rules INTO l_rule_id, l_rule_weight, l_label_format_id, l_label_format_name, l_label_req_rc.document_id;
14747 EXIT WHEN c_rules%NOTFOUND;
14748 -- get the pre-generated package name for this rule
14749 getpackagename(l_rule_id, l_package_name);
14750
14751 FOR l_rule_counter IN 1..2 LOOP
14752 IF l_debug = 1 THEN
14753 log_error(l_api_name, 'AssignLabel', 'Inside Loop :l_rule_counter ' || l_rule_counter);
14754 log_error(l_api_name, 'AssignLabel', 'Calling execute_label :l_rule_id ' || l_rule_id);
14755 log_error(l_api_name, 'AssignLabel', 'p_label_request_id ' || p_label_request_id);
14756 END IF;
14757 execute_label_rule(l_rule_id, p_label_request_id, l_return_status);
14758 IF l_debug = 1 THEN
14759 log_statement(l_api_name, 'Inside Loop', 'l_return_status' || l_return_status);
14760 END IF;
14761 log_statement(l_api_name, 'pack_name', 'Package name: ' || l_package_name);
14762 IF (l_return_status = -1) and l_rule_counter = 2 THEN --error
14763 fnd_message.set_name('WMS', 'WMS_PACKAGE_MISSING');
14764 fnd_message.set_token('RULEID', l_rule_id);
14765 fnd_msg_pub.ADD;
14766 IF l_debug = 1 THEN
14767 log_error_msg(l_api_name, 'rule_package_missing');
14768 log_error(l_api_name, 'Rule missing in the list pkg', 'l_rule_id ' || l_rule_id);
14769 END IF;
14770 RAISE fnd_api.g_exc_unexpected_error;
14771 ELSIF l_return_status <> -1 THEN
14772 EXIT;
14773 END IF;
14774 END LOOP;
14775
14776 IF l_return_status > 0 THEN -- the rule matches the label request
14777 -- update wms_label_requests table with label_format_id
14778
14779
14780 UPDATE wms_label_requests wlr
14781 SET wlr.label_format_id = l_label_format_id
14782 , wlr.rule_id = l_rule_id
14783 , wlr.strategy_id = l_strategy_id
14784 , wlr.rule_weight = l_rule_weight
14785 WHERE wlr.label_request_id = p_label_request_id;
14786 IF l_debug = 1 THEN
14787 TRACE('Rule Match.Update Label Request with format ID :'|| l_label_format_id || ' ' || l_label_format_name);
14788 END IF;
14789
14790 EXIT; -- label retrieved, jump out of the rule loop
14791 ELSIF (l_return_status = 0) THEN
14792 IF l_debug = 1 THEN
14793 trace('no rows found from procedure execute_label_rule()');
14794 END IF;
14795 END IF;
14796 END LOOP;
14797
14798 CLOSE c_rules; --close the rule cursor
14799
14800 -- ===================================================================
14801 -- Retrieve default label if there is no rule match the label request
14802 -- ===================================================================
14803 IF l_debug = 1 THEN
14804 trace('l_return_status : '|| l_return_status);
14805 END IF;
14806
14807 IF (l_return_status = 0) THEN
14808 IF l_debug = 1 THEN
14809 TRACE('No rule match retrieve the default format ');
14810 END IF;
14811 --Bug: 2646648 Patchset I label cleanup
14812 --Reset l_label_format_id(name) to null
14813 -- before retrieving default format
14814 -- so that if no default format, it will have value null
14815 -- instead of the value from cursor c_rules
14816 l_label_format_id := NULL;
14817 l_label_format_name := NULL;
14818 OPEN l_default_label_curs;
14819 FETCH l_default_label_curs INTO l_label_format_id, l_label_format_name;
14820 CLOSE l_default_label_curs;
14821 END IF;
14822
14823 -- update wms_label_requests table with label_format_id
14824
14825
14826 UPDATE wms_label_requests wlr
14827 SET wlr.label_format_id = l_label_format_id
14828 WHERE wlr.label_request_id = p_label_request_id;
14829
14830 IF l_debug = 1 THEN
14831 TRACE('Update Label Request with label ID :'|| l_label_format_id || '.(' || SQL%ROWCOUNT || ')');
14832 END IF;
14833
14834 --
14835 -- Assign x_label_format_id with l_label_format_id
14836 --
14837 x_label_format_id := l_label_format_id;
14838 x_label_format_name := l_label_format_name;
14839
14840 -- Standard check of p_commit
14841 IF fnd_api.to_boolean(p_commit) THEN
14842 COMMIT WORK;
14843 END IF;
14844 EXCEPTION
14845 WHEN fnd_api.g_exc_error THEN
14846 -- if the rule package not created yet, close the rule cursor
14847 IF c_rules%ISOPEN THEN
14848 CLOSE c_rules;
14849 END IF;
14850
14851 ROLLBACK TO assignlabelsp;
14852 freeglobals;
14853 x_return_status := fnd_api.g_ret_sts_error;
14854 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14855 WHEN OTHERS THEN
14856 l_msg_data := SQLERRM;
14857 IF l_debug = 1 THEN
14858 TRACE('EXCEPTION OTHERS: '|| l_msg_data);
14859 END IF;
14860 ROLLBACK TO assignlabelsp;
14861 freeglobals;
14862 x_return_status := fnd_api.g_ret_sts_unexp_error;
14863 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
14864 END applylabel;
14865
14866 PROCEDURE get_wms_sys_task_type(
14867 p_move_order_type IN NUMBER
14868 , p_transaction_action_id IN NUMBER
14869 , p_transaction_source_type_id IN NUMBER
14870 , x_wms_sys_task_type OUT NOCOPY NUMBER
14871 ) IS
14872 BEGIN
14873 IF p_move_order_type = 2 THEN -- replenishment
14874 x_wms_sys_task_type := 4; -- replenishment
14875 ELSIF p_move_order_type IN (3,5) THEN -- Bug 2666620: BackFlush MO Type Removed
14876 x_wms_sys_task_type := 1; -- pick
14877 ELSIF p_move_order_type = 6 THEN -- put away
14878 x_wms_sys_task_type := 2;
14879 ELSIF (p_move_order_type = 1
14880 AND p_transaction_action_id = 1
14881 AND p_transaction_source_type_id = 4
14882 ) THEN -- MO Issue
14883 x_wms_sys_task_type := 6;
14884 ELSIF (p_move_order_type = 1
14885 AND p_transaction_action_id = 2
14886 AND p_transaction_source_type_id = 4
14887 ) THEN -- MO Xfer
14888 x_wms_sys_task_type := 5;
14889 END IF;
14890 END get_wms_sys_task_type;
14891
14892 --Compile_All_Rule_Packages
14893 -- Concurrent program which generates rule packages
14894 -- for all rules with enabled flag = Y
14895 PROCEDURE compile_all_rule_packages(errbuf OUT NOCOPY VARCHAR2, retcode OUT NOCOPY NUMBER) IS
14896 l_return_status VARCHAR2(1);
14897 l_msg_count NUMBER;
14898 l_msg_data VARCHAR2(240);
14899 l_rule_id NUMBER;
14900 l_error_string VARCHAR2(240);
14901 l_errbuf VARCHAR2(240);
14902 l_return_code NUMBER;
14903
14904 CURSOR l_enabled_rules IS
14905 SELECT rule_id
14906 FROM wms_rules_b
14907 WHERE enabled_flag = 'Y'
14908 ORDER BY rule_id;
14909 BEGIN
14910 --fnd_file.put_names('genall.log', 'genall.out', '/home/jcearley/work/');
14911 retcode := 0;
14912 --fnd_file.put_line(fnd_file.LOG, '===Compiling All Rule Packages===');
14913 OPEN l_enabled_rules;
14914
14915 LOOP
14916 FETCH l_enabled_rules INTO l_rule_id;
14917 EXIT WHEN l_enabled_rules%NOTFOUND;
14918 --fnd_file.put_line(fnd_file.LOG, 'Compiling Rule ID= ' || l_rule_id);
14919 wms_rule_pvt.generaterulepackage(
14920 p_api_version => 1.0
14921 , p_init_msg_list => fnd_api.g_true
14922 , p_validation_level => fnd_api.g_valid_level_full
14923 , x_return_status => l_return_status
14924 , x_msg_count => l_msg_count
14925 , x_msg_data => l_msg_data
14926 , p_rule_id => l_rule_id
14927 );
14928
14929 --
14930 -- kkoothan Bug Fix:2561401
14931 -- Used FND APIs to check the return status of the called procedure
14932 -- instead of using hard coded values.
14933 --
14934 IF (l_return_status = fnd_api.g_ret_sts_success) THEN
14935 FND_FILE.put_line(FND_FILE.LOG, 'Success from GenerateRulePackage');
14936 ELSE
14937 FND_FILE.put_line(FND_FILE.LOG, 'Error from GenerateRulePackage:');
14938 retcode := 1;
14939
14940 FOR i IN 1 .. l_msg_count LOOP
14941 --fnd_file.put_line(fnd_file.LOG, 'Error:');
14942 l_error_string := fnd_message.get;
14943 --fnd_file.put_line(fnd_file.LOG, l_error_string);
14944 errbuf := errbuf || ' Error: Rule ' || l_rule_id || '
14945 ' || l_error_string;
14946 END LOOP;
14947 END IF;
14948 END LOOP;
14949
14950 --- Calling procedure to generate all rule list packages
14951 --- this package should be called stand alone .
14952 buildrulespkg(l_errbuf, l_return_code, l_return_status);
14953
14954 IF (l_return_status = fnd_api.g_ret_sts_success) THEN
14955 FND_FILE.put_line(FND_FILE.LOG, 'Success from BuildRulesPkg');
14956 ELSE
14957 FND_FILE.put_line(FND_FILE.LOG, 'Error from BuildRulesPkg:');
14958 retcode := 1;
14959
14960 FOR i IN 1 .. l_msg_count LOOP
14961 --fnd_file.put_line(fnd_file.LOG, 'Error:');
14962 l_error_string := fnd_message.get;
14963 --fnd_file.put_line(fnd_file.LOG, l_error_string);
14964 errbuf := errbuf || ' Error: Creating WMS Rule List Package ' || l_error_string;
14965 END LOOP;
14966 END IF;
14967 EXCEPTION
14968 WHEN OTHERS THEN
14969 retcode := 2;
14970 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
14971 fnd_msg_pub.add_exc_msg(g_pkg_name, 'Compile All Rule Packages');
14972 END IF;
14973
14974 fnd_msg_pub.count_and_get(p_count => l_msg_count, p_data => l_msg_data);
14975 --fnd_file.put_line(fnd_file.LOG, 'Exception in compile_all_rule_packages');
14976 --fnd_file.put_line(fnd_file.LOG, l_msg_data);
14977 errbuf := errbuf || 'Error: ' || l_msg_data;
14978 END compile_all_rule_packages;
14979
14980 --
14981 --
14982 PROCEDURE QuickPick
14983 (p_api_version IN NUMBER ,
14984 p_init_msg_list IN VARCHAR2 DEFAULT fnd_api.g_false ,
14985 p_commit IN VARCHAR2 DEFAULT fnd_api.g_false ,
14986 p_validation_level IN NUMBER DEFAULT fnd_api.g_valid_level_full ,
14987 x_return_status OUT NOCOPY VARCHAR2 ,
14988 x_msg_count OUT NOCOPY NUMBER ,
14989 x_msg_data OUT NOCOPY VARCHAR2 ,
14990 p_type_code IN NUMBER DEFAULT NULL ,
14991 p_transaction_temp_id IN NUMBER DEFAULT NULL ,
14992 p_organization_id IN NUMBER DEFAULT NULL ,
14993 p_inventory_item_id IN NUMBER DEFAULT NULL ,
14994 p_transaction_uom IN VARCHAR2 DEFAULT NULL,
14995 p_primary_uom IN VARCHAR2 DEFAULT NULL,
14996 p_secondary_uom IN VARCHAR2 DEFAULT NULL, -- new
14997 p_grade_code IN VARCHAR2 DEFAULT NULL, -- new
14998 p_transaction_type_id IN NUMBER DEFAULT NULL ,
14999 p_tree_id IN NUMBER DEFAULT NULL ,
15000 x_finished OUT NOCOPY VARCHAR2 ,
15001 p_detail_serial IN BOOLEAN DEFAULT FALSE ,
15002 p_from_serial IN VARCHAR2 DEFAULT NULL ,
15003 p_to_serial IN VARCHAR2 DEFAULT NULL ,
15004 p_detail_any_serial IN NUMBER DEFAULT NULL,
15005 p_unit_volume IN NUMBER DEFAULT NULL,
15006 p_volume_uom_code IN VARCHAR2 DEFAULT NULL,
15007 p_unit_weight IN NUMBER DEFAULT NULL,
15008 p_weight_uom_code IN VARCHAR2 DEFAULT NULL,
15009 p_base_uom_code IN VARCHAR2 DEFAULT NULL,
15010 p_lpn_id IN NUMBER DEFAULT NULL,
15011 p_unit_number IN VARCHAR2 DEFAULT NULL,
15012 p_simulation_mode IN NUMBER DEFAULT -1,
15013 p_project_id IN NUMBER DEFAULT NULL,
15014 p_task_id IN NUMBER DEFAULT NULL
15015 )
15016 IS
15017
15018 -- API standard variables
15019 l_api_version CONSTANT NUMBER := 1.0;
15020 l_api_name CONSTANT VARCHAR2(30) := 'QuickPick';
15021 l_debug_on BOOLEAN;
15022
15023 -- input variables
15024
15025 l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE; --
15026 l_revision wms_transactions_temp.revision%TYPE; --
15027 l_lot_number wms_transactions_temp.lot_number%TYPE; --
15028 l_lot_expiration_date wms_transactions_temp.lot_expiration_date%TYPE; --
15029 l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE; --
15030 l_to_subinventory_code wms_transactions_temp.to_subinventory_code%TYPE; --
15031 l_subinventory_code wms_transactions_temp.to_subinventory_code%TYPE;
15032 l_from_locator_id wms_transactions_temp.from_locator_id%TYPE; --
15033 l_to_locator_id wms_transactions_temp.to_locator_id%TYPE; --
15034 l_locator_id wms_transactions_temp.to_locator_id%TYPE;
15035 l_from_cost_group_id wms_transactions_temp.from_cost_group_id%TYPE; --
15036 l_to_cost_group_id wms_transactions_temp.to_cost_group_id%TYPE; --
15037 l_cost_group_id wms_transactions_temp.to_cost_group_id%TYPE;
15038 l_lpn_id wms_transactions_temp.lpn_id%TYPE; --
15039 l_initial_pri_quantity wms_transactions_temp.primary_quantity%TYPE;
15040
15041 l_reservation_id NUMBER; --
15042 l_needed_quantity NUMBER; --
15043 l_sec_needed_quantity NUMBER; -- -- new
15044 l_grade_code VARCHAR2(150); -- -- new
15045 l_cur_rec NUMBER;
15046
15047 -- variables needed for qty tree
15048 l_qoh NUMBER;
15049 l_rqoh NUMBER;
15050 l_qr NUMBER;
15051 l_qs NUMBER;
15052 l_att NUMBER;
15053 l_atr NUMBER;
15054 l_tree_mode NUMBER;
15055 l_tree_id NUMBER;
15056 l_sqoh NUMBER; -- new
15057 l_srqoh NUMBER; -- new
15058 l_sqr NUMBER; -- new
15059 l_sqs NUMBER; -- new
15060 l_satt NUMBER; -- new
15061 l_satr NUMBER; -- new
15062
15063 l_inserted_record BOOLEAN;
15064 l_allocated_quantity NUMBER;
15065 l_remaining_quantity NUMBER;
15066 l_finished VARCHAR2(1);
15067 l_sec_allocated_quantity NUMBER; -- new
15068 l_sec_remaining_quantity NUMBER; -- new
15069
15070 -- Variables to check if Item is Lot and serial contriled
15071
15072 l_lot_status_enabled VARCHAR2(1);
15073 l_default_lot_status_id NUMBER := NULL;
15074 l_serial_status_enabled VARCHAR2(1);
15075 l_default_serial_status_id NUMBER;
15076
15077
15078 l_serial_control_code NUMBER;
15079 l_is_serial_control NUMBER;
15080
15081 l_unit_number VARCHAR2(30);
15082 l_allowed VARCHAR2(1) := 'Y';
15083 l_serial_allowed VARCHAR2(1) := 'Y';
15084
15085 g_trace_recs wms_search_order_globals_pvt.pre_suggestions_record_tbl;
15086
15087 l_debug NUMBER; -- 1 for debug is on , 0 for debug is off
15088 l_progress VARCHAR2(10); -- local variable to track program progress,
15089
15090 -- especially useful when exception occurs
15091 l_serial_number NUMBER; -- [ new code ]
15092
15093 -- LPN Status Project
15094 l_onhand_status_trx_allowed VARCHAR2(1);
15095 l_default_status_id NUMBER ;
15096 -- LPN Status Project
15097
15098 cursor lpn_serial_cur(l_lpn_id NUMBER ) is
15099 SELECT STATUS_ID FROM MTL_SERIAL_NUMBERS
15100 WHERE INVENTORY_ITEM_ID = P_INVENTORY_ITEM_ID
15101 AND LPN_ID = l_lpn_id;
15102
15103
15104 BEGIN
15105
15106 IF NOT(inv_cache.is_pickrelease AND g_debug IS NOT NULL) THEN
15107 g_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
15108 END IF;
15109 l_debug := g_debug;
15110 l_progress := 10;
15111
15112 l_tree_id := p_tree_id;
15113
15114 IF l_debug = 1 THEN
15115 log_procedure(l_api_name, 'QuickPick', 'enter '|| g_pkg_name || '.' || l_api_name);
15116 END IF;
15117 -- end of debugging section
15118 --
15119 -- Standard start of API savepoint
15120 SAVEPOINT QuickPicksp;
15121
15122 -- Standard call to check for call compatibility
15123 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
15124 RAISE fnd_api.g_exc_unexpected_error;
15125 END IF;
15126 -- Initialize message list if p_init_msg_list is set to TRUE
15127 IF fnd_api.to_boolean(p_init_msg_list) THEN
15128 fnd_msg_pub.initialize;
15129 END IF;
15130 -- Initialize API return status to success
15131 x_return_status := fnd_api.g_ret_sts_success;
15132 -- Initialize functional return status to completed
15133 x_finished := fnd_api.g_true;
15134 -- Validate input parameters and pre-requisites, if validation level
15135 -- requires this
15136
15137 IF p_validation_level <> fnd_api.g_valid_level_none THEN
15138 IF l_debug = 1 THEN
15139 log_statement(l_api_name, 'Quick Pick',
15140 'p_validation_level <> fnd_api.g_valid_level_none ');
15141 END IF;
15142
15143 IF p_type_code IS NULL
15144 OR p_type_code = fnd_api.g_miss_num
15145 OR p_type_code = 1 THEN
15146 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15147 fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
15148 log_error_msg(l_api_name, 'type_code_missing');
15149 fnd_msg_pub.ADD;
15150 END IF;
15151 RAISE fnd_api.g_exc_error;
15152 END IF;
15153
15154 IF l_debug = 1 THEN
15155 log_statement(l_api_name, 'Quick Pick',
15156 'p_transaction_temp_id ' || p_transaction_temp_id );
15157 END IF;
15158
15159 IF p_transaction_temp_id IS NULL
15160 OR p_transaction_temp_id = fnd_api.g_miss_num THEN
15161 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15162 fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
15163 log_error_msg(l_api_name, 'trx_req_line_id_missing');
15164 fnd_msg_pub.ADD;
15165 END IF;
15166
15167 RAISE fnd_api.g_exc_error;
15168 END IF;
15169
15170 IF l_debug = 1 THEN
15171 log_statement(l_api_name, 'Quick Pick',
15172 'p_organization_id ' || p_organization_id );
15173 END IF;
15174
15175 IF p_organization_id IS NULL
15176 OR p_organization_id = fnd_api.g_miss_num THEN
15177 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15178 fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
15179 log_error_msg(l_api_name, 'org_id_missing');
15180 fnd_msg_pub.ADD;
15181 END IF;
15182
15183 RAISE fnd_api.g_exc_error;
15184 END IF;
15185
15186 IF l_debug = 1 THEN
15187 log_statement(l_api_name, 'Quick Pick',
15188 'p_Inventory_item_id_id ' || p_inventory_item_id );
15189 END IF;
15190
15191 IF p_inventory_item_id IS NULL
15192 OR p_inventory_item_id = fnd_api.g_miss_num THEN
15193 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15194 fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
15195 log_error_msg(l_api_name, 'item_id_missing');
15196 fnd_msg_pub.ADD;
15197 END IF;
15198
15199 RAISE fnd_api.g_exc_error;
15200 END IF;
15201
15202 /** Commented for bug 4006426
15203 IF l_debug = 1 THEN
15204 log_statement(l_api_name, 'Quick Pick', 'qty Tree =>' || p_tree_id );
15205 END IF;
15206
15207 IF (p_tree_id IS NULL
15208 OR p_tree_id = fnd_api.g_miss_num
15209 ) THEN
15210 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15211 fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
15212 log_error_msg(l_api_name, 'qty_tree_id_missing');
15213 fnd_msg_pub.ADD;
15214 END IF;
15215
15216 RAISE fnd_api.g_exc_error;
15217 END IF;
15218
15219 IF l_debug = 1 THEN
15220 log_statement(l_api_name, 'Quick Pick', 'finished validations and qty tree init' );
15221 END IF;
15222 */
15223 END IF;
15224
15225 -- LPN Status Project
15226 if (inv_cache.set_org_rec(p_organization_id)) then
15227 l_default_status_id := nvl(inv_cache.org_rec.default_status_id,-1);
15228 end if;
15229 -- LPN Status Project
15230 --
15231 -- backup qty tree
15232 If p_tree_id IS NOT NULL THEN -- Added for bug # 4006426
15233
15234 IF l_debug = 1 THEN
15235 log_statement(l_api_name, 'backup_tree',
15236 'Calling inv_quantity_tree_pvt.backup_tree');
15237 END IF;
15238
15239 inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
15240
15241 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15242 IF l_debug = 1 THEN
15243 log_statement(l_api_name, 'backup_tree_unexp_err',
15244 'Unexpected error from inv_quantity_tree_pvt.backup_tree');
15245 END IF;
15246 RAISE fnd_api.g_exc_unexpected_error;
15247 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15248 IF l_debug = 1 THEN
15249 log_statement(l_api_name, 'backup_tree_err',
15250 'Error from inv_quantity_tree_pvt.backup_tree');
15251 END IF;
15252 RAISE fnd_api.g_exc_error;
15253 END IF;
15254 END IF; --- Added for bug # 4006426
15255
15256 g_locs_index := 0;
15257 g_locs.DELETE;
15258 l_cur_rec := 0; --initialize pointer to next rec
15259
15260 IF l_debug = 1 THEN
15261 log_statement(l_api_name, 'Quick Pick',
15262 'Check if item is lot status / Serial Status enabled');
15263 END IF;
15264
15265 --Check if item is lot status / Serial Status enabled --
15266 inv_material_status_grp.get_lot_serial_status_control(
15267 p_organization_id => p_organization_id
15268 ,p_inventory_item_id => p_inventory_item_id
15269 ,x_return_status => x_return_status
15270 ,x_msg_count => x_msg_count
15271 ,x_msg_data => x_msg_data
15272 ,x_lot_status_enabled => l_lot_status_enabled
15273 ,x_default_lot_status_id => l_default_lot_status_id
15274 ,x_serial_status_enabled => l_serial_status_enabled
15275 ,x_default_serial_status_id => l_default_serial_status_id);
15276
15277 wms_re_common_pvt.initinputpointer; -- Initialize the pointer
15278 -- to the first trx detail input line
15279
15280 IF l_debug = 1 THEN
15281 log_statement(l_api_name, 'Quick Pick',
15282 'Initialize the pointer to the first trx detail input line');
15283 log_statement(l_api_name, 'Quick Pick',
15284 'Loop through all the trx detail input lines');
15285 END IF;
15286
15287 -- Loop through all the trx detail input lines
15288 WHILE TRUE LOOP
15289 IF l_debug = 1 THEN
15290 log_statement(l_api_name, 'Quick Pick',
15291 'Get the next trx detail input line ');
15292 END IF;
15293
15294 -- Get the next trx detail input line
15295 wms_re_common_pvt.getnextinputline(
15296 l_pp_transaction_temp_id
15297 , l_revision
15298 , l_lot_number
15299 , l_lot_expiration_date
15300 , l_from_subinventory_code
15301 , l_from_locator_id
15302 , l_from_cost_group_id
15303 , l_to_subinventory_code
15304 , l_to_locator_id
15305 , l_to_cost_group_id
15306 , l_needed_quantity
15307 , l_sec_needed_quantity
15308 , l_grade_code
15309 , l_reservation_id
15310 , l_serial_number -- [ new code ]
15311 , l_lpn_id
15312 );
15313 EXIT WHEN l_pp_transaction_temp_id IS NULL;
15314 IF l_debug = 1 THEN
15315 log_statement(l_api_name, 'Quick Pick',
15316 'Get sub/Locator /Lot / serial status allowed' || l_needed_quantity );
15317 END IF;
15318 -- Get sub/Locator /Lot / serial status allowed --
15319
15320 --LPN Status Project
15321 IF l_debug = 1 THEN
15322 log_statement(l_api_name, 'Came to LPN Status Project ', l_onhand_status_trx_allowed);
15323 END IF;
15324
15325
15326 l_onhand_status_trx_allowed := 'Y';
15327
15328 IF l_default_status_id = -1 THEN
15329 l_onhand_status_trx_allowed:='N';
15330
15331 -- Get sub/Locator /Lot / serial status allowed --
15332 l_allowed := inv_detail_util_pvt.is_sub_loc_lot_trx_allowed(
15333 p_transaction_type_id => p_transaction_type_id
15334 , p_organization_id => p_organization_id
15335 , p_inventory_item_id => p_inventory_item_id
15336 , p_subinventory_code => l_from_subinventory_code
15337 , p_locator_id => l_from_locator_id
15338 , p_lot_number => l_lot_number );
15339 IF ( l_allowed = 'N') then
15340 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SUB_STATUS_NA';
15341 fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
15342 fnd_msg_pub.ADD;
15343 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15344 IF l_debug = 1 THEN
15345 log_error_msg(l_api_name, x_msg_data);
15346 END IF;
15347 END IF;
15348
15349
15350 ELSE
15351 l_allowed:='N';
15352 if (inv_cache.item_rec.serial_number_control_code in (1,6)) then
15353 l_onhand_status_trx_allowed := inv_detail_util_pvt.is_onhand_status_trx_allowed(
15354 p_transaction_type_id
15355 ,p_organization_id
15356 ,p_inventory_item_id
15357 ,l_from_subinventory_code
15358 ,l_from_locator_id
15359 ,l_lot_number
15360 , l_lpn_id);
15361
15362 IF l_debug = 1 THEN
15363 log_statement(l_api_name, 'l_onhand_status_trx_allowed ', l_onhand_status_trx_allowed);
15364 END IF;
15365
15366 IF (l_onhand_status_trx_allowed = 'N') then
15367 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_DISALLOW_TRANSACTION';
15368 fnd_message.set_name('WMS', 'WMS_DISALLOW_TRANSACTION');
15369 fnd_msg_pub.ADD;
15370 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15371 IF l_debug = 1 THEN
15372 log_error_msg(l_api_name, x_msg_data);
15373 END IF;
15374 END IF;
15375 end if; -- if (inv_cache.item_rec.serial_number_control_code in (1,6))
15376
15377 END IF; -- IF l_default_status_id = -1
15378
15379 --LPN Status Project
15380
15381 IF ( l_serial_status_enabled = 'Y') then
15382 IF l_debug = 1 THEN
15383 log_statement(l_api_name, 'Quick Pick',
15384 'inside If l_serial_status_enabled = y ') ;
15385 log_statement(l_api_name, 'Quick Pick',
15386 'Calling inv_detail_util_pvt.is_serial_trx_allowed');
15387 END IF;
15388 --bug 7171840 changed the code to check the status at serial level rather than item defualt status
15389 FOR L_LPN_CUR IN lpn_serial_cur(l_lpn_id) LOOP
15390 l_serial_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
15391 p_transaction_type_id => p_transaction_type_id
15392 ,p_organization_id => p_organization_id
15393 ,p_inventory_item_id => p_inventory_item_id
15394 ,p_serial_status => L_LPN_CUR.STATUS_ID ) ;
15395
15396 IF L_SERIAL_ALLOWED = 'N' THEN
15397 log_statement(l_api_name, 'Quick Pick',
15398 'inside If l_serial_status_enabled = N ') ;
15399 EXIT;
15400 END IF;
15401 L_SERIAL_ALLOWED := 'Y';
15402 END LOOP ;
15403 /* commented out for bug 7171840
15404 l_serial_allowed := inv_detail_util_pvt.is_serial_trx_allowed(
15405 p_transaction_type_id => p_transaction_type_id
15406 ,p_organization_id => p_organization_id
15407 ,p_inventory_item_id => p_inventory_item_id
15408 ,p_serial_status => l_default_serial_status_id ) ;
15409 end of bug 7171848*/
15410
15411 ELSIF ( l_serial_status_enabled = 'N') then
15412 IF l_debug = 1 THEN
15413 log_statement(l_api_name, 'Quick Pick',
15414 'inside If l_serial_status_enabled = N ') ;
15415 END IF;
15416 l_serial_allowed := 'Y' ;
15417 END IF;
15418
15419 l_cur_rec := l_cur_rec + 1 ;
15420
15421 -- Bug # 5512287
15422 g_locs(l_cur_rec).quantity := l_needed_quantity;
15423 g_locs(l_cur_rec).secondary_quantity := l_sec_needed_quantity;
15424
15425 g_locs(l_cur_rec).revision := l_revision;
15426 g_locs(l_cur_rec).lot_number := l_lot_number;
15427 g_locs(l_cur_rec).subinventory_code := l_from_subinventory_code;
15428 g_locs(l_cur_rec).locator_id := l_from_locator_id;
15429 g_locs(l_cur_rec).cost_group_id := l_from_cost_group_id;
15430 g_locs(l_cur_rec).lpn_id := l_lpn_id;
15431
15432 --add record to table
15433 g_locs_index := g_locs_index + 1;
15434
15435 IF l_debug = 1 THEN
15436 log_statement(l_api_name, 'loc_index', 'loc index: ' || g_locs_index);
15437 END IF;
15438
15439 IF l_debug = 1 THEN
15440 log_statement(l_api_name, 'validate_and_insert', 'Calling validate_and_insert');
15441 log_statement(l_api_name, 'validate_and_insert', 'p_record_id '|| l_cur_rec);
15442 log_statement(l_api_name, 'validate_and_insert', 'p_needed_quantity '|| l_needed_quantity);
15443 log_statement(l_api_name, 'validate_and_insert', 'p_needed_sec_quantity '|| l_sec_needed_quantity);
15444 log_statement(l_api_name, 'validate_and_insert', 'p_organization_id '|| p_organization_id);
15445 log_statement(l_api_name, 'validate_and_insert', 'p_inventory_item_id'|| p_inventory_item_id);
15446 log_statement(l_api_name, 'validate_and_insert', 'p_to_subinventory_code'|| l_to_subinventory_code);
15447 log_statement(l_api_name, 'validate_and_insert', 'p_to_locator_id '|| l_to_locator_id);
15448 log_statement(l_api_name, 'validate_and_insert', 'p_to_cost_group_id '|| l_to_cost_group_id );
15449 log_statement(l_api_name, 'validate_and_insert', 'p_primary_uom '|| p_primary_uom);
15450 log_statement(l_api_name, 'validate_and_insert', 'p_transaction_uom '|| p_transaction_uom);
15451 log_statement(l_api_name, 'validate_and_insert', 'p_transaction_temp_id'|| p_transaction_temp_id );
15452 log_statement(l_api_name, 'validate_and_insert', 'p_type_code '|| p_type_code );
15453 log_statement(l_api_name, 'validate_and_insert', 'p_reservation_id '|| l_reservation_id );
15454 log_statement(l_api_name, 'validate_and_insert', 'p_tree_id '|| l_tree_id);
15455 log_statement(l_api_name, 'validate_and_insert', 'Insert an Output record into WTT if status allowed');
15456 END IF;
15457 -- Insert an Output record into WTT if status allowed
15458 --
15459 --LPN Status Project
15460
15461 IF l_debug = 1 THEN
15462 log_statement(l_api_name, 'l_onhand_status_trx_allowed: ', l_onhand_status_trx_allowed);
15463 log_statement(l_api_name, 'l_allowed: ', l_allowed);
15464 log_statement(l_api_name, 'l_serial_allowed: ', l_serial_allowed);
15465 END IF;
15466
15467
15468 IF ( ( nvl(l_allowed, 'Y') = 'Y' OR l_onhand_status_trx_allowed='Y') and nvl(l_serial_allowed, 'Y') = 'Y') then
15469 --LPN Status Project
15470 IF p_tree_id IS NOT NULL THEN -- Added for bug #4006426
15471
15472 IF l_debug = 1 THEN
15473 log_statement(l_api_name, 'Calling validate_and_insert', '');
15474 END IF;
15475 validate_and_insert(
15476 x_return_status => x_return_status
15477 , x_msg_count => x_msg_count
15478 , x_msg_data => x_msg_data
15479 , p_record_id => l_cur_rec
15480 , p_needed_quantity => l_needed_quantity
15481 , p_use_pick_uom => FALSE
15482 , p_organization_id => p_organization_id
15483 , p_inventory_item_id => p_inventory_item_id
15484 , p_to_subinventory_code => l_to_subinventory_code
15485 , p_to_locator_id => l_to_locator_id
15486 , p_to_cost_group_id => l_to_cost_group_id
15487 , p_primary_uom => p_primary_uom
15488 , p_transaction_uom => p_transaction_uom
15489 , p_transaction_temp_id => p_transaction_temp_id
15490 , p_type_code => p_type_code
15491 , p_rule_id => 0
15492 , p_reservation_id => l_reservation_id
15493 , p_tree_id => l_tree_id
15494 , p_debug_on => l_debug_on
15495 , p_needed_sec_quantity => l_sec_needed_quantity
15496 , p_secondary_uom => p_secondary_uom
15497 , p_grade_code => p_grade_code
15498 , x_inserted_record => l_inserted_record
15499 , x_allocated_quantity => l_allocated_quantity
15500 , x_remaining_quantity => l_remaining_quantity
15501 , x_sec_allocated_quantity => l_sec_allocated_quantity
15502 , x_sec_remaining_quantity => l_sec_remaining_quantity
15503 );
15504 ELSIF p_tree_id is NULL THEN -- Call the new local procedure validate_and_insert_noqtytree() for bug #4006426
15505
15506 IF l_debug = 1 THEN
15507 log_statement(l_api_name, 'Calling validateNinsert', '');
15508 END IF;
15509
15510 ValidNinsert(
15511 x_return_status => x_return_status
15512 , x_msg_count => x_msg_count
15513 , x_msg_data => x_msg_data
15514 , p_record_id => l_cur_rec
15515 , p_needed_quantity => l_needed_quantity
15516 , p_use_pick_uom => FALSE
15517 , p_organization_id => p_organization_id
15518 , p_inventory_item_id => p_inventory_item_id
15519 , p_to_subinventory_code => l_to_subinventory_code
15520 , p_to_locator_id => l_to_locator_id
15521 , p_to_cost_group_id => l_to_cost_group_id
15522 , p_primary_uom => p_primary_uom
15523 , p_transaction_uom => p_transaction_uom
15524 , p_transaction_temp_id => p_transaction_temp_id
15525 , p_type_code => p_type_code
15526 , p_rule_id => 0
15527 , p_reservation_id => l_reservation_id
15528 , p_tree_id => l_tree_id
15529 , p_debug_on => l_debug_on
15530 , x_inserted_record => l_inserted_record
15531 , x_allocated_quantity => l_allocated_quantity
15532 , x_remaining_quantity => l_remaining_quantity
15533 );
15534 END IF;
15535
15536 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15537 IF l_debug = 1 THEN
15538 log_statement(l_api_name, 'uerr_validate_insert',
15539 'Unexpected error in validate_and_insert');
15540 END IF;
15541 RAISE fnd_api.g_exc_unexpected_error;
15542 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15543 IF l_debug = 1 THEN
15544 log_statement(l_api_name, 'err_validate_insert', 'Error in validate_and_insert');
15545 END IF;
15546 RAISE fnd_api.g_exc_error;
15547 END IF;
15548
15549 IF l_inserted_record = FALSE OR l_allocated_quantity < l_needed_quantity THEN
15550 fnd_message.set_name('WMS', 'WMS_LPN_UNAVAILABLE'); --- to be Added to Mesg Dict
15551 fnd_msg_pub.ADD;
15552 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15553 IF l_debug = 1 THEN
15554 log_error_msg(l_api_name, x_msg_data);
15555 END IF;
15556
15557 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_LPN_UNAVAILABLE';
15558 IF p_tree_id IS NOT NULL THEN -- Bug# 4006426
15559
15560 IF l_debug = 1 THEN
15561 log_statement(l_api_name, 'insert_failed', 'Record failed to allocation. Rolling back and ' || 'invalidating LPN');
15562 log_statement(l_api_name, 'restore_tree', 'Calling restore_tree');
15563 END IF;
15564 inv_quantity_tree_pvt.restore_tree(x_return_status => x_return_status, p_tree_id => p_tree_id);
15565 END IF; -- Bug # 4006426
15566 END IF;
15567
15568 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
15569 IF l_debug = 1 THEN
15570 log_error(l_api_name, 'uerr_restore_tree', 'Unexpected error in restore_tree');
15571 END IF;
15572 RAISE fnd_api.g_exc_unexpected_error;
15573 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
15574 IF l_debug = 1 THEN
15575 log_error(l_api_name, 'err_restore_tree', 'Error in restore_tree');
15576 END IF;
15577 RAISE fnd_api.g_exc_error;
15578 END IF;
15579 ELSE
15580
15581 IF ( l_allowed = 'N') then
15582 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SUB_STATUS_NA';
15583 fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
15584 fnd_msg_pub.ADD;
15585
15586 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15587 IF l_debug = 1 THEN
15588 log_error_msg(l_api_name, x_msg_data);
15589 END IF;
15590
15591 ELSIF l_serial_allowed = 'N' then
15592 WMS_ENGINE_PVT.G_SUGG_FAILURE_MESSAGE := 'WMS_ATT_SERIAL_STATUS_NA' ;
15593 fnd_message.set_name('WMS', 'WMS_ATT_SUB_STATUS_NA');
15594 fnd_msg_pub.ADD;
15595 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15596
15597 IF l_debug = 1 THEN
15598 log_error_msg(l_api_name, x_msg_data);
15599 END IF;
15600 END IF;
15601 END IF;
15602
15603 -- <<nextoutputrecord>>
15604 l_cur_rec := g_locs(l_cur_rec).next_rec;
15605
15606 END LOOP;
15607 EXCEPTION
15608 WHEN fnd_api.g_exc_error THEN
15609
15610 ROLLBACK TO QuickPicksp;
15611 freeglobals;
15612 x_return_status := fnd_api.g_ret_sts_error;
15613 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15614
15615 IF l_debug = 1 THEN
15616 log_error(l_api_name, 'error', 'Expected error - ' || x_msg_data);
15617 END IF;
15618
15619 WHEN fnd_api.g_exc_unexpected_error THEN
15620 ROLLBACK TO QuickPicksp;
15621 freeglobals;
15622 x_return_status := fnd_api.g_ret_sts_unexp_error;
15623 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15624
15625 IF l_debug = 1 THEN
15626 log_error(l_api_name, 'unexp_error', 'Unexpected error - ' || x_msg_data);
15627 END IF;
15628
15629 WHEN OTHERS THEN
15630 ROLLBACK TO QuickPicksp;
15631 freeglobals;
15632 x_return_status := fnd_api.g_ret_sts_unexp_error;
15633 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15634 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
15635 END IF;
15636 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
15637
15638 IF l_debug = 1 THEN
15639 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
15640 END IF;
15641 END QuickPick;
15642
15643 -- LG convergence
15644 --
15645 -- API name : get_available_inventory
15646 -- Type : Private
15647 -- Function : Applies a wms rule to the given transaction
15648 -- input parameters and creates recommendations
15649 -- Pre-reqs : Record in WMS_STRATEGY_MAT_TXN_TMP_V uniquely
15650 -- identified by parameters p_transaction_temp_id and
15651 -- p_type_code ( base table for the view is
15652 -- MTL_MATERIAL_TRANSACTIONS_TEMP );
15653 -- At least one transaction detail record in
15654 -- WMS_TRX_DETAILS_TMP_V identified by line type code = 1
15655 -- and parameters p_transaction_temp_id and p_type_code
15656 -- ( base tables are MTL_MATERIAL_TRANSACTIONS_TEMP and
15657 -- WMS_TRANSACTIONS_TEMP, respectively );
15658 -- Rule record has to exist in WMS_RULES_B uniquely
15659 -- identified by parameter p_rule_id;
15660 -- Package WMS_RULE_(RULEID) must exist;
15661 -- If picking, quantity tree has to exist, created through
15662 -- INV_Quantity_Tree_PVT.Create_Tree and uniquely identified
15663 -- by parameter p_tree_id
15664 -- Parameters :
15665 -- p_api_version Standard Input Parameter
15666 -- p_init_msg_list Standard Input Parameter
15667 -- p_commit Standard Input Parameter
15668 -- p_validation_level Standard Input Parameter
15669 -- p_rule_id Identifier of the rule to apply
15670 -- p_type_code Type code of the rule
15671 -- p_partial_success_allowed_flag
15672 -- 'Y' or 'N'
15673 -- p_transaction_temp_id Identifier for the record in view
15674 -- wms_strategy_mat_txn_tmp_v that represents
15675 -- the request for detailing
15676 -- p_organization_id Organization identifier
15677 -- p_inventory_item_id Inventory item identifier
15678 -- p_transaction_uom Transaction UOM code
15679 -- p_primary_uom Primary UOM code
15680 -- p_tree_id Identifier for the quantity tree
15681 --
15682 -- Output Parameters
15683 -- x_return_status Standard Output Parameter
15684 -- x_msg_count Standard Output Parameter
15685 -- x_msg_data Standard Output Parameter
15686 -- x_finished whether the rule has found enough quantity to
15687 -- find a location that completely satisfy
15688 -- the requested quantity (value is 'Y' or 'N')
15689 --
15690 -- Version
15691 -- Currently version is 1.0
15692 --
15693 -- Notes : Calls API's of WMS_Common_PVT and INV_Quantity_Tree_PVT
15694 -- This API must be called internally by
15695 -- WMS_Strategy_PVT.Apply only !
15696 --APPLY
15697 PROCEDURE get_available_inventory(
15698 p_api_version IN NUMBER
15699 , p_init_msg_list IN VARCHAR2
15700 , p_commit IN VARCHAR2
15701 , p_validation_level IN NUMBER
15702 , x_return_status OUT NOCOPY VARCHAR2
15703 , x_msg_count OUT NOCOPY NUMBER
15704 , x_msg_data OUT NOCOPY VARCHAR2
15705 , p_rule_id IN NUMBER
15706 , p_type_code IN NUMBER
15707 , p_partial_success_allowed_flag IN VARCHAR2
15708 , p_transaction_temp_id IN NUMBER
15709 , p_organization_id IN NUMBER
15710 , p_inventory_item_id IN NUMBER
15711 , p_transaction_uom IN VARCHAR2
15712 , p_primary_uom IN VARCHAR2
15713 , p_transaction_type_id IN NUMBER
15714 , p_tree_id IN NUMBER
15715 , x_finished OUT NOCOPY VARCHAR2
15716 , p_detail_serial IN BOOLEAN
15717 , p_from_serial IN VARCHAR2
15718 , p_to_serial IN VARCHAR2
15719 , p_detail_any_serial IN NUMBER
15720 , p_unit_volume IN NUMBER
15721 , p_volume_uom_code IN VARCHAR2
15722 , p_unit_weight IN NUMBER
15723 , p_weight_uom_code IN VARCHAR2
15724 , p_base_uom_code IN VARCHAR2
15725 , p_lpn_id IN NUMBER
15726 , p_unit_number IN VARCHAR2
15727 , p_simulation_mode IN NUMBER
15728 , p_project_id IN NUMBER
15729 , p_task_id IN NUMBER
15730 ) IS
15731 -- API standard variables
15732 l_api_version CONSTANT NUMBER := 1.0;
15733 l_api_name CONSTANT VARCHAR2(30) := 'Apply';
15734 -- variables needed for dynamic SQL
15735 l_cursor INTEGER;
15736 l_rows INTEGER;
15737 -- rule dynamic SQL input variables
15738 l_pp_transaction_temp_id wms_transactions_temp.pp_transaction_temp_id%TYPE;
15739 l_revision wms_transactions_temp.revision%TYPE := null;
15740 l_lot_number wms_transactions_temp.lot_number%TYPE := null;
15741 l_lot_expiration_date wms_transactions_temp.lot_expiration_date%TYPE;
15742 l_from_subinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
15743 l_to_subinventory_code wms_transactions_temp.to_subinventory_code%TYPE;
15744 l_subinventory_code wms_transactions_temp.to_subinventory_code%TYPE;
15745 l_from_locator_id wms_transactions_temp.from_locator_id%TYPE;
15746 l_to_locator_id wms_transactions_temp.to_locator_id%TYPE;
15747 l_locator_id wms_transactions_temp.to_locator_id%TYPE;
15748 l_from_cost_group_id wms_transactions_temp.from_cost_group_id%TYPE;
15749 l_to_cost_group_id wms_transactions_temp.to_cost_group_id%TYPE;
15750 l_cost_group_id wms_transactions_temp.to_cost_group_id%TYPE;
15751 l_lpn_id wms_transactions_temp.lpn_id%TYPE := null;
15752 l_initial_pri_quantity wms_transactions_temp.primary_quantity%TYPE;
15753 -- rule dynamic SQL output variables
15754 l_orevision wms_transactions_temp.revision%TYPE;
15755 l_olot_number wms_transactions_temp.lot_number%TYPE;
15756 l_olot_expiration_date wms_transactions_temp.lot_expiration_date%TYPE;
15757 l_osubinventory_code wms_transactions_temp.from_subinventory_code%TYPE;
15758 l_olocator_id wms_transactions_temp.from_locator_id%TYPE;
15759 l_olocator_id_prev wms_transactions_temp.from_locator_id%TYPE;
15760 l_olocator_id_new wms_transactions_temp.from_locator_id%TYPE;
15761 l_ocost_group_id wms_transactions_temp.from_cost_group_id%TYPE;
15762 l_olpn_id wms_transactions_temp.lpn_id%TYPE;
15763 l_possible_quantity wms_transactions_temp.primary_quantity%TYPE;
15764 l_possible_trx_qty wms_transactions_temp.transaction_quantity%TYPE;
15765 l_reservation_id wms_transactions_temp.reservation_id%TYPE;
15766 -- variables needed for qty tree
15767 l_qoh NUMBER;
15768 l_rqoh NUMBER;
15769 l_qr NUMBER;
15770 l_qs NUMBER;
15771 l_att NUMBER;
15772 l_atr NUMBER;
15773 --
15774 l_rule_func_sql LONG;
15775 l_rule_result NUMBER;
15776 l_dummy NUMBER;
15777 l_pack_exists NUMBER;
15778 l_serial_control_code NUMBER;
15779 l_is_serial_control NUMBER;
15780 l_package_name VARCHAR2(128);
15781 l_msg_data VARCHAR2(240);
15782 l_msg_count NUMBER;
15783 l_rule_id NUMBER;
15784 l_unit_number VARCHAR2(30);
15785 --variables related to pick by UOM
15786 l_uom_code VARCHAR2(3);
15787 l_order_by_string VARCHAR2(1000);
15788 l_consist_string VARCHAR2(1000);
15789 l_cur_order_by_string VARCHAR2(1000) := '-9999999';
15790 l_default_pick_rule NUMBER;
15791 l_default_put_rule NUMBER;
15792 l_allowed VARCHAR2(1);
15793 l_loc_avail_units NUMBER;
15794 l_capacity_updated BOOLEAN;
15795 l_consider_staging_capacity BOOLEAN; --Added bug3237702
15796 l_return_status VARCHAR2(1);
15797 l_consist_exists BOOLEAN;
15798 l_comingle VARCHAR2(1);
15799 l_serial_number VARCHAR2(30);
15800 l_detail_serial NUMBER;
15801 l_found BOOLEAN;
15802 l_first_serial NUMBER;
15803 l_locs_index NUMBER; --index to v_locs table
15804 l_debug_on BOOLEAN;
15805 l_uom_index NUMBER;
15806 l_lpn_controlled_flag NUMBER;
15807 l_check_cg BOOLEAN;
15808 l_restrict_subs_code NUMBER;
15809 l_restrict_locs_code NUMBER;
15810 l_quantity_function NUMBER;
15811 v_current_row t_location_rec;
15812 --added to support allocation mode
15813 l_cur_lpn_group NUMBER;
15814 l_cur_lpn_rec NUMBER;
15815 l_needed_quantity NUMBER;
15816 l_inserted_record BOOLEAN;
15817 l_expected_quantity NUMBER;
15818 l_allocated_quantity NUMBER;
15819 l_remaining_quantity NUMBER;
15820 l_sec_inserted_record BOOLEAN; -- new
15821 l_sec_expected_quantity NUMBER; -- new
15822 l_sec_allocated_quantity NUMBER; -- new
15823 l_sec_remaining_quantity NUMBER; -- new
15824 l_sec_needed_quantity NUMBER; -- new
15825 l_grade_code VARCHAR2(150); -- new
15826 l_allocation_mode NUMBER;
15827 l_cur_uom_rec NUMBER;
15828 l_first_uom_rec NUMBER;
15829 l_last_uom_rec NUMBER;
15830 l_finished BOOLEAN;
15831 l_cur_consist_group NUMBER;
15832 l_use_pick_uom BOOLEAN;
15833 l_order_by_rank NUMBER := 0;
15834 l_cur_rec NUMBER;
15835 l_prev_rec NUMBER;
15836 l_next_rec NUMBER;
15837 l_hash_size NUMBER;
15838 l_sub_rsv_type NUMBER;
15839
15840 --added to support pjm
15841 l_project_id NUMBER;
15842 l_oproject_id NUMBER;
15843 l_task_id NUMBER;
15844 l_otask_id NUMBER;
15845 l_input_lpn_id NUMBER;
15846 --- Initilization of Ref cursors for Pick and putaway rules
15847 -- Added to pass into DoProjectCheck new parameter used in other apply procedure Bug3237702
15848 l_dummy_loc NUMBER;
15849
15850 v_pick_cursor wms_rule_pvt.cv_pick_type;
15851 v_put_cursor wms_rule_pvt.cv_put_type;
15852
15853 l_debug NUMBER; -- 1 for debug is on , 0 for debug is off
15854 l_progress VARCHAR2(10); -- local variable to track program progress,
15855 -- especially useful when exception occurs
15856
15857
15858 --cursor to get default rule ids from mtl_parameters table
15859 CURSOR l_default_rules IS
15860 SELECT default_wms_picking_rule_id
15861 , default_put_away_rule_id
15862 FROM mtl_parameters
15863 WHERE organization_id = p_organization_id;
15864
15865 --cursor used to determine if item is lot controlled
15866 CURSOR l_cur_serial IS
15867 SELECT serial_number_control_code
15868 , NVL(restrict_subinventories_code, 2)
15869 , NVL(restrict_locators_code, 2)
15870 FROM mtl_system_items
15871 WHERE organization_id = p_organization_id
15872 AND inventory_item_id = p_inventory_item_id;
15873
15874 --cursor used to determine if the rule package exists
15875 CURSOR l_pack_gen IS
15876 SELECT COUNT(object_name)
15877 FROM user_objects
15878 WHERE object_name = l_package_name;
15879
15880 --cursor used to determine if suggestions should be minimized
15881 -- for this rule. This flag affects how the Pick UOM functionality
15882 -- works.
15883 CURSOR c_allocation_mode IS
15884 SELECT allocation_mode_id
15885 , qty_function_parameter_id
15886 FROM wms_rules_b
15887 WHERE rule_id = l_rule_id;
15888
15889 --cursor used to determine if rule has any consistency requirements
15890 CURSOR l_consist IS
15891 SELECT consistency_id
15892 FROM wms_rule_consistencies
15893 WHERE rule_id = l_rule_id;
15894
15895 --cursor to get lpn controlled flag from subinventory
15896 CURSOR c_subinventory IS
15897 SELECT lpn_controlled_flag, reservable_type
15898 FROM mtl_secondary_inventories
15899 WHERE organization_id = p_organization_id
15900 AND secondary_inventory_name = l_osubinventory_code;
15901
15902 --cursor to get the total quantity for the LPN
15903 CURSOR c_lpn_quantity IS
15904 SELECT SUM(primary_transaction_quantity)
15905 FROM mtl_onhand_quantities_detail
15906 WHERE lpn_id = v_current_row.lpn_id;
15907
15908
15909 BEGIN
15910 --
15911 l_debug := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
15912 l_progress := 10;
15913 -- debugging portion
15914 -- can be commented ut for final code
15915 if nvl(inv_cache.is_pickrelease, FALSE) THEN
15916 If (l_debug = 1) then
15917 log_event(l_api_name, 'Check if Pick Release', 'True');
15918 End if;
15919 l_consider_staging_capacity := FALSE;
15920 else
15921 If (l_debug = 1) then
15922 log_event(l_api_name, 'Check if Pick Release', 'False');
15923 End if;
15924 l_consider_staging_capacity := TRUE;
15925 end if;
15926 IF inv_pp_debug.is_debug_mode THEN
15927 inv_pp_debug.send_message_to_pipe('enter '|| g_pkg_name || '.'
15928 || l_api_name);
15929 END IF;
15930 IF l_debug = 1 THEN
15931 log_procedure(l_api_name, 'start', 'Start Apply');
15932 END IF;
15933 -- end of debugging section
15934 --
15935 -- Standard start of API savepoint
15936 SAVEPOINT applyrulesp;
15937
15938 -- Standard call to check for call compatibility
15939 IF NOT fnd_api.compatible_api_call(l_api_version, p_api_version, l_api_name, g_pkg_name) THEN
15940 RAISE fnd_api.g_exc_unexpected_error;
15941 END IF;
15942
15943 -- Initialize message list if p_init_msg_list is set to TRUE
15944 IF fnd_api.to_boolean(p_init_msg_list) THEN
15945 fnd_msg_pub.initialize;
15946 END IF;
15947
15948 --
15949 -- Initialize API return status to success
15950 x_return_status := fnd_api.g_ret_sts_success;
15951 --
15952 -- Initialize functional return status to completed
15953 x_finished := fnd_api.g_true;
15954
15955 --
15956 -- Validate input parameters and pre-requisites, if validation level
15957 -- requires this
15958 IF p_validation_level <> fnd_api.g_valid_level_none THEN
15959 IF p_type_code IS NULL
15960 OR p_type_code = fnd_api.g_miss_num THEN
15961 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
15962 fnd_message.set_name('WMS', 'WMS_RULE_TYPE_CODE_MISSING');
15963 fnd_msg_pub.ADD;
15964 IF l_debug = 1 THEN
15965 log_error_msg(l_api_name, 'type_code_missing');
15966 END IF;
15967 END IF;
15968 RAISE fnd_api.g_exc_error;
15969 END IF;
15970
15971 -- init variables
15972 l_revision := null;
15973 l_lot_number := null;
15974 l_lpn_id := null;
15975
15976 --changed by jcearley on 11/22/99, b/c a null rule_id is now allowed
15977 -- if rule_id is null, use default rule (0 for put away, 1 for pick)
15978
15979 IF p_rule_id IS NULL OR p_rule_id = fnd_api.g_miss_num THEN
15980 --query org parameters to get user's default rule
15981 IF l_debug = 1 THEN
15982 log_statement(l_api_name,'no_rule','Getting default rule at org level');
15983 END IF;
15984 OPEN l_default_rules;
15985 FETCH l_default_rules INTO l_default_pick_rule, l_default_put_rule;
15986
15987 IF l_default_rules%NOTFOUND THEN
15988 IF l_debug = 1 THEN
15989 log_statement(l_api_name, 'org_not_found', 'Organization not found');
15990 END IF;
15991 l_default_pick_rule := NULL;
15992 l_default_put_rule := NULL;
15993 END IF;
15994
15995 CLOSE l_default_rules;
15996
15997 --if default rule not defined, use default seeded rule
15998 IF p_type_code = 1 THEN --put away
15999 l_rule_id := l_default_put_rule;
16000
16001 IF l_rule_id IS NULL THEN
16002 IF l_debug = 1 THEN
16003 log_statement(l_api_name, 'no_org_rule_put',
16004 'Did not find org default put away rule');
16005 END IF;
16006 l_rule_id := 10;
16007 END IF;
16008 ELSE --pick
16009 l_rule_id := l_default_pick_rule;
16010
16011 IF l_rule_id IS NULL THEN
16012 IF l_debug = 1 THEN
16013 log_statement(l_api_name, 'no_org_rule_put',
16014 'Did not find org default put away rule');
16015 END IF;
16016 l_rule_id := 2;
16017 END IF;
16018 END IF;
16019 IF l_debug = 1 THEN
16020 log_statement(l_api_name, 'default_rule',
16021 'Rule being used: ' || l_rule_id);
16022 END IF;
16023 ELSE
16024 l_rule_id := p_rule_id;
16025 END IF;
16026
16027 /* Lgao, Bug 5141737 select available will not check this flag, not used */
16028 /*IF p_partial_success_allowed_flag IS NULL
16029 OR p_partial_success_allowed_flag = fnd_api.g_miss_char THEN
16030 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16031 fnd_message.set_name('WMS', 'WMS_PARTIAL_SUCC_FLAG_MISS');
16032
16033 IF l_debug = 1 THEN
16034 log_error_msg(l_api_name, 'partial_succ_flag_missing');
16035 END IF;
16036 fnd_msg_pub.ADD;
16037 END IF;
16038
16039 RAISE fnd_api.g_exc_error;
16040 END IF;
16041 */
16042
16043 IF p_transaction_temp_id IS NULL
16044 OR p_transaction_temp_id = fnd_api.g_miss_num THEN
16045 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16046 fnd_message.set_name('WMS', 'WMS_TRX_REQ_LINE_ID_MISS');
16047 fnd_msg_pub.ADD;
16048 IF l_debug = 1 THEN
16049 log_error_msg(l_api_name, 'trx_req_line_id_missing');
16050 END IF;
16051
16052 END IF;
16053
16054 RAISE fnd_api.g_exc_error;
16055 END IF;
16056
16057 IF p_organization_id IS NULL
16058 OR p_organization_id = fnd_api.g_miss_num THEN
16059 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16060 fnd_message.set_name('INV', 'INV_NO_ORG_INFORMATION');
16061 fnd_msg_pub.ADD;
16062 IF l_debug = 1 THEN
16063 log_error_msg(l_api_name, 'org_id_missing');
16064 END IF;
16065 END IF;
16066
16067 RAISE fnd_api.g_exc_error;
16068 END IF;
16069
16070 IF p_inventory_item_id IS NULL
16071 OR p_inventory_item_id = fnd_api.g_miss_num THEN
16072 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16073 fnd_message.set_name('INV', 'INV_ITEM_ID_REQUIRED');
16074 fnd_msg_pub.ADD;
16075 IF l_debug = 1 THEN
16076 log_error_msg(l_api_name, 'item_id_missing');
16077 END IF;
16078 END IF;
16079
16080 RAISE fnd_api.g_exc_error;
16081 END IF;
16082
16083 IF p_type_code = 2
16084 AND (p_tree_id IS NULL
16085 OR p_tree_id = fnd_api.g_miss_num
16086 ) THEN
16087 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16088 fnd_message.set_name('INV', 'INV_QTY_TREE_ID_MISSING');
16089 fnd_msg_pub.ADD;
16090
16091 IF l_debug = 1 THEN
16092 log_error_msg(l_api_name, 'qty_tree_id_missing');
16093 END IF;
16094 END IF;
16095
16096 RAISE fnd_api.g_exc_error;
16097 END IF;
16098 END IF;
16099
16100 --inv_pp_debug.send_message_to_pipe('finished validations and qty tree init');
16101
16102 --
16103 -- backup qty tree
16104 IF p_type_code = 2 THEN
16105 IF l_debug = 1 THEN
16106 log_statement(l_api_name, 'backup_tree',
16107 'Calling inv_quantity_tree_pvt.backup_tree');
16108 END IF;
16109 inv_quantity_tree_pvt.backup_tree(x_return_status, p_tree_id);
16110
16111 IF x_return_status = fnd_api.g_ret_sts_unexp_error THEN
16112 IF l_debug = 1 THEN
16113 log_statement(l_api_name, 'backup_tree_unexp_err',
16114 'Unexpected error from inv_quantity_tree_pvt.backup_tree');
16115 END IF;
16116
16117 RAISE fnd_api.g_exc_unexpected_error;
16118 ELSIF x_return_status = fnd_api.g_ret_sts_error THEN
16119 IF l_debug = 1 THEN
16120 log_statement(l_api_name, 'backup_tree_err',
16121 'Error from inv_quantity_tree_pvt.backup_tree');
16122 END IF;
16123 RAISE fnd_api.g_exc_error;
16124 END IF;
16125
16126 --does the rule have any consistency restrictions?
16127 OPEN l_consist;
16128 FETCH l_consist INTO l_dummy;
16129
16130 IF l_consist%NOTFOUND THEN
16131 l_consist_exists := FALSE;
16132
16133 IF l_debug = 1 THEN
16134 log_statement(l_api_name, 'consist_exist_false',
16135 'Consistencies do not exist');
16136 END IF;
16137 ELSE
16138 l_consist_exists := TRUE;
16139
16140 IF l_debug = 1 THEN
16141 log_statement(l_api_name, 'consist_exist_true', 'Consistencies exist');
16142 END IF;
16143
16144 END IF;
16145 CLOSE l_consist;
16146 END IF;
16147
16148 --
16149
16150 --Get allocation mode
16151 OPEN c_allocation_mode;
16152 FETCH c_allocation_mode INTO l_allocation_mode, l_quantity_function;
16153
16154 IF c_allocation_mode%NOTFOUND
16155 OR l_allocation_mode IS NULL THEN
16156 --by default, make allocation mode 3
16157 l_allocation_mode := 3;
16158 END IF;
16159
16160 CLOSE c_allocation_mode;
16161
16162 IF l_allocation_mode IN (3, 4) THEN
16163 l_use_pick_uom := TRUE;
16164 ELSE
16165 l_use_pick_uom := FALSE;
16166 END IF;
16167
16168 -- make sure, everything is clean
16169 freeglobals;
16170 wms_parameter_pvt.clearcache;
16171 --
16172 g_trace_recs.DELETE;
16173 l_debug_on := isruledebugon(p_simulation_mode);
16174 --query items table to see if item is serial controlled (picking) or if it
16175 -- restricts subs or locators (putaway)
16176 OPEN l_cur_serial;
16177 FETCH l_cur_serial
16178 INTO l_serial_control_code
16179 , l_restrict_subs_code
16180 , l_restrict_locs_code
16181 ;
16182
16183 IF l_cur_serial%NOTFOUND THEN
16184 l_serial_control_code := 1;
16185 l_restrict_subs_code := 2;
16186 l_restrict_locs_code := 2;
16187 END IF;
16188
16189 CLOSE l_cur_serial;
16190
16191 -- Only detail serial numbers if they are prespecified or entered
16192 -- at inventory receipt for this item.
16193 IF p_type_code = 2 THEN --pick
16194 IF l_serial_control_code IN (2, 5) THEN
16195 l_is_serial_control := 1;
16196 ELSE
16197 l_is_serial_control := 0;
16198 END IF;
16199 ELSE
16200 l_is_serial_control := 0;
16201 END IF;
16202
16203 IF p_detail_serial = TRUE THEN
16204 l_detail_serial := 1;
16205 ELSE
16206 l_detail_serial := 0;
16207 END IF;
16208
16209 IF l_debug = 1 THEN
16210 log_statement(l_api_name, 'input_proj', 'Project: ' || p_project_id);
16211 log_statement(l_api_name, 'input_task', 'Task: ' || p_task_id);
16212 END IF;
16213
16214 --get the name of the rule package
16215 getpackagename(l_rule_id, l_package_name);
16216 -- Initialize the pointer to the first trx detail input line
16217 wms_re_common_pvt.initinputpointer;
16218 --
16219 IF l_debug = 1 THEN
16220 log_statement(l_api_name, 'get line ', 'get line input');
16221 END IF;
16222 wms_re_common_pvt.getnextinputline(
16223 l_pp_transaction_temp_id
16224 , l_revision
16225 , l_lot_number
16226 , l_lot_expiration_date
16227 , l_from_subinventory_code
16228 , l_from_locator_id
16229 , l_from_cost_group_id
16230 , l_to_subinventory_code
16231 , l_to_locator_id
16232 , l_to_cost_group_id
16233 , l_needed_quantity
16234 , l_sec_needed_quantity
16235 , l_grade_code
16236 , l_reservation_id
16237 , l_serial_number -- [ new code ]
16238 , l_lpn_id
16239 );
16240
16241 -- Loop through all the trx detail input lines
16242 IF l_debug = 1 THEN
16243 log_statement(l_api_name, 'input_rec', 'Got next input line');
16244 log_statement(l_api_name, 'input_rev', 'rev:' || l_revision);
16245 log_statement(l_api_name, 'input_lot', 'lot:' || l_lot_number);
16246 log_statement(l_api_name, 'input_sub', 'sub:' || l_from_subinventory_code);
16247 log_statement(l_api_name, 'input_loc', 'loc:' || l_from_locator_id);
16248 log_statement(l_api_name, 'input_cg', 'cg:' || l_from_cost_group_id);
16249 log_statement(l_api_name, 'input_tsub', 'tsub:' || l_to_subinventory_code);
16250 log_statement(l_api_name, 'input_tloc', 'tloc:' || l_to_locator_id);
16251 log_statement(l_api_name, 'input_tcg', 'tcg:' || l_to_cost_group_id);
16252 log_statement(l_api_name, 'input_lpn', 'lpn:' || l_lpn_id);
16253 log_statement(l_api_name, 'input_qty', 'qty:' || l_needed_quantity);
16254 log_statement(l_api_name, 'input_qty', 'sec qty:' || l_sec_needed_quantity);
16255
16256 END IF;
16257
16258 IF ((p_project_id IS NOT NULL) AND (l_to_locator_id IS NOT NULL) AND (p_type_code = 1)) THEN
16259 --bug 2400549 - for WIP backflush transfer putaway,
16260 --always use the locator specified on the move order line, even
16261 --if that locator is from common stock (not project)
16262 -- Bug 2666620: BackFlush MO Type Removed. It is now 5. Moreover Txn Action ID is 2 which is
16263 -- already handled.
16264 IF NOT (wms_engine_pvt.g_move_order_type = 5 AND wms_engine_pvt.g_transaction_action_id = 2) THEN
16265
16266 IF l_debug = 1 THEN
16267 log_statement(l_api_name, 'do_project1', 'Calling do project check');
16268 END IF;
16269
16270 IF doprojectcheck(l_return_status, l_to_locator_id, p_project_id, p_task_id, l_to_locator_id, l_dummy_loc) THEN
16271
16272 IF l_debug = 1 THEN
16273 log_statement(l_api_name, 'do_project1_success', 'Do Project Check passed');
16274 END IF;
16275
16276 NULL;
16277 END IF;
16278 END IF;
16279 END IF;
16280
16281 --
16282 -- Save the initial input qty for later usage
16283 l_initial_pri_quantity := l_needed_quantity;
16284 --
16285 l_input_lpn_id := l_lpn_id;
16286
16287 IF p_type_code = 2 THEN
16288 --check for null values. NULL produces error in stored procedure,
16289 -- so we treat -9999 as NULL;
16290 -- since revision is varchar(3), use -99
16291 -- we only want to overwrite revision and lot for pick rules, since
16292 -- we use these values in putaway.
16293 IF (l_revision IS NULL) THEN
16294 --gmi_reservation_util.println('l_revision is null');
16295 l_revision := '-99';
16296 END IF;
16297
16298 IF (l_lot_number IS NULL) THEN
16299 l_lot_number := '-9999';
16300 END IF;
16301 END IF;
16302
16303 IF (p_type_code = 2) THEN --pick
16304 l_subinventory_code := l_from_subinventory_code;
16305 l_locator_id := l_from_locator_id;
16306 l_cost_group_id := l_from_cost_group_id;
16307 ELSE --put away
16308 l_subinventory_code := l_to_subinventory_code;
16309 l_locator_id := l_to_locator_id;
16310 l_cost_group_id := l_to_cost_group_id;
16311 END IF;
16312
16313 IF (l_subinventory_code IS NULL) THEN
16314 l_subinventory_code := '-9999';
16315 END IF;
16316
16317 IF (l_locator_id IS NULL) THEN
16318 l_locator_id := -9999;
16319 END IF;
16320
16321 IF (l_cost_group_id IS NULL) THEN
16322 l_cost_group_id := -9999;
16323 END IF;
16324
16325 IF (l_lpn_id IS NULL) THEN
16326 l_lpn_id := -9999;
16327 END IF;
16328
16329 IF (p_project_id IS NULL) THEN
16330 l_project_id := -9999;
16331 ELSE
16332 l_project_id := p_project_id;
16333 END IF;
16334
16335 IF (p_task_id IS NULL) THEN
16336 l_task_id := -9999;
16337 ELSE
16338 l_task_id := p_task_id;
16339 END IF;
16340
16341 IF (p_unit_number IS NULL) THEN
16342 l_unit_number := '-9999';
16343 ELSE
16344 l_unit_number := p_unit_number;
16345 END IF;
16346
16347 IF l_debug = 1 THEN
16348 log_statement(l_api_name, 'calling_open_curs', 'Calling open_curs');
16349 END IF;
16350
16351 -- Bug# 2430429
16352 -- The call to open_curs was not using bind variables.
16353 -- This was causing performance problems
16354
16355 -- l_cursor := dbms_sql.open_cursor;
16356 --build dynamic PL/SQL for call to stored procedure;
16357 -- open_curs opens the appropriate cursor for the rule;
16358 -- this call has to be dynamic because of the name of the rule package
16359 IF p_type_code = 2 THEN
16360 --pick_open_curs
16361 --inv_pp_debug.send_message_to_pipe('Calling **pick_open_curs ** wms_rule_pick_pkg1.execute');
16362 IF (l_revision IS NULL) THEN
16363 --gmi_reservation_util.println('l_revision is null');
16364 l_revision := '-99';
16365 END IF;
16366
16367 IF (l_lot_number IS NULL) THEN
16368 l_lot_number := '-9999';
16369 END IF;
16370 IF (l_lpn_id IS NULL) THEN
16371 l_lpn_id := -9999;
16372 END IF;
16373 IF l_debug = 1 THEN
16374 log_statement(l_api_name, 'pick_open_rule :l_rule_id ', l_rule_id);
16375 log_statement(l_api_name, 'pick_open_rule :p_organization_id ', p_organization_id);
16376 log_statement(l_api_name, 'pick_open_rule :p_inventory_item_id ', p_inventory_item_id);
16377 log_statement(l_api_name, 'pick_open_rule :p_transaction_type_id ', p_transaction_type_id);
16378 log_statement(l_api_name, 'pick_open_rule :l_revision ', l_revision);
16379 log_statement(l_api_name, 'pick_open_rule :l_lot_number ', l_lot_number);
16380 log_statement(l_api_name, 'pick_open_rule :l_from_subinventory_code ', l_subinventory_code);
16381 log_statement(l_api_name, 'pick_open_rule :l_locator_id ', l_locator_id);
16382 log_statement(l_api_name, 'pick_open_rule :l_cost_group_id ', l_cost_group_id);
16383 log_statement(l_api_name, 'pick_open_rule :l_pp_transaction_temp_id ', l_pp_transaction_temp_id);
16384 log_statement(l_api_name, 'pick_open_rule :l_is_serial_control ', l_is_serial_control);
16385 log_statement(l_api_name, 'pick_open_rule :l_detail_serial ', l_detail_serial);
16386 log_statement(l_api_name, 'pick_open_rule :p_detail_any_serial ', p_detail_any_serial);
16387 log_statement(l_api_name, 'pick_open_rule :p_from_serial ', p_from_serial);
16388 log_statement(l_api_name, 'pick_open_rule :p_to_serial ', p_to_serial);
16389 log_statement(l_api_name, 'pick_open_rule :l_unit_number ', l_unit_number);
16390 log_statement(l_api_name, 'pick_open_rule :l_lpn_id ', l_lpn_id);
16391 log_statement(l_api_name, 'pick_open_rule :l_project_id ', l_project_id);
16392 log_statement(l_api_name, 'pick_open_rule :l_task_id ', l_task_id);
16393 log_statement(l_api_name, 'pick_open_rule :l_rule_result ',l_rule_result);
16394 END IF;
16395 pick_open_rule(
16396 v_pick_cursor
16397 , l_rule_id
16398 , p_organization_id
16399 , p_inventory_item_id
16400 , p_transaction_type_id
16401 , l_revision
16402 , l_lot_number
16403 , l_subinventory_code
16404 , l_locator_id
16405 , l_cost_group_id
16406 , l_pp_transaction_temp_id
16407 , l_is_serial_control
16408 , l_detail_serial
16409 , p_detail_any_serial
16410 , p_from_serial
16411 , p_to_serial
16412 , l_unit_number
16413 , l_lpn_id
16414 , l_project_id
16415 , l_task_id
16416 , l_rule_result
16417 );
16418 --gmi_reservation_util.println('after open rule');
16419 fetchcursorrows(
16420 x_return_status
16421 , x_msg_count
16422 , x_msg_data
16423 , v_pick_cursor
16424 , l_rule_id
16425 );
16426 close_pick_rule(l_rule_id, v_pick_cursor);
16427
16428 /*FETCH v_pick_cursor bulk collect INTO
16429 WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl;
16430 */
16431 /*FOR i IN 1..WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT
16432 LOOP
16433 WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).organization_id := p_organization_id;
16434 WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).inventory_item_id := p_inventory_item_id;
16435 END LOOP;
16436 gmi_reservation_util.println('fetch the rows, return rows number'
16437 ||WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT);
16438 FOR i IN 1..WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl.COUNT
16439 LOOP
16440 gmi_reservation_util.println('fetch the rows, 2nd qty '
16441 ||WMS_SEARCH_ORDER_GLOBALS_PVT.g_available_inv_tbl(i).secondary_onhand_qty);
16442 end loop;
16443 */
16444 END IF;
16445 EXCEPTION
16446 /*WHEN INVALID_PKG_STATE THEN
16447 x_return_status := fnd_api.g_ret_sts_unexp_error;
16448 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
16449 fnd_message.set_token('LIST_PKG', l_list_pkg);
16450 fnd_message.set_token('RULE_NAME', l_package_name);
16451 fnd_msg_pub.ADD;
16452 log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
16453 || l_list_pkg || ' / ' || l_package_name);
16454 */
16455 WHEN OTHERS THEN
16456 x_return_status := fnd_api.g_ret_sts_unexp_error;
16457
16458 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16459 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
16460 END IF;
16461
16462 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16463 --
16464 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
16465
16466 -- debugging portion
16467 -- can be commented ut for final code
16468 IF inv_pp_debug.is_debug_mode THEN
16469 -- Note: in debug mode, later call to fnd_msg_pub.get will not get
16470 -- the message retrieved here since it is no longer on the stack
16471 inv_pp_debug.set_last_error_message(SQLERRM);
16472 inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
16473 inv_pp_debug.send_last_error_message;
16474 END IF;
16475 -- end of debugging section
16476 END get_available_inventory;
16477
16478 PROCEDURE FetchCursorRows(
16479 x_return_status OUT NOCOPY VARCHAR2
16480 , x_msg_count OUT NOCOPY NUMBER
16481 , x_msg_data OUT NOCOPY VARCHAR2
16482 , p_cursor IN wms_rule_pvt.cv_pick_type
16483 , p_rule_id IN NUMBER
16484 ) IS
16485 invalid_pkg_state exception;
16486 Pragma Exception_Init(invalid_pkg_state, -6508);
16487
16488 l_list_pkg VARCHAR2(30);
16489
16490 l_api_name VARCHAR2(30) := 'FetchCursor';
16491 l_rows NUMBER;
16492 l_func_sql VARCHAR(1000);
16493 l_cursor NUMBER;
16494 l_dummy NUMBER;
16495 l_package_name VARCHAR2(128);
16496 l_ctr NUMBER := 0;
16497
16498
16499 BEGIN
16500 -- Initialize API return status to success
16501 x_return_status := fnd_api.g_ret_sts_success;
16502
16503 --
16504 -- debugging portion
16505 -- can be commented ut for final code
16506 IF inv_pp_debug.is_debug_mode THEN
16507 inv_pp_debug.send_message_to_pipe('enter '|| g_pkg_name || '.' || l_api_name);
16508 END IF;
16509
16510 log_procedure(l_api_name, 'start', 'Start FetchCursorrows');
16511 -- end of debugging section
16512 --
16513
16514 --get package name based on rule id
16515 getpackagename(p_rule_id, l_package_name);
16516 log_statement(l_package_name, 'package_name ', l_package_name);
16517 --- calling the static fetch cursor. The name of the rule package will be
16518 --- determined based on the rule_id
16519 --- If the ctr is 1 then there is no subscript ,
16520 --- if ctr = 2 then subscript = 1
16521 --- and if ctr = 3 then subscript = 2, this script is added to the package
16522 --- name.
16523 l_ctr := wms_rule_gen_pkgs.get_count_no_lock('PICK');
16524 l_list_pkg := 'wms_rule_pick_pkg' || l_ctr ;
16525 log_statement(l_package_name, 'l_ctr ', l_ctr);
16526 --log_statement(l_package_name, 'p_cursor ', p_cursor);
16527
16528 IF (l_ctr = 1) THEN
16529
16530 wms_rule_pick_pkg1.execute_fetch_available_inv(
16531 p_cursor
16532 , p_rule_id
16533 , x_return_status
16534 );
16535 ELSIF (l_ctr = 2) THEN
16536
16537 wms_rule_pick_pkg2.execute_fetch_available_inv(
16538 p_cursor
16539 , p_rule_id
16540 , x_return_status
16541 );
16542 ELSIF (l_ctr = 3) THEN
16543 wms_rule_pick_pkg3.execute_fetch_available_inv(
16544 p_cursor
16545 , p_rule_id
16546 , x_return_status
16547 );
16548 END IF;
16549
16550 IF inv_pp_debug.is_debug_mode THEN
16551 inv_pp_debug.send_message_to_pipe('exit '|| g_pkg_name || '.' || l_api_name);
16552 END IF;
16553 -- end of debugging section
16554 log_procedure(l_api_name, 'end', 'End FetchCursorrows');
16555 --
16556 EXCEPTION
16557 WHEN INVALID_PKG_STATE THEN
16558 x_return_status := fnd_api.g_ret_sts_unexp_error;
16559 fnd_message.set_name('WMS', 'WMS_INVALID_PKG');
16560 fnd_message.set_token('LIST_PKG', l_list_pkg);
16561 fnd_message.set_token('RULE_NAME', l_package_name);
16562 fnd_msg_pub.ADD;
16563 log_error(l_api_name, 'execute_fetch_rule', 'Invalid Package, Contact your DBA - '
16564 || l_list_pkg || ' / ' || l_package_name);
16565
16566 WHEN OTHERS THEN
16567 x_return_status := fnd_api.g_ret_sts_unexp_error;
16568
16569 IF fnd_msg_pub.check_msg_level(fnd_msg_pub.g_msg_lvl_unexp_error) THEN
16570 fnd_msg_pub.add_exc_msg(g_pkg_name, l_api_name);
16571 END IF;
16572
16573 fnd_msg_pub.count_and_get(p_count => x_msg_count, p_data => x_msg_data);
16574 --
16575 log_error(l_api_name, 'other_error', 'Other error - ' || x_msg_data);
16576
16577 -- debugging portion
16578 -- can be commented ut for final code
16579 IF inv_pp_debug.is_debug_mode THEN
16580 -- Note: in debug mode, later call to fnd_msg_pub.get will not get
16581 -- the message retrieved here since it is no longer on the stack
16582 inv_pp_debug.set_last_error_message(SQLERRM);
16583 inv_pp_debug.send_message_to_pipe('exception in '|| l_api_name);
16584 inv_pp_debug.send_last_error_message;
16585 END IF;
16586 -- end of debugging section
16587 END FetchCursorRows;
16588 -- end LG convergence
16589
16590 END wms_rule_pvt;