1 PACKAGE BODY wms_replenishment_pvt AS
2 /* $Header: WMSREPVB.pls 120.31.12020000.5 2013/03/18 05:52:51 pramadur ship $ */
3
4
5 -- PACKAGE variables
6 g_ordered_psr psrTabTyp;
7 g_total_pick_criteria NUMBER := 5;
8 g_conversion_precision NUMBER := 5;
9
10
11 -- replenishment Type
12 g_push_repl NUMBER := 1;
13 g_dynamic_repl NUMBER := 2;
14
15 -- This is a function used to retrieve the UOM conversion rate given an inventory item ID,
16 -- from UOM code and to UOM code. The values retrieved will be cached in a global PLSQL table.
17
18 PROCEDURE print_debug(p_err_msg VARCHAR2)
19 IS
20 BEGIN
21 inv_mobile_helper_functions.tracelog(p_err_msg => p_err_msg,
22 p_module => 'WMS_REPLENISHMENT_PVT',
23 p_level => 4);
24 END print_debug;
25
26
27
28 FUNCTION get_conversion_rate(p_item_id IN NUMBER,
29 p_from_uom_code IN VARCHAR2,
30 p_to_uom_code IN VARCHAR2) RETURN NUMBER
31 IS
32 l_conversion_rate NUMBER;
33 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
34
35 BEGIN
36 IF (p_from_uom_code = p_to_uom_code) THEN
37 -- No conversion necessary
38 l_conversion_rate := 1;
39 ELSE
40 -- Check if the conversion rate for the item/from UOM/to UOM combination is cached
41 IF (g_item_uom_conversion_tb.EXISTS(p_item_id) AND
42 g_item_uom_conversion_tb(p_item_id).EXISTS(p_from_uom_code) AND
43 g_item_uom_conversion_tb(p_item_id)(p_from_uom_code).EXISTS(p_to_uom_code)) THEN
44
45 -- Conversion rate is cached so just use the value
46 l_conversion_rate := g_item_uom_conversion_tb(p_item_id)(p_from_uom_code)(p_to_uom_code);
47 ELSE
48 -- Conversion rate is not cached so query and store the value
49 inv_convert.inv_um_conversion(from_unit => p_from_uom_code,
50 to_unit => p_to_uom_code,
51 item_id => p_item_id,
52 uom_rate => l_conversion_rate);
53 IF (l_conversion_rate > 0) THEN
54 -- Store the conversion rate and also the reverse conversion.
55 -- Do this only if the conversion rate returned is valid, i.e. not negative.
56 -- {{
57 -- Test having an exception when retrieving the UOM conversion rate. }}
58 g_item_uom_conversion_tb(p_item_id)(p_from_uom_code)(p_to_uom_code) := l_conversion_rate;
59 g_item_uom_conversion_tb(p_item_id)(p_to_uom_code)(p_from_uom_code) := 1 /l_conversion_rate;
60 END IF;
61 END IF;
62 END IF;
63
64 -- Return the conversion rate retrieved
65 RETURN l_conversion_rate;
66
67 EXCEPTION
68 WHEN OTHERS THEN
69 IF l_debug = 1 THEN
70 print_debug('Exception in get_conversion_rate: ' || sqlcode || ', ' || sqlerrm);
71 END IF;
72 -- If an exception occurs, return a negative value.
73 -- The calling program should interpret this as an exception in retrieving
74 -- the UOM conversion rate.
75 RETURN -999;
76 END get_conversion_rate;
77
78
79 -- API name : Init_Rules
80 -- Type : Public
81 -- Pre-reqs : None.
82 -- Procedure: API to retrieves sequencing information based on sequence rule and
83 -- group information based on grouping rule.
84 -- Parameters :
85 -- IN:
86 -- p_pick_seq_rule_id IN pick sequence rule id.
87 -- OUT:
88 -- x_api_status OUT NOCOPY Standard to output api status.
89
90 -- This API gets called from the wms_task_dispatch_gen.pick_drop() API as
91 -- well. Needed to pass x_ordered_psr for this
92
93 PROCEDURE Init_Rules(p_pick_seq_rule_id IN NUMBER
94 , x_order_id_sort OUT NOCOPY VARCHAR2
95 , x_INVOICE_VALUE_SORT OUT NOCOPY VARCHAR2
96 , x_SCHEDULE_DATE_SORT OUT NOCOPY VARCHAR2
97 , x_trip_stop_date_sort OUT NOCOPY VARCHAR2
98 , x_SHIPMENT_PRI_SORT OUT NOCOPY VARCHAR2
99 , x_ordered_psr OUT nocopy psrTabTyp
100 , x_api_status OUT NOCOPY VARCHAR2)
101 IS
102
103
104 -- cursor to fetch pick sequence rule info
105 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
106 CURSOR pick_seq_rule(v_psr_id NUMBER) IS
107 SELECT NAME,
108 NVL(ORDER_ID_PRIORITY, 999999999),
109 DECODE(ORDER_ID_SORT, 'A', 'ASC', 'D', 'DESC', ''),
110 NVL(INVOICE_VALUE_PRIORITY, 999999999),
111 DECODE(INVOICE_VALUE_SORT, 'A', 'ASC', 'D', 'DESC', ''),
112 NVL(SCHEDULE_DATE_PRIORITY, 999999999),
113 DECODE(SCHEDULE_DATE_SORT, 'A', 'ASC', 'D', 'DESC', ''),
114 NVL(SHIPMENT_PRI_PRIORITY, 999999999),
115 DECODE(SHIPMENT_PRI_SORT, 'A', 'ASC', 'D', 'DESC', ''),
116 NVL(TRIP_STOP_DATE_PRIORITY, 999999999),
117 DECODE(TRIP_STOP_DATE_SORT, 'A', 'ASC', 'D', 'DESC', '')
118 FROM WSH_PICK_SEQUENCE_RULES
119 WHERE PICK_SEQUENCE_RULE_ID = v_psr_id
120 AND SYSDATE BETWEEN TRUNC(NVL(START_DATE_ACTIVE, SYSDATE)) AND
121 NVL(END_DATE_ACTIVE, TRUNC(SYSDATE) + 1);
122
123 l_pick_seq_rule_name VARCHAR2(30);
124 l_invoice_value_priority NUMBER;
125 l_order_id_priority NUMBER;
126 l_schedule_date_priority NUMBER;
127 l_trip_stop_date_priority NUMBER;
128 l_shipment_pri_priority NUMBER;
129 l_invoice_value_sort VARCHAR2(4);
130 l_order_id_sort VARCHAR2(4);
131 l_schedule_date_sort VARCHAR2(4);
132 l_trip_stop_date_sort VARCHAR2(4);
133 l_shipment_pri_sort VARCHAR2(4);
134 i NUMBER;
135 j NUMBER;
136 l_temp_psr psrTyp;
137 l_ordered_psr psrtabtyp;
138 BEGIN
139 x_api_status := fnd_api.g_ret_sts_success;
140
141 IF p_pick_seq_rule_id IS NULL THEN
142 FOR i IN 1 .. g_total_pick_criteria LOOP
143 l_ordered_psr(i).attribute_name := 'TEMP';
144 l_ordered_psr(i).priority := 999999999;
145 l_ordered_psr(i).sort_order := 'ASC';
146 END LOOP;
147
148 --ASSIGN ANY VALUE
149 x_order_id_sort := 'ASC';
150 x_INVOICE_VALUE_SORT := 'ASC';
151 x_SCHEDULE_DATE_SORT := 'ASC';
152 x_trip_stop_date_sort := 'ASC';
153 x_SHIPMENT_PRI_SORT := 'ASC';
154
155 ELSE -- means p_pick_seq_rule_id is not null
156
157
158 -- fetch pick sequence rule parameters
159 OPEN pick_seq_rule(p_pick_seq_rule_id);
160 LOOP
161 FETCH pick_seq_rule
162 INTO l_pick_seq_rule_name, L_ORDER_ID_PRIORITY, x_ORDER_ID_SORT,
163 L_INVOICE_VALUE_PRIORITY, x_INVOICE_VALUE_SORT,
164 L_SCHEDULE_DATE_PRIORITY, x_SCHEDULE_DATE_SORT,
165 L_TRIP_STOP_DATE_PRIORITY,
166 x_TRIP_STOP_DATE_SORT, L_SHIPMENT_PRI_PRIORITY, x_SHIPMENT_PRI_SORT;
167 EXIT WHEN pick_seq_rule%notfound;
168 END LOOP;
169 CLOSE pick_seq_rule;
170
171 -- initialize the pick sequence rule parameters
172 i := 1;
173
174 l_ordered_psr(i).attribute_name := 'ORDER_NUMBER';
175 l_ordered_psr(i).priority := l_order_id_priority;
176 l_ordered_psr(i).sort_order := x_order_id_sort;
177 i := i + 1;
178
179 l_ordered_psr(i).attribute_name := 'SHIPMENT_PRIORITY';
180 l_ordered_psr(i).priority := l_shipment_pri_priority;
181 l_ordered_psr(i).sort_order := x_shipment_pri_sort;
182 i := i + 1;
183
184 l_ordered_psr(i).attribute_name := 'INVOICE_VALUE';
185 l_ordered_psr(i).priority := l_invoice_value_priority;
186 l_ordered_psr(i).sort_order := x_invoice_value_sort;
187 i := i + 1;
188
189 l_ordered_psr(i).attribute_name := 'SCHEDULE_DATE';
190 l_ordered_psr(i).priority := l_schedule_date_priority;
191 l_ordered_psr(i).sort_order := x_schedule_date_sort;
192 i := i + 1;
193
194 l_ordered_psr(i).attribute_name := 'TRIP_STOP_DATE';
195 l_ordered_psr(i).priority := l_trip_stop_date_priority;
196 l_ordered_psr(i).sort_order := x_trip_stop_date_sort;
197 i := i + 1;
198
199 -- sort the table for pick sequence rule according to priority
200 FOR i IN 1 .. g_total_pick_criteria LOOP
201 FOR j IN i + 1 .. g_total_pick_criteria LOOP
202 IF (l_ordered_psr(j).priority < l_ordered_psr(i).priority) THEN
203 l_temp_psr := l_ordered_psr(j);
204 l_ordered_psr(j) := l_ordered_psr(i);
205 l_ordered_psr(i) := l_temp_psr;
206 END IF;
207 END LOOP;
208 END LOOP;
209 END IF; -- for p_pick_seq_rule_id is null
210
211 x_ordered_psr := l_ordered_psr;
212 x_api_status := FND_API.G_RET_STS_SUCCESS;
213
214 EXCEPTION
215 --
216 WHEN OTHERS THEN
217 --
218 x_api_status := fnd_api.g_ret_sts_unexp_error;
219 --
220 IF pick_seq_rule%ISOPEN THEN
221 CLOSE pick_seq_rule;
222 END IF;
223 IF l_debug = 1 THEN
224 print_debug('Error in Init_Rules: ' || sqlcode || ', ' || sqlerrm);
225 END IF;
226
227 END Init_Rules;
228
229
230
231 PROCEDURE Get_Source_Sub_Dest_Loc_Info(p_Org_id IN NUMBER,
232 p_Item_id IN NUMBER,
233 p_Picking_Sub IN VARCHAR2,
234 x_source_sub OUT NOCOPY VARCHAR2,
235 x_src_pick_uom OUT NOCOPY VARCHAR2,
236 x_MAX_MINMAX_QUANTITY OUT NOCOPY NUMBER,
237 x_fixed_lot_multiple OUT NOCOPY NUMBER,
238 x_return_status OUT NOCOPY VARCHAR2)
239 IS
240
241 -- Get the source sub for destination location for the replenishment move order
242
243 CURSOR c_get_source_sub IS
244 select MISI.SOURCE_SUBINVENTORY, MSISR.pick_uom_code, Nvl(MISI.max_minmax_quantity,0), NVL(MISI.FIXED_LOT_MULTIPLE, -1)
245 FROM MTL_ITEM_SUB_INVENTORIES MISI,
246 MTL_SECONDARY_INVENTORIES msi,
247 MTL_SECONDARY_INVENTORIES MSISR
248 WHERE MISI.organization_id = p_Org_id
249 AND MISI.SECONDARY_INVENTORY = MSI.SECONDARY_INVENTORY_NAME
250 AND MISI.ORGANIZATION_ID = MSI.ORGANIZATION_ID
251 and MISI.INVENTORY_ITEM_ID = p_Item_id
252 and MISI.source_type = 3 --(for Subinventory)
253 AND MISI.source_organization_id = p_Org_id
254 and MISI.SECONDARY_INVENTORY = p_picking_sub
255 and MSISR.SECONDARY_INVENTORY_NAME = MISI.SOURCE_SUBINVENTORY
256 AND MSISR.ORGANIZATION_ID = MISI.ORGANIZATION_ID
257 order by MSI.picking_order;
258
259 -- Destination locator from Item+Sub Form will NOT be stamped on the REPL MO
260 -- So that rules engine can allocate destination locator of the
261 -- IDENTIFIED sub based on available capacity
262
263 L_INDEX NUMBER;
264 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
265
266 BEGIN
267 x_return_status := fnd_api.g_ret_sts_success;
268
269 -- Get the highest priority subinventory
270 L_INDEX := 0;
271 OPEN c_get_source_sub;
272 LOOP
273 FETCH c_get_source_sub
274 into x_source_sub, x_src_pick_uom, x_max_minmax_quantity, x_fixed_lot_multiple;
275 EXIT WHEN c_get_source_sub%NOTFOUND;
276 L_INDEX := L_INDEX + 1;
277 EXIT WHEN L_INDEX = 1;
278 END LOOP;
279 CLOSE c_get_source_sub;
280
281 IF l_index = 0 THEN -- means no record found
282 x_source_sub := NULL;
283 x_src_pick_uom := NULL;
284 x_max_minmax_quantity := 0;
285 x_fixed_lot_multiple := -1;
286 END IF;
287
288
289 IF l_debug = 1 THEN
290 print_debug('Return values from API Get_Source_Sub_Dest_Loc_Info' );
291 print_debug('l_index :' || l_index);
292 print_debug('x_source_sub :' || x_source_sub );
293 print_debug('x_src_pick_uom :' || x_src_pick_uom );
294 print_debug('x_fixed_lot_multiple :' || x_fixed_lot_multiple);
295 print_debug('x_MAX_MINMAX_QUANTITY :' || x_MAX_MINMAX_QUANTITY);
296 END IF;
297
298
299 x_return_status := FND_API.G_RET_STS_SUCCESS;
300
301 EXCEPTION
302 WHEN OTHERS THEN
303 IF l_debug = 1 THEN
304 print_debug('Error Get_Source_Sub_loc_Info: ' || sqlcode || ',' || sqlerrm);
305 END IF;
306
307 IF c_get_source_sub%ISOPEN THEN
308 CLOSE c_get_source_sub;
309 END IF;
310
311 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
312
313 END Get_Source_Sub_Dest_Loc_Info;
314
315
316
317 --Updates the replenishment_status of single passed delivery_detail_id
318 -- If p_repl_status = 'R' marks it RR
319 -- If p_repl_status = 'C' marks it RC
320 -- If p_repl_status = NULL - Reverts WDD to original status (Ready to release / backorder)
321 --
322 PROCEDURE update_wdd_repl_status (p_deliv_detail_id IN NUMBER
323 , p_repl_status IN VARCHAR2
324 , p_deliv_qty IN NUMBER DEFAULT NULL
325 , x_return_status OUT NOCOPY VARCHAR2
326 )
327 IS
328
329 l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
330
331 l_detail_info_tab WSH_INTERFACE_EXT_GRP.delivery_details_Attr_tbl_Type;
332 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
333 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
334
335 l_msg_count NUMBER;
336 l_msg_data VARCHAR2(1000);
337 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
338
339 -- for backordering
340 l_out_rows WSH_UTIL_CORE.ID_TAB_TYPE;
341 l_backorder_deliv_tab WSH_UTIL_CORE.ID_TAB_TYPE;
342 l_backorder_qty_tab WSH_UTIL_CORE.ID_TAB_TYPE;
343 l_dummy_table WSH_UTIL_CORE.ID_TAB_TYPE;
344 BEGIN
345
346 IF (l_debug = 1) THEN
347 print_debug('Updating Repl status of delivery_detail :'||p_deliv_detail_id
348 ||' To Status :'||p_repl_status);
349 END IF;
350
351 l_detail_info_tab.DELETE;
352 l_in_rec := NULL;
353
354
355 IF p_repl_status IS NOT NULL
356 AND p_repl_status <> FND_API.G_MISS_CHAR THEN -- Added for bug 16197390
357 -- call WSH to just update the replenishment status
358
359 l_detail_info_tab(1).delivery_detail_id := p_deliv_detail_id;
360 l_detail_info_tab(1).replenishment_status := p_repl_status ;
361 l_in_rec.caller := 'WMS_REP';
362 l_in_rec.action_code := 'UPDATE';
363
364 WSH_INTERFACE_EXT_GRP.Create_Update_Delivery_Detail
365 (p_api_version_number => 1.0,
366 p_init_msg_list => fnd_api.g_false,
367 p_commit => fnd_api.g_false,
368 x_return_status => l_return_status,
369 x_msg_count => l_msg_count,
370 x_msg_data => l_msg_data,
371 p_detail_info_tab => l_detail_info_tab,
372 p_in_rec => l_in_rec,
373 x_out_rec => l_out_rec
374 );
375
376 IF (l_debug = 1) THEN
377 print_debug('Status after updating the Repl status '||l_return_status);
378 END IF;
379
380 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
381 IF (l_debug = 1) THEN
382 print_debug('Error returned from Create_Update_Delivery_Detail IN api update_wdd_repl_status');
383 END IF;
384 RAISE FND_API.G_EXC_ERROR;
385 ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
386 IF (l_debug = 1) THEN
387 print_debug('Unexpected errror from Create_Update_Delivery_Detail IN api update_wdd_repl_status');
388 END IF;
389 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
390 END IF;
391
392 ELSE -- p_repl_status IS NULL
393
394 -- This gets called from INVTOTRL.pld->clear_replenishment_status() procedure.
395
396 -- We need to explicitely backorder delivery detail
397 -- be calling api WSH_SHIP_CONFIRM_ACTIONS2.backorder
398
399 -- While pick release process WSH does not backorder all those
400 -- delivery detail lines that can not be fulfilled at that time(once the INV
401 -- returns 'replenishment_status = 'R'). Rather WSH
402 -- marks wdd.replenishemnt_status = 'R' and released_status = 'B'.
403 -- This is just pseudo backorder. We actually need to backorder here explicitely.
404 IF (l_debug = 1) THEN
405 print_debug('Calling Shipping API to backorder related WDD lines');
406 END IF;
407 l_backorder_deliv_tab(1) := p_deliv_detail_id;
408 l_backorder_qty_tab(1) := p_deliv_qty ;
409 /* no of records in l_backorder_deliv_tab should be equal to
410 no of records in p_overpick_qtys 14014540*/
411 l_dummy_table(1) := NULL; -- 14014540
412
413 WSH_SHIP_CONFIRM_ACTIONS2.backorder
414 (
415 p_detail_ids => l_backorder_deliv_tab,
416 p_bo_qtys => l_backorder_qty_tab,
417 p_req_qtys => l_backorder_qty_tab,
418 p_bo_qtys2 => l_dummy_table,
419 p_overpick_qtys => l_dummy_table,
420 p_overpick_qtys2 => l_dummy_table,
421 p_bo_mode => 'UNRESERVE',
422 p_bo_source => 'PICK',
423 x_out_rows => l_out_rows,
424 x_return_status => l_return_status
425 );
426 IF (l_debug = 1) THEN
427 print_debug('WSH_SHIP_CONFIRM_ACTIONS2.backorder returned STATUS :'||l_return_status);
428 END IF;
429
430 END IF;
431
432 x_return_status := l_return_status ;
433
434 EXCEPTION
435 WHEN OTHERS THEN
436 IF l_debug = 1 THEN
437 print_debug('Error update_wdd_repl_status: ' || sqlcode || ',' || sqlerrm);
438 END IF;
439 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
440
441 END update_wdd_repl_status;
442
443
444
445
446 PROCEDURE Revert_ALL_WDD_dynamic_repl (p_org_id IN NUMBER
447 , p_batch_id IN NUMBER
448 , x_return_status OUT NOCOPY VARCHAR2
449 )
450 IS
451
452 l_deliv_detail_id_tab num_tab;
453
454 l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
455 l_detail_info_tab WSH_INTERFACE_EXT_GRP.delivery_details_Attr_tbl_Type;
456 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
457 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
458 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
459
460 l_msg_count NUMBER;
461 l_msg_data VARCHAR2(1000);
462
463 CURSOR c_rr_marked_wdd IS
464 SELECT delivery_detail_id
465 FROM wsh_delivery_details wdd
466 WHERE wdd.source_code = 'OE'
467 AND wdd.organization_id = p_org_id
468 AND wdd.requested_quantity > 0
469 -- excluding Replenishment Requested status
470 AND wdd.released_status in ('R', 'B') and wdd.replenishment_status = 'R'
471 -- there might not be reservation
472 AND NOT EXISTS
473 (select 1
474 from mtl_reservations mr
475 WHERE MR.DEMAND_SOURCE_LINE_ID = wdd.source_line_id
476 and MR.DEMAND_SOURCE_HEADER_ID =
477 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id)
478 and MR.demand_source_type_id =
479 decode(wdd.source_document_type_id, 10, 8, 2)
480 and MR.SUBINVENTORY_CODE IS NOT NULL --locator is not needed,
481 )-- Exclude detailed RSV
482 AND NOT EXISTS
483 (select wrd.demand_line_detail_id
484 from WMS_REPLENISHMENT_DETAILS wrd
485 where wrd.demand_line_detail_id = wdd.delivery_detail_id
486 and wrd.demand_line_id = wdd.source_line_id
487 and wrd.organization_id = wdd.organization_id
488 AND wrd.organization_id = p_org_id)
489 AND wdd.batch_id = p_batch_id;
490
491 BEGIN
492
493 IF (l_debug = 1) THEN
494 print_debug('Inside API Revert_ALL_WDD_dynamic_repl ....');
495 END IF;
496
497 BEGIN
498
499 OPEN c_rr_marked_wdd;
500 FETCH c_rr_marked_wdd BULK COLLECT INTO l_deliv_detail_id_tab;
501 CLOSE c_rr_marked_wdd;
502
503 EXCEPTION
504 WHEN OTHERS THEN
505 IF (l_debug = 1) THEN
506 print_debug('Exception retrieving item repl records for Dynamic');
507 END IF;
508 l_return_status := fnd_api.g_ret_sts_error;
509 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
510 END;
511
512 l_detail_info_tab.DELETE;
513 IF (l_deliv_detail_id_tab.count>0) THEN --bug#10185153
514 FOR i IN l_deliv_detail_id_tab.FIRST..l_deliv_detail_id_tab.LAST LOOP
515 l_detail_info_tab(i).delivery_detail_id := l_deliv_detail_id_tab(i);
516 -- mark the demand lines for FND_API.g_miss_char replenishment status
517 l_detail_info_tab(i).replenishment_status := FND_API.g_miss_char;
518
519 END LOOP;
520 END IF;
521
522 IF (l_debug = 1) THEN
523 print_debug('REVERT ALL DEMAND DETAIL STATUS to original release status');
524 END IF;
525
526 l_in_rec := NULL;
527 l_in_rec.caller := 'WMS_REP';
528 l_in_rec.action_code := 'UPDATE';
529
530 WSH_INTERFACE_EXT_GRP.Create_Update_Delivery_Detail
531 (p_api_version_number => 1.0,
532 p_init_msg_list => fnd_api.g_false,
533 p_commit => fnd_api.g_false,
534 x_return_status => l_return_status,
535 x_msg_count => l_msg_count,
536 x_msg_data => l_msg_data,
537 p_detail_info_tab => l_detail_info_tab,
538 p_in_rec => l_in_rec,
539 x_out_rec => l_out_rec
540 );
541
542 IF (l_debug = 1) THEN
543 print_debug('AFTER Changing the line status to original release status');
544 END IF;
545
546 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
547 IF (l_debug = 1) THEN
548 print_debug('Error returned from Create_Update_Delivery_Detail IN api Revert_ALL_WDD_dynamic_repl');
549 END IF;
550 RAISE FND_API.G_EXC_ERROR;
551 ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
552 IF (l_debug = 1) THEN
553 print_debug('Unexpected errror from Create_Update_Delivery_Detail api IN Revert_ALL_WDD_dynamic_repl');
554 END IF;
555 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
556 END IF;
557
558 x_return_status := l_return_status ;
559
560 EXCEPTION
561 WHEN OTHERS THEN
562 IF l_debug = 1 THEN
563 print_debug('Error In Revert_ALL_WDD_dynamic_repl: ' || sqlcode || ',' || sqlerrm);
564 END IF;
565 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
566 END revert_all_wdd_dynamic_repl;
567
568
569 PROCEDURE Revert_Consol_item_changes ( p_repl_type IN NUMBER
570 , p_demand_type_id IN NUMBER
571 , P_item_id IN NUMBER
572 , p_org_id IN NUMBER
573 , x_return_status OUT NOCOPY VARCHAR2
574 )
575 IS
576
577 l_deliv_detail_id_tab num_tab;
578 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
579 l_detail_info_tab WSH_INTERFACE_EXT_GRP.delivery_details_Attr_tbl_Type;
580 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
581 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
582
583 l_item_id NUMBER;
584 l_org_id NUMBER;
585
586 l_msg_count NUMBER;
587 l_msg_data VARCHAR2(1000);
588
589 l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
590
591 CURSOR c_demand_for_items IS
592 SELECT demand_line_detail_id
593 FROM wms_repl_demand_gtmp
594 WHERE inventory_item_id = p_item_id
595 AND ORGANIZATION_ID = p_org_id
596 AND repl_level = 1
597 AND demand_type_id <> 4;
598 BEGIN
599
600 IF (l_debug = 1) THEN
601 print_debug('Inside API Revert_Consol_item_changes .......');
602 END IF;
603
604 -- if repl_type 2 and demand_type_id <> 4 then revert that WDD to original status
605 IF p_repl_type = g_dynamic_repl AND p_demand_type_id <> 4 THEN
606
607 IF (l_debug = 1) THEN
608 print_debug('Reverting WDD status to original status for consol item');
609 END IF;
610
611 BEGIN
612
613 OPEN c_demand_for_items;
614 FETCH c_demand_for_items BULK COLLECT INTO l_deliv_detail_id_tab;
615 CLOSE c_demand_for_items;
616
617 EXCEPTION
618 WHEN OTHERS THEN
619 IF (l_debug = 1) THEN
620 print_debug('Exception retrieving repl records for consol item');
621 END IF;
622 l_return_status := fnd_api.g_ret_sts_error;
623 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
624 END;
625
626 l_detail_info_tab.DELETE;
627 IF (l_deliv_detail_id_tab.count>0) THEN --bug#10185153
628 FOR i IN l_deliv_detail_id_tab.FIRST..l_deliv_detail_id_tab.LAST LOOP
629 l_detail_info_tab(i).delivery_detail_id := l_deliv_detail_id_tab(i);
630 -- mark the demand lines for FND_API.g_miss_char replenishment status
631 l_detail_info_tab(i).replenishment_status := FND_API.g_miss_char;
632 END LOOP;
633 END IF;
634
635 l_in_rec := NULL;
636 l_in_rec.caller := 'WMS_REP';
637 l_in_rec.action_code := 'UPDATE';
638
639 WSH_INTERFACE_EXT_GRP.Create_Update_Delivery_Detail
640 (p_api_version_number => 1.0,
641 p_init_msg_list => fnd_api.g_false,
642 p_commit => fnd_api.g_false,
643 x_return_status => l_return_status,
644 x_msg_count => l_msg_count,
645 x_msg_data => l_msg_data,
646 p_detail_info_tab => l_detail_info_tab,
647 p_in_rec => l_in_rec,
648 x_out_rec => l_out_rec
649 );
650
651 IF (l_debug = 1) THEN
652 print_debug('AFTER Changing the line status to original release status');
653 END IF;
654
655 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
656 IF (l_debug = 1) THEN
657 print_debug('Error returned from Create_Update_Delivery_Detail IN api revert_consol_item_changes');
658 END IF;
659 RAISE FND_API.G_EXC_ERROR;
660 ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
661 IF (l_debug = 1) THEN
662 print_debug('Unexpected errror from Create_Update_Delivery_Detail api IN revert_consol_item_changes');
663 END IF;
664 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
665 END IF;
666
667 END IF; -- for IF p_repl_type = g_dynamic_repl AND p_demand_type_id <> 4
668
669
670 -- remove all entries for that item from gtmp
671 DELETE FROM wms_repl_demand_gtmp
672 WHERE inventory_item_id = p_item_id
673 AND ORGANIZATION_ID = p_org_id;
674
675 x_return_status := l_return_status ;
676
677 EXCEPTION
678 WHEN OTHERS THEN
679 IF l_debug = 1 THEN
680 print_debug('Error in Revert_Consol_item_changes: ' || sqlcode || ',' || sqlerrm);
681 END IF;
682 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
683 END revert_consol_item_changes;
684
685
686
687
688 PROCEDURE Backorder_wdd_for_repl( x_return_status OUT NOCOPY VARCHAR2
689 )
690 IS
691 l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
692 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
693 l_out_rows WSH_UTIL_CORE.ID_TAB_TYPE;
694 BEGIN
695
696 IF (l_debug = 1) THEN
697 print_debug( 'Calling Shipping API to backorder all unment demand lines during Replenishment');
698 END IF;
699 -- Bulk processing of records here
700 --these demand lines need fresh backordering
701
702 WSH_SHIP_CONFIRM_ACTIONS2.backorder
703 (
704 p_detail_ids => G_backorder_deliv_tab,
705 p_bo_qtys => G_backorder_qty_tab,
706 p_req_qtys => G_backorder_qty_tab,
707 p_bo_qtys2 => G_dummy_table,
708 p_overpick_qtys => G_dummy_table,
709 p_overpick_qtys2 => G_dummy_table,
710 p_bo_mode => 'UNRESERVE',
711 p_bo_source => 'PICK',
712 x_out_rows => l_out_rows,
713 x_return_status => l_return_status
714 );
715
716 IF (l_debug = 1) THEN
717 print_debug( 'After call to Backorder API Return Status :'||l_return_status);
718 END IF;
719
720 IF l_return_status <> fnd_api.g_ret_sts_success THEN
721 RAISE fnd_api.g_exc_unexpected_error;
722 END IF;
723
724 --Delete all entries in the pl/sql table
725 G_backorder_deliv_tab.DELETE;
726 G_backorder_qty_tab.DELETE;
727 G_dummy_table.DELETE;
728
729 x_return_status := l_return_status;
730 EXCEPTION
731 WHEN OTHERS THEN
732 IF l_debug = 1 THEN
733 print_debug('Error in Backorder_wdd_for_repl: ' || sqlcode || ',' || sqlerrm);
734 END IF;
735 --Delete all entries in the pl/sql table
736 G_backorder_deliv_tab.DELETE;
737 G_backorder_qty_tab.DELETE;
738 G_dummy_table.DELETE;
739 x_return_status := FND_API.G_RET_STS_UNEXP_ERROR;
740 END Backorder_wdd_for_repl ;
741
742
743
744
745 PROCEDURE ADJUST_ATR_FOR_ITEM (p_repl_level IN NUMBER
746 , p_repl_type IN NUMBER
747 , x_consol_item_repl_tbl IN OUT NOCOPY CONSOL_ITEM_REPL_TBL
748 , x_return_status OUT NOCOPY VARCHAR2
749 )
750 IS
751
752
753 l_qoh NUMBER;
754 l_rqoh NUMBER;
755 l_qr NUMBER;
756 l_qs NUMBER;
757 l_att NUMBER;
758 l_atr NUMBER;
759 l_msg_count NUMBER;
760 l_msg_data VARCHAR2(1000);
761 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
762
763 l_is_revision_ctrl BOOLEAN;
764 l_is_lot_ctrl BOOLEAN;
765 l_is_serial_ctrl BOOLEAN;
766
767 l_open_mo_qty NUMBER;
768 l_item_id NUMBER;
769 l_org_id NUMBER;
770 l_demand_line_detail_id NUMBER;
771 l_quantity NUMBER;
772 l_uom_code VARCHAR2(3);
773 l_prim_repl_qty NUMBER;
774 l_released_status VARCHAR2(1);
775 cnt NUMBER;
776 l_cnt NUMBER; --BUG10149131/BUG10131943
777 l_qty_in_repl_uom NUMBER;
778 l_REPL_UOM_CODE VARCHAR2(3);
779
780 l_demand_header_id NUMBER;
781 l_demand_line_id NUMBER;
782 l_demand_type_id NUMBER;
783 l_new_qty_in_repl_uom NUMBER;
784
785 l_expected_ship_date DATE;
786 l_repl_to_subinventory_code VARCHAR2(10);
787 l_repl_status VARCHAR2(1);
788
789 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
790 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
791
792 l_detail_id_tab WSH_UTIL_CORE.id_tab_type;
793 l_action_prms WSH_GLBL_VAR_STRCT_GRP.dd_action_parameters_rec_type;
794 l_action_out_rec WSH_GLBL_VAR_STRCT_GRP.dd_action_out_rec_type;
795
796 l_return_status VARCHAR2(1) := fnd_api.g_ret_sts_success;
797 l_split_wdd_id NUMBER;
798
799 l_dyn_bkord_dd_id_tab num_tab;
800
801 l_psh_cnt NUMBER;
802 l_push_bkord_dd_id_tab num_tab;
803 l_rsvd_demand_qty NUMBER;
804 l_gtmp_demand_qty NUMBER;
805 l_rsv_accounted_qty NUMBER;
806 l_other_wdd_qty NUMBER;
807 l_temp_value NUMBER;
808 l_rsvd_demand_line_qty NUMBER; --BUG14504260
809
810 CURSOR c_item_demand_lines IS
811 SELECT demand_header_id,
812 demand_line_id,
813 demand_line_detail_id,
814 demand_type_id,
815 Quantity,
816 Uom_code,
817 quantity_in_repl_uom,
818 REPL_UOM_code,
819 Expected_ship_date,
820 Repl_To_Subinventory_code,
821 repl_status,
822 RELEASED_STATUS
823 FROM wms_repl_demand_gtmp
824 WHERE inventory_item_id = l_item_id
825 AND organization_id = l_org_id
826 AND repl_level = P_REPL_LEVEL
827 ORDER BY repl_sequence_id;
828
829 BEGIN
830
831 IF (l_debug = 1) THEN
832 print_debug('Inside API ADJUST_atr_for_item.....');
833 END IF ;
834
835 cnt := g_backorder_deliv_tab.count; --BUG10149131/BUG13491877 this is to store counter for global variable to store all WDD's to be backordered. initialise.
836
837
838 IF (x_consol_item_repl_tbl.count>0) THEN --bug#10185153
839 FOR i IN x_consol_item_repl_tbl.FIRST.. x_consol_item_repl_tbl.LAST LOOP
840
841 l_item_id := x_consol_item_repl_tbl(i).item_id;
842 l_org_id := x_consol_item_repl_tbl(i).organization_id;
843
844 -- Get all item details
845 IF inv_cache.set_item_rec(L_ORG_ID, L_item_id) THEN
846
847 IF inv_cache.item_rec.revision_qty_control_code = 2 THEN
848 l_is_revision_ctrl := TRUE;
849 ELSE
850 l_is_revision_ctrl := FALSE;
851 END IF;
852
853 IF inv_cache.item_rec.lot_control_code = 2 THEN
854 l_is_lot_ctrl := TRUE;
855 ELSE
856 l_is_lot_ctrl := FALSE;
857 END IF;
858
859 IF inv_cache.item_rec.serial_number_control_code NOT IN (1,6) THEN
860 l_is_serial_ctrl := FALSE;
861 ELSE
862 l_is_serial_ctrl := TRUE;
863 END IF;
864
865 ELSE
866
867 IF (l_debug = 1) THEN
868 print_debug('Error: Item detail not found');
869 END IF ;
870
871 RAISE no_data_found;
872 END IF; -- for inv_cache.set_item_rec
873
874
875 --uom conversio would already be defined, otherwise it will not come here
876 -- get the final repl qty in the primary UOM
877 l_prim_repl_qty :=
878 ROUND((x_consol_item_repl_tbl(i).total_demand_qty * get_conversion_rate(l_Item_id,
879 x_consol_item_repl_tbl(i).repl_uom_code,
880 inv_cache.item_rec.primary_uom_code
881 )),
882 g_conversion_precision);
883
884
885 IF (l_debug = 1) THEN
886 print_debug('Processing for Item :'||l_item_id||
887 ' Total Primary Dmd Qty :'||l_prim_repl_qty);
888 END IF ;
889
890 --Query Quantity Tree
891 inv_quantity_tree_pub.clear_quantity_cache;
892
893 -- Check value passed in this call to QTY Tree
894 inv_quantity_tree_pub.query_quantities
895 (
896 p_api_version_number => 1.0
897 , p_init_msg_lst => fnd_api.g_false
898 , x_return_status => l_return_status
899 , x_msg_count => l_msg_count
900 , x_msg_data => l_msg_data
901 , p_organization_id => L_ORG_ID
902 , p_inventory_item_id => L_item_id
903 , p_tree_mode => inv_quantity_tree_pub.g_transaction_mode
904 , p_is_revision_control => l_is_revision_ctrl
905 , p_is_lot_control => l_is_lot_ctrl
906 , p_is_serial_control => l_is_serial_ctrl
907 , p_demand_source_type_id => -9999 --should not be null
908 , p_demand_source_header_id => -9999 --should not be null
909 , p_demand_source_line_id => -9999
910 , p_revision => NULL
911 , p_lot_number => NULL
912 , p_subinventory_code => NULL
913 , p_locator_id => NULL
914 , p_lot_expiration_date => sysdate --bug#10185153
915 , x_qoh => l_qoh
916 , x_rqoh => l_rqoh
917 , x_qr => l_qr
918 , x_qs => l_qs
919 , x_att => l_att
920 , x_atr => l_atr
921 );
922
923 IF (l_debug = 1) THEN
924 print_debug( 'Return status from QTY TREE:' ||l_return_status);
925 print_debug( '>>>> From Qrt Tree, Org Level atr for Item :'||L_item_id||' is : '||l_atr);
926 END IF;
927
928 IF l_return_status <> fnd_api.g_ret_sts_success THEN
929 l_atr := 0;
930 END IF;
931
932 ----------------------
933 -- Since Qty Tree would have also subttracted qty for current demand
934 -- lines under consideration for which there is existing
935 -- reservation as well, I need to add them back
936 -- to see real picture of the atr for demand line under consideration
937
938 ------------------
939 -- Note: one SO demand line can have multiple delivery_details
940 -- Reservation is made at the SO line level and WRDG is at the
941 -- delivery_detail level
942
943 -- Steps:
944 -- 1-Get all the RSV qty for the item+org for ONLY those SO lines
945 -- that are part OF GTMP table= Q1
946 -- 2-Get the SUM OF qty in the GTMP for item+org combination = Q2
947 -- Q3 - represents, For a specific item+Org, SUM OF qty for ALL wdds that are :
948 -- 1- Part of same SO line whose wdds in the GTMP table
949 -- 2- Excludes Wdds in the GTMP table
950 -- 3- WDD.released_status not in (R,N,B,X,C) or already RR
951
952 --R- Ready to Release
953 --N- Not ready to Release
954 --B- Backordered
955 --X- Not applicable
956 --C- Shipped
957 --S- Released to Warehouse
958 --Y- Staged
959
960
961 -- On the so line that can be possible candidate to contribute to reduction OF ATR
962
963 -- Qty that would already have been accounted for in the qty
964 -- tree = MIN(MAX((Q1-Q3), 0),Q2)
965
966 ------------------------
967
968 -- Get Q1
969 -- 13806919 Changed the query(Q1) to get only distinct records from WRDG
970 -- Also changed mr.reservations_quantity to mr.primary_reservation_quantity
971 -- as Q2 and Q3 values are fetched in primary UOM
972
973 SELECT NVL(SUM(mr.primary_reservation_quantity),0)
974 INTO l_rsvd_demand_qty
975 FROM mtl_reservations mr ,
976 (select distinct organization_id, inventory_item_id,
977 demand_line_id, demand_header_id
978 from WMS_REPL_DEMAND_GTMP
979 where inventory_item_id = l_item_id
980 and organization_id = l_org_id
981 and demand_type_id <> 4
982 and repl_level = nvl(p_repl_level,1)) wrdg_v
983 WHERE mr.organization_id = wrdg_v.organization_id
984 AND mr.inventory_item_id = wrdg_v.inventory_item_id
985 AND MR.DEMAND_SOURCE_LINE_ID = wrdg_v.DEMAND_line_ID
986 AND MR.DEMAND_SOURCE_HEADER_ID = wrdg_v.DEMAND_HEADER_ID;
987
988
989 -- Get Q2
990 SELECT Nvl(sum(wrdg.QUANTITY),0) INTO l_gtmp_demand_qty
991 from WMS_REPL_DEMAND_GTMP WRDG
992 WHERE Wrdg.INVENTORY_ITEM_ID = l_item_id
993 and wrdg.ORGANIZATION_ID = L_ORG_ID
994 and wrdg.demand_type_id <> 4
995 and wrdg.repl_level = nvl(p_repl_level, 1);
996
997 -- Get Q3
998 SELECT Nvl(SUM(wdd.requested_quantity),0) INTO l_other_wdd_qty
999 FROM wsh_delivery_details wdd
1000 WHERE wdd.organization_id = l_org_id
1001 AND wdd.inventory_item_id = l_item_id
1002 AND((wdd.released_status NOT IN ('R','N','B','X','C') AND wdd.replenishment_status IS NULL)
1003 OR (wdd.released_status = 'B' AND wdd.replenishment_status IS NOT NULL))
1004 AND NOT EXISTS
1005 (SELECT 1
1006 FROM wms_repl_demand_gtmp wrdg
1007 WHERE wrdg.organization_id = wdd.organization_id
1008 AND wrdg.inventory_item_id = wdd.inventory_item_id
1009 AND wrdg.demand_line_detail_id = wdd.delivery_detail_id
1010 AND wrdg.demand_header_id = inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id)
1011 AND wrdg.demand_line_id = wdd.source_line_id
1012 )
1013 AND inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) IN
1014 (
1015 SELECT DISTINCT demand_header_id FROM wms_repl_demand_gtmp wrdg1
1016 WHERE WRDG1.organization_id = l_org_id
1017 AND WRDG1.inventory_item_id = l_item_id
1018 );
1019
1020
1021 IF (l_debug = 1) THEN
1022 print_debug( ' l_rsvd_demand_qty:'||l_rsvd_demand_qty);
1023 print_debug( ' l_gtmp_demand_qty:'||l_gtmp_demand_qty);
1024 print_debug( ' l_other_wdd_qty :'||l_other_wdd_qty);
1025
1026 END IF;
1027
1028 --l_rsv_accounted_qty = MIN(MAX((Q1-Q3), 0),Q2)
1029 --l_rsv_accounted_qty := MIN(MAX((l_rsvd_demand_qty-l_other_wdd_qty ), 0),l_gtmp_demand_qty) ;
1030
1031
1032 IF (l_rsvd_demand_qty-l_other_wdd_qty ) >= 0 THEN
1033 l_temp_value := (l_rsvd_demand_qty-l_other_wdd_qty );
1034 ELSE
1035 l_temp_value := 0;
1036 END IF;
1037
1038
1039 IF l_temp_value >= l_gtmp_demand_qty THEN
1040 l_rsv_accounted_qty :=l_gtmp_demand_qty;
1041 ELSE
1042 l_rsv_accounted_qty :=l_temp_value;
1043 END IF;
1044
1045
1046 IF (l_debug = 1) THEN
1047 print_debug( 'Already Rsvd QTY AT ORG for demand lines for current item :'||l_rsv_accounted_qty);
1048 END IF;
1049
1050
1051 -- Adjust the l_atr with "EFFECTIVE QTY" on open MO whose source_sub is
1052 -- sub under consideration. These MO should NOT be part of WRD becs
1053 -- those part of WRD would already have been accounted in the RSV
1054 -- Problematic are those for which MO is created but not allocated and
1055 -- NOT tracked IN wrd AND whose source sub is Current Sub under consideration
1056 -- So any untracked repl MO that is going out of the current sub should
1057 -- be subtracted FROM l_org_atr for item for the reason of directionality (Pallet > CASE > Each)
1058 -- becs material move from higher configuration to lower configuration
1059 -- "EFFECTIVE QTY" = (mtrl.quantity - (Nvl(mtrl.quantity_detailed,0) + Nvl(mtrl.quantity_delivered,0)))
1060
1061 BEGIN
1062 SELECT SUM((mtrl.quantity - (Nvl(mtrl.quantity_detailed,0) +
1063 Nvl(mtrl.quantity_delivered,0)))) INTO l_open_mo_qty
1064 FROM mtl_txn_request_lines mtrl,
1065 Mtl_txn_request_headers mtrh
1066 WHERE mtrl.header_id = mtrh.header_id
1067 AND mtrl.organization_id = mtrh.organization_id
1068 AND mtrl.organization_id = L_ORG_ID
1069 AND mtrl.inventory_item_id = L_item_id
1070 AND mtrl.organization_id in (select organization_id from mtl_parameters where wms_enabled_flag = 'Y')
1071 AND MTRH.move_order_type = 2
1072 and mtrl.line_status in (3,7) -- only approved and pre-approved
1073 and mtrl.transaction_type_id = 64
1074 and mtrl.transaction_source_type_id = 4
1075 and mtrl.from_SUBINVENTORY_CODE = x_consol_item_repl_tbl(i).repl_to_subinventory_code
1076 GROUP BY mtrl.inventory_item_id;
1077 EXCEPTION
1078 WHEN no_data_found THEN
1079 l_open_mo_qty := 0;
1080 END;
1081
1082 l_atr := l_atr + Nvl(l_rsv_accounted_qty,0) - Nvl(l_open_mo_qty,0);
1083
1084 IF (l_debug = 1) THEN
1085 print_debug( 'Total effective qty for Untracked repl MO going out of FP Sub:' ||l_open_mo_qty);
1086 print_debug( 'Final Org Level Effective ATR for Item in GTMP table:'||l_atr);
1087 END IF;
1088
1089 --========================================
1090 -- Now perform these 3 things.
1091 --1- Do calculation about qty
1092 --2- Remove unmet entery from the GTMP table
1093 --3- For the Item, Adjust the QTY in the CONSOLIDATED TABLE
1094 --4- Backorder the unmet demand line qty
1095 --========================================
1096
1097 --1- Do calculation about qty
1098 IF l_atr > l_prim_repl_qty THEN
1099 -- do nothing
1100 --CONTINUE;
1101 GOTO skip_item;
1102
1103 ELSE -- L_ATR IS NOT GOOD ENOUGH to handle all demands
1104 l_prim_repl_qty := 0; -- Reset AND re-add in loop for each item
1105 l_psh_cnt := 0;
1106 l_cnt := 0; --BUG10149131/BUG10131943
1107 -- l_dyn_bkord_dd_id_tab.DELETE;
1108 -- l_push_bkord_dd_id_tab.DELETE;
1109
1110 --We will reduce this and later we will add the demand line specific reserved qty.
1111 l_atr := l_atr - Nvl(l_rsv_accounted_qty,0) ; --BUG14504260
1112
1113
1114 OPEN c_item_demand_lines;
1115 LOOP
1116 FETCH c_item_demand_lines INTO l_demand_header_id,
1117 l_demand_line_id,
1118 l_demand_line_detail_id,
1119 l_demand_type_id,
1120 l_Quantity,
1121 l_Uom_code,
1122 l_qty_in_repl_uom,
1123 l_REPL_UOM_code,
1124 l_Expected_ship_date,
1125 l_Repl_To_Subinventory_code,
1126 l_repl_status,
1127 l_released_status;
1128
1129 EXIT WHEN c_item_demand_lines%notfound;
1130
1131 SELECT NVL(SUM(mr.primary_reservation_quantity),0)
1132 INTO l_rsvd_demand_line_qty
1133 FROM mtl_reservations mr
1134 WHERE mr.organization_id =l_org_id
1135 AND mr.inventory_item_id =l_item_id
1136 AND MR.DEMAND_SOURCE_LINE_ID = l_demand_line_id
1137 AND MR.DEMAND_SOURCE_HEADER_ID = l_demand_header_id;
1138
1139 l_atr := l_atr + l_rsvd_demand_line_qty ; --BUG14504260
1140
1141 IF (l_debug = 1) THEN
1142 print_debug( 'l_atr after considering current order demand'||l_atr);
1143 END IF;
1144
1145 IF l_atr >= l_quantity THEN
1146 -- once l_atr becomes negative it will always reamin negative
1147 -- and code will always go TO the ELSE section afterwards
1148 -- Final primary qty will be set here for this item
1149 l_atr := l_atr - l_quantity;
1150 l_prim_repl_qty := l_prim_repl_qty +l_quantity;
1151
1152 ELSE -- means l_atr < l_quantity; remaining l_atr is not enough for l_quantity
1153
1154 IF l_atr <> 0 THEN -- so that it does not call to split again FOR an item
1155 IF (l_debug = 1) THEN
1156 print_debug( 'Remaining l_atr is not enough for CURRENT demand line,....splitting the WDD ');
1157 END IF;
1158
1159 -- 1-Call Shipping API to split the WDD with (l_quantity - l_atr)
1160 -- Shipping will update current WDD with qty = l_atr
1161 -- and create a new WDD with qty = (l_quantity - l_atr)
1162
1163 -- 2-Split the Qty in the GTMP :UPDATE current demand RECORD with qty = l_atr
1164 -- We do NOT need to insert the new record in GTMP with qty = (l_quantity - l_atr)
1165 -- since we are going to delete downstream from GTMP for ALL unmet demand lines
1166
1167 -- -3-Adjust l_prim_repl_qty := l_prim_repl_qty +l_atr;
1168 -- -4- Set l_atr = 0
1169
1170 l_detail_id_tab.DELETE;
1171 l_action_prms := NULL;
1172 l_detail_id_tab(1) := l_demand_line_detail_id;
1173 -- Caller needs to be WSH_PUB in order for shipping to allow this action
1174 l_action_prms.caller := 'WSH_PUB';
1175 l_action_prms.action_code := 'SPLIT-LINE';
1176 l_action_prms.split_quantity := (l_quantity - l_atr);
1177
1178 WSH_INTERFACE_GRP.Delivery_Detail_Action
1179 (p_api_version_number => 1.0,
1180 p_init_msg_list => fnd_api.g_false,
1181 p_commit => fnd_api.g_false,
1182 x_return_status => l_return_status,
1183 x_msg_count => l_msg_count,
1184 x_msg_data => l_msg_data,
1185 p_detail_id_tab => l_detail_id_tab,
1186 p_action_prms => l_action_prms,
1187 x_action_out_rec => l_action_out_rec
1188 );
1189
1190 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1191 IF (l_debug = 1) THEN
1192 print_debug( 'Error returned from Split ADJUST_ATR_FOR_ITEM API..skip this demand');
1193 END IF;
1194 -- skip this demand line
1195 GOTO next_dmd_rec;
1196 ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1197 IF (l_debug = 1) THEN
1198 print_debug( 'Unexpected errror from Split ADJUST_ATR_FOR_ITEM API..skip this demand');
1199 END IF;
1200 -- skip this demand line
1201 GOTO next_dmd_rec;
1202 END IF;
1203
1204 l_split_wdd_id := l_action_out_rec.result_id_tab(l_action_out_rec.result_id_tab.FIRST);
1205
1206 l_new_qty_in_repl_uom := ROUND((l_atr * get_conversion_rate(l_item_id,
1207 inv_cache.item_rec.primary_uom_code,
1208 x_consol_item_repl_tbl(i).repl_uom_code )), g_conversion_precision);
1209
1210 -- update the qty in the existing GTMP record
1211 UPDATE wms_repl_demand_gtmp
1212 SET QUANTITY = l_atr,
1213 QUANTITY_IN_REPL_UOM = l_new_qty_in_repl_uom
1214 WHERE demand_line_detail_id = l_demand_line_detail_id;
1215
1216 --reset program parameters for next loop
1217 l_prim_repl_qty := l_prim_repl_qty +l_atr;
1218 l_atr := 0;
1219
1220
1221 --Override l_demand_line_detail_id so that it gets added to
1222 -- the backorder list. released status of both dd_id is same
1223 l_demand_line_detail_id := l_split_wdd_id;
1224 END IF; --for l_atr <> 0
1225
1226 -- the code will go in above split case only once to consume
1227 -- all remaining available l_atr. Thereafter, it will only go to following section to add
1228 -- lines to be backordered
1229
1230 -- add to the backorder table to backorder demand AND delete from GTMP
1231 IF p_repl_type = g_push_repl THEN
1232
1233 -- we can call the backorder API for WDD lines that are already backordered
1234 -- Now, Shipping team has made changes and it will honor
1235 -- consolidation of the backordered api feature
1236 -- it does NOT matter whether DD_id was alredy backordered
1237
1238 l_cnt := l_cnt+1; --BUG10131943
1239 cnt := cnt+1;
1240 l_push_bkord_dd_id_tab(l_cnt) := l_demand_line_detail_id; --BUG10131943
1241
1242 g_backorder_deliv_tab(cnt):= l_demand_line_detail_id;
1243 g_backorder_qty_tab(cnt) := l_quantity;
1244 -- since we are backordering entire qty parameters
1245 -- p_bo_qtys AND p_req_qtys will have same value
1246 g_dummy_table(cnt) := 0;
1247
1248
1249 ELSIF p_repl_type = g_dynamic_repl THEN
1250 -- call the backorder API to backorder the delivery_detail
1251 -- add the delivery_detail to the global variable
1252 -- it does NOT matter whether DD_id was already backordered
1253 l_cnt := l_cnt+1; --BUG10149131
1254 cnt := cnt+1;
1255 l_dyn_bkord_dd_id_tab(l_cnt) := l_demand_line_detail_id; --BUG10149131
1256
1257 g_backorder_deliv_tab(cnt):= l_demand_line_detail_id;
1258 g_backorder_qty_tab(cnt) := l_quantity;
1259 -- since we are backordering entire qty parameters
1260 -- p_bo_qtys AND p_req_qtys will have same value
1261 g_dummy_table(cnt) := 0;
1262
1263 END IF;
1264
1265 END IF; -- for IF l_atr >= l_quantity
1266
1267 <<next_dmd_rec>>
1268 IF l_return_status <> 'S' THEN
1269 IF (l_debug = 1) THEN
1270 print_debug( 'Removing the demand from repl consideration :'||l_demand_line_detail_id);
1271 END IF;
1272 -- delete this demand line from the GTMP
1273 -- subtract the qty from the consol record
1274 DELETE FROM wms_repl_demand_gtmp
1275 WHERE demand_line_detail_id = l_demand_line_detail_id;
1276
1277 -- we have not updated the qty l_prim_repl_qty yet
1278 -- so no need to update the consol qty for this item
1279
1280 -- Add here to list of delivery_details to be backordered
1281 cnt := cnt+1;
1282 g_backorder_deliv_tab(cnt):= l_demand_line_detail_id;
1283 g_backorder_qty_tab(cnt) := l_quantity;
1284 -- since we are backordering entire qty parameters
1285 -- p_bo_qtys AND p_req_qtys will have same value
1286 g_dummy_table(cnt) := 0;
1287
1288 END IF; --for IF l_return_status <> 'S'
1289
1290 END LOOP;
1291 CLOSE c_item_demand_lines;
1292 END IF; -- for if l_atr > l_prim_repl_qty
1293
1294 --2- Remove unmet entery from the GTMP table IN bulk
1295 IF p_repl_type = g_push_repl THEN
1296 IF (l_debug = 1) THEN
1297 print_debug( 'PUSH - NUMBER OF lines to be deleted :'||l_push_bkord_dd_id_tab.count);
1298 END IF;
1299
1300 FORALL k IN 1 .. l_push_bkord_dd_id_tab.COUNT
1301 DELETE FROM wms_repl_demand_gtmp
1302 WHERE demand_line_detail_id = l_push_bkord_dd_id_tab(k)
1303 AND inventory_item_id = l_item_id
1304 AND organization_id = L_ORG_ID
1305 AND Nvl(repl_level,1) = p_repl_level;
1306 ELSIF p_repl_type = g_dynamic_repl THEN
1307 IF (l_debug = 1) THEN
1308 print_debug( 'DYNAMIC - NUMBER OF lines to be deleted :'||l_dyn_bkord_dd_id_tab.count);
1309 END IF;
1310
1311 IF (l_dyn_bkord_dd_id_tab.count>0) THEN
1312 FOR k IN l_dyn_bkord_dd_id_tab.FIRST .. l_dyn_bkord_dd_id_tab.LAST LOOP
1313 print_debug( 'AMO - value of K ' || k);
1314 print_debug( 'AMO Debug l_dyn_bkord_dd_id_tab place 1 '||l_dyn_bkord_dd_id_tab(k));
1315
1316 END LOOP;
1317 END IF;
1318
1319 IF (l_debug = 1) THEN
1320 print_debug( 'AMO Debug place 1.5 value i '||i);
1321 print_debug( 'AMO Debug place 2 '||x_consol_item_repl_tbl(i).total_demand_qty );
1322 print_debug( 'AMO Debug place 3 '||x_consol_item_repl_tbl(i).repl_uom_code);
1323 END IF;
1324
1325
1326 FORALL k IN 1 .. l_dyn_bkord_dd_id_tab.COUNT
1327 DELETE FROM wms_repl_demand_gtmp
1328 WHERE demand_line_detail_id = l_dyn_bkord_dd_id_tab(k)
1329 AND inventory_item_id = l_item_id
1330 AND organization_id = L_ORG_ID
1331 AND Nvl(repl_level,1) = p_repl_level;
1332 END IF;
1333
1334
1335 IF (l_debug = 1) THEN
1336 print_debug( 'AMOaa Debug place 1.5 value i '||i);
1337 print_debug( 'AMOaa Debug place 2 '||x_consol_item_repl_tbl(i).total_demand_qty );
1338 print_debug( 'AMOaa Debug place 3 '||x_consol_item_repl_tbl(i).repl_uom_code);
1339 END IF;
1340
1341 --3- For the Item, Adjust the QTY in the CONSOLIDATED TABLE
1342 IF l_prim_repl_qty > 0 THEN
1343 x_consol_item_repl_tbl(i).total_demand_qty :=
1344 ROUND((l_prim_repl_qty * get_conversion_rate(l_item_id,
1345 inv_cache.item_rec.primary_uom_code,
1346 x_consol_item_repl_tbl(i).repl_uom_code
1347 )),
1348 g_conversion_precision);
1349
1350 IF (l_debug = 1) THEN
1351 print_debug( 'After all into account Final total dmd Qty :'||x_consol_item_repl_tbl(i).total_demand_qty);
1352 print_debug( 'In the UOM Code :'||x_consol_item_repl_tbl(i).repl_uom_code);
1353 END IF;
1354
1355 ELSE
1356 IF (l_debug = 1) THEN
1357 print_debug( 'NO Qty available for this item in the ORG....removing FROM Replenishment Consideration');
1358 END IF;
1359 x_consol_item_repl_tbl.DELETE(i);
1360 END IF;
1361
1362
1363
1364 --4- Backorder the unmet demand line qty
1365 -- We do not need to do anything here as we have already added those
1366 -- delivery_details IN the global TABLE that need TO be backordered
1367 -- we call an api WSH_SHIP_CONFIRM_ACTIONS2.backorder()
1368 -- to backorder these delivery at the end of the
1369 -- replenishment process - be it push/stock-up OR pull/dynamic
1370
1371 /* NOT needed
1372
1373 IF p_repl_type = g_push_repl THEN
1374 NULL;
1375 -- To honor the consolidation of the backordered demand lines
1376 -- We need to call the WSH_SHIP_CONFIRM_ACTIONS2.backorder() API
1377 -- at the end of Push replenishment process. Above in the code,
1378 -- We have already stored the delivery_details_ids to be
1379 -- backordered IN the global pacakge variable - g_backorder_deliv_tab
1380
1381 ELSIF p_repl_type = g_dynamic_repl THEN
1382 -- since line is already marked RR, just reverting the line status
1383 -- to its orignal status will make it Backorder
1384 -- Bulk processing of records here
1385
1386 -- FOR dynamic repl,consolidation of the backordered demand lines
1387 -- works fine, even if we call in the middle of the dynamic repl
1388 -- only for the push repl, backorder API needs to be called at
1389 -- end of the push replenishment process.
1390
1391 IF (l_debug = 1) THEN
1392 print_debug( 'Calling Shipping API to revert to original status FOR unmet demand lines');
1393 END IF;
1394 l_in_rec := NULL;
1395 l_in_rec.caller := 'WMS_REP';
1396 l_in_rec.action_code := 'UPDATE';
1397
1398 WSH_INTERFACE_EXT_GRP.Create_Update_Delivery_Detail
1399 (p_api_version_number => 1.0,
1400 p_init_msg_list => fnd_api.g_false,
1401 p_commit => fnd_api.g_false,
1402 x_return_status => l_return_status,
1403 x_msg_count => l_msg_count,
1404 x_msg_data => l_msg_data,
1405 p_detail_info_tab => l_detail_info_tab,
1406 p_in_rec => l_in_rec,
1407 x_out_rec => l_out_rec
1408 );
1409
1410 IF (l_debug = 1) THEN
1411 print_debug('AFTER Changing the line status to original release status');
1412 END IF;
1413
1414 IF (l_return_status = FND_API.G_RET_STS_ERROR) THEN
1415 IF (l_debug = 1) THEN
1416 print_debug('Error returned from Create_Update_Delivery_Detail IN api ADJUST_ATR_FOR_ITEM');
1417 END IF;
1418 RAISE FND_API.G_EXC_ERROR;
1419 ELSIF (l_return_status = FND_API.G_RET_STS_UNEXP_ERROR) THEN
1420 IF (l_debug = 1) THEN
1421 print_debug('Unexpected errror from Create_Update_Delivery_Detail api IN ADJUST_ATR_FOR_ITEM');
1422 END IF;
1423 RAISE FND_API.G_EXC_UNEXPECTED_ERROR;
1424 END IF;
1425
1426 END IF;
1427
1428 */
1429 --AMO IFFCO --BUG10149131
1430 l_dyn_bkord_dd_id_tab.DELETE;
1431 l_push_bkord_dd_id_tab.DELETE;
1432
1433 <<skip_item>>
1434 IF (l_debug = 1 and x_consol_item_repl_tbl.exists(i)) THEN -- 13393465
1435 print_debug('end consolidated item : '||x_consol_item_repl_tbl(i).item_id);
1436 END IF;
1437
1438 END LOOP; -- For each consolidated Items
1439 END IF;
1440
1441 x_return_status := l_return_status;
1442
1443 EXCEPTION
1444 WHEN OTHERS THEN
1445 IF (l_debug = 1) THEN
1446 print_debug('Exception in ADJUST_atr_for_item: ' || sqlcode || ', ' || sqlerrm);
1447 END IF;
1448 x_return_status := FND_API.G_RET_STS_ERROR;
1449 -- calling API will rollback
1450 END ADJUST_atr_for_item;
1451
1452
1453
1454 PROCEDURE PUSH_REPLENISHMENT(P_repl_level IN NUMBER DEFAULT 1,
1455 p_Item_id IN NUMBER,
1456 p_organization_id IN NUMBER,
1457 p_ABC_assignment_group_id IN NUMBER, -- For ABC Compile Group
1458 p_abc_class_id IN NUMBER, -- For Item Classification
1459 p_Order_Type_id IN NUMBER,
1460 p_Carrier_id IN NUMBER,
1461 p_customer_class IN VARCHAR2,
1462 p_customer_id IN NUMBER,
1463 p_Ship_Method_code IN VARCHAR2,
1464 p_Scheduled_Ship_Date_To IN NUMBER,
1465 p_Scheduled_Ship_Date_From IN NUMBER,
1466 p_Forward_Pick_Sub IN VARCHAR2,
1467 p_repl_UOM IN VARCHAR2,
1468 p_Repl_Lot_Size IN NUMBER,
1469 p_Min_Order_lines_threshold IN NUMBER,
1470 p_Min_repl_qty_threshold IN NUMBER,
1471 p_max_NUM_items_for_repl IN NUMBER,
1472 p_Sort_Criteria IN NUMBER,
1473 p_Auto_Allocate IN VARCHAR2,
1474 p_Plan_Tasks IN VARCHAR2,
1475 p_Release_Sequence_Rule_Id IN NUMBER,
1476 p_Create_Reservation IN VARCHAR2,
1477 x_return_status OUT NOCOPY VARCHAR2,
1478 x_msg_count OUT NOCOPY NUMBER,
1479 x_msg_data OUT NOCOPY VARCHAR2)
1480 IS
1481
1482 l_return_value BOOLEAN;
1483 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
1484 l_consol_item_repl_tbl CONSOL_ITEM_REPL_TBL;
1485
1486 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
1487 BEGIN
1488 x_return_status := l_return_status;
1489
1490 SAVEPOINT push_replenishment_sp;
1491
1492 -- REPLENISHMENT_TYPE
1493 -- 1 - PUSH REPLENISHMENT
1494 -- 2 - DYNAMIC REPLENISHMENT
1495 -- Do validation on passed parameter values
1496
1497 IF l_debug = 1 THEN
1498 print_debug('Printing Values inside PUSH_REPLENISHMENT');
1499 print_debug(' P_repl_level :'|| p_repl_level);
1500 print_debug(' p_Item_id :'|| p_Item_id );
1501 print_debug(' p_organization_id :'||p_organization_id );
1502 print_debug(' p_ABC_assignment_group_id :'||p_ABC_assignment_group_id );
1503 print_debug(' p_abc_class_id :'|| p_abc_class_id );
1504 print_debug(' p_Order_Type_id :'|| p_Order_Type_id );
1505 print_debug(' p_Carrier_id :'||p_Carrier_id );
1506 print_debug(' p_customer_class :'|| p_customer_class );
1507 print_debug(' p_customer_id :'|| p_customer_id );
1508 print_debug(' p_Ship_Method_code :'|| p_Ship_Method_code );
1509 print_debug(' p_Scheduled_Ship_Date_To :'|| p_Scheduled_Ship_Date_To );
1510 print_debug(' p_Scheduled_Ship_Date_From :'||p_Scheduled_Ship_Date_From );
1511 print_debug(' p_Forward_Pick_Sub :'|| p_Forward_Pick_Sub );
1512 print_debug(' p_repl_UOM :'|| p_repl_UOM );
1513 print_debug(' p_Repl_Lot_Size :'|| p_Repl_Lot_Size );
1514 print_debug(' p_Min_Order_lines_threshold :'||p_Min_Order_lines_threshold);
1515 print_debug(' p_Min_repl_qty_threshold :'||p_Min_repl_qty_threshold );
1516 print_debug(' p_max_NUM_items_for_repl :'||p_max_NUM_items_for_repl );
1517 print_debug(' p_Sort_Criteria :'|| p_Sort_Criteria );
1518 print_debug(' p_Auto_Allocate :'|| p_Auto_Allocate );
1519 print_debug(' p_Plan_Tasks :'|| p_Plan_Tasks );
1520 print_debug(' p_Release_Sequence_Rule_Id :'||p_Release_Sequence_Rule_Id);
1521 print_debug(' p_Create_Reservation :'|| p_Create_Reservation );
1522 END IF;
1523
1524
1525 IF (p_organization_id IS NULL
1526 OR p_Forward_Pick_Sub IS NULL
1527 OR p_repl_UOM IS NULL
1528 OR p_Sort_Criteria IS NULL --Default is total demand quantity = 1 from UI
1529 OR p_Auto_Allocate IS NULL
1530 OR p_Plan_Tasks IS NULL
1531 OR (p_ABC_assignment_group_id IS NULL AND p_abc_class_id IS NOT NULL)) THEN
1532
1533 IF l_debug = 1 THEN
1534 print_debug(' ERROR: VALIDATION FAILED !' );
1535 END IF;
1536
1537 x_return_status := FND_API.G_RET_STS_ERROR;
1538 x_msg_data := 'Missing Required Information';
1539 RETURN;
1540
1541 END IF;
1542
1543 -- Initialize Global package tables
1544
1545 l_consol_item_repl_tbl.DELETE;
1546
1547 -- Initialize the global Item UOM conversion table
1548 g_item_uom_conversion_tb.DELETE;
1549
1550 POPULATE_PUSH_REPL_DEMAND(p_repl_level => p_repl_level,
1551 p_Item_id => p_Item_id,
1552 p_organization_id => p_organization_id,
1553 p_ABC_assignment_group_id => p_ABC_assignment_group_id,
1554 p_abc_class_id => p_abc_class_id,
1555 p_Order_Type_id => p_Order_Type_id,
1556 p_Carrier_id => p_Carrier_id,
1557 p_customer_class => p_customer_class,
1558 p_customer_id => p_customer_id,
1559 p_Ship_Method_code => p_Ship_Method_code,
1560 p_Scheduled_Ship_Date_To => p_Scheduled_Ship_Date_To,
1561 p_Scheduled_Ship_Date_From => p_Scheduled_Ship_Date_From,
1562 p_Forward_Pick_Sub => p_Forward_Pick_Sub,
1563 p_repl_UOM => p_repl_UOM,
1564 p_Release_Sequence_Rule_Id => p_Release_Sequence_Rule_Id,
1565 p_Min_Order_lines_threshold => p_Min_Order_lines_threshold,
1566 p_Min_repl_qty_threshold => p_Min_repl_qty_threshold,
1567 p_max_NUM_items_for_repl => p_max_NUM_items_for_repl,
1568 p_Sort_Criteria => p_Sort_Criteria,
1569 x_consol_item_repl_tbl => l_consol_item_repl_tbl,
1570 x_return_status => l_return_status,
1571 x_msg_count => x_msg_count,
1572 x_msg_data => x_msg_data);
1573
1574
1575 IF l_RETURN_status = fnd_api.g_ret_sts_success THEN
1576 IF (l_debug = 1) THEN
1577 PRINT_DEBUG('Demand records populated successfully');
1578 END IF;
1579
1580 ELSE
1581 l_consol_item_repl_tbl.DELETE;
1582 IF (l_debug = 1) THEN
1583 PRINT_DEBUG('Error from API POPULATE_PUSH_REPL_DEMAND');
1584 END IF;
1585 RAISE fnd_api.g_exc_unexpected_error;
1586 END IF;
1587
1588
1589 -- ==========TEST CODE starts ===========
1590 -- This code is for debugging purpose only, this code should be in
1591 -- l_debug = 1 only
1592 IF (l_debug = 1) THEN
1593 IF l_consol_item_repl_tbl.COUNT <> 0 THEN
1594 print_debug('*******AFTER GETTING DEMAND RECORDS******');
1595 FOR i IN l_consol_item_repl_tbl.FIRST .. l_consol_item_repl_tbl.LAST LOOP
1596 IF (NOT l_consol_item_repl_tbl.exists(i)) THEN
1597 print_debug('RECORD has been deleted from consol table, Skipping it');
1598 ELSE
1599 print_debug('ITEM_ID = ' || l_consol_item_repl_tbl(i).ITEM_ID || ' '
1600 || 'total_demand_qty = ' || l_consol_item_repl_tbl(i).total_demand_qty );
1601
1602 END IF;
1603 END LOOP;
1604 END IF;
1605 END IF;
1606 -- ==========TEST CODE ends ===========
1607
1608
1609
1610 -- To populate the demand table - WMS_REPL_DEMAND_GTMP - Get values in l_consol_item_repl_tbl
1611 -- Cache information about relevant items
1612 -- Call the Extensibility API to see if there is a custom logic to get the consolidate demand lines per Item.
1613 --This API will appropriately populate l_consol_item_repl_tbl .
1614
1615
1616 IF (WMS_REPL_CUSTOM_APIS_PUB.g_is_api_implemented) THEN
1617 l_consol_item_repl_tbl.DELETE;
1618 WMS_REPL_CUSTOM_APIS_PUB.GET_CONSOL_REPL_DEMAND_CUST(x_return_status => x_return_status,
1619 x_msg_count => x_msg_count,
1620 x_msg_data => x_msg_data,
1621 x_consol_item_repl_tbl => l_consol_item_repl_tbl);
1622
1623 END IF; -- for API is implemented
1624
1625
1626 IF l_consol_item_repl_tbl.COUNT <> 0 THEN
1627
1628 --Call the core replenishment processing API - PROCESS_REPLENISHMENT()
1629 PROCESS_REPLENISHMENT(P_repl_level => P_repl_level,
1630 p_repl_type => 1, --Push Replenishment
1631 p_Repl_Lot_Size => p_Repl_Lot_Size,
1632 P_consol_item_repl_tbl => l_consol_item_repl_tbl,
1633 p_Create_Reservation => p_Create_Reservation,
1634 p_Auto_Allocate => p_Auto_Allocate,
1635 p_Plan_Tasks => p_Plan_Tasks,
1636 x_return_status => l_return_status,
1637 x_msg_count => x_msg_count,
1638 x_msg_data => x_msg_data);
1639
1640 IF l_RETURN_status = fnd_api.g_ret_sts_success THEN
1641 IF (l_debug = 1) THEN
1642 PRINT_DEBUG('processed replenishment successfully');
1643 END IF;
1644
1645 ELSE
1646 IF (l_debug = 1) THEN
1647 PRINT_DEBUG('Error from API process_replenishment');
1648 END IF;
1649 RAISE fnd_api.g_exc_unexpected_error;
1650 END IF;
1651 ELSE
1652 IF (l_debug = 1) THEN
1653 print_debug('No Demand Records Identified for Chosen Criteria..Exiting...');
1654 END IF;
1655 ROLLBACK TO push_replenishment_sp;
1656 -- RETURN; -- bug 7201888
1657 END IF;
1658
1659 -- Call an API to backorder all demands lines that were stored to be backordered
1660 -- We do not fail the transaction even if the backordering fails
1661
1662 IF (l_debug = 1) THEN
1663 print_debug( 'Number of WDDs to backorder :'||g_backorder_deliv_tab.COUNT());
1664 END IF;
1665
1666 IF g_backorder_deliv_tab.COUNT() <> 0 THEN
1667 Backorder_wdd_for_repl( l_return_status );
1668 IF l_RETURN_status <> fnd_api.g_ret_sts_success THEN
1669 IF (l_debug = 1) THEN
1670 PRINT_DEBUG('Call to Backorder_wdd_for_repl API returned failure..DO NOTHING');
1671 END IF;
1672 END IF;
1673 END IF;
1674
1675
1676 COMMIT; -- commit entire transaction
1677 x_return_status := FND_API.g_ret_sts_success;
1678
1679 IF (l_debug = 1) THEN
1680 PRINT_DEBUG('Done with the Push Replenishment');
1681 END IF;
1682
1683 EXCEPTION
1684
1685 WHEN OTHERS THEN
1686 ROLLBACK TO push_replenishment_sp;
1687 l_consol_item_repl_tbl.DELETE;
1688 g_item_uom_conversion_tb.DELETE;
1689 IF l_debug = 1 THEN
1690 print_debug('Error in PUSH_REPLENISHMENT: ' || sqlcode || ', ' || sqlerrm);
1691 END IF;
1692 x_return_status:= FND_API.g_ret_sts_error;
1693
1694 END PUSH_REPLENISHMENT;
1695
1696
1697 PROCEDURE DYNAMIC_REPLENISHMENT(p_org_id IN NUMBER,
1698 P_Batch_id IN NUMBER,
1699 p_Plan_Tasks IN VARCHAR2,
1700 p_Release_Sequence_Rule_Id IN NUMBER,
1701 P_repl_level IN NUMBER DEFAULT 1,
1702 x_msg_count OUT NOCOPY NUMBER,
1703 x_return_status OUT NOCOPY VARCHAR2,
1704 x_msg_data OUT NOCOPY VARCHAR2)
1705 IS
1706 l_return_value BOOLEAN;
1707 l_consol_item_repl_tbl CONSOL_ITEM_REPL_TBL;
1708 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
1709
1710 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
1711 BEGIN
1712
1713 x_return_status := l_return_status;
1714 SAVEPOINT dynamic_replenishment_sp;
1715
1716 --REPLENISHMENT_TYPE
1717 -- 1 - PUSH REPLENISHMENT
1718 -- 2 - DYNAMIC REPLENISHMENT
1719
1720 IF l_debug = 1 THEN
1721 print_debug('Inside DYNAMIC_REPLENISHMENT API....');
1722 print_debug('p_org_id :'||p_org_id );
1723 print_debug('p_Batch_id :'||p_Batch_id );
1724 print_debug('p_Plan_Tasks :'||p_Plan_Tasks );
1725 print_debug('p_Release_Sequence_Rule_Id :'||p_Release_Sequence_Rule_Id );
1726 print_debug('p_repl_level :'||p_repl_level );
1727 END IF;
1728
1729
1730 -- Do validation on passed parameter values
1731
1732 IF(P_Batch_id IS NULL) THEN
1733 -- if no batch_id provided, just return, Pick release should not fail here
1734 IF l_debug = 1 THEN
1735 print_debug('P_Batch_id is NULL, Returning from DYNAMIC_REPLENISHMENT');
1736 END IF;
1737 RETURN;
1738 END IF;
1739
1740 --Initialize Global package tables
1741 l_consol_item_repl_tbl.DELETE;
1742
1743 -- Initialize the global Item UOM conversion table
1744 g_item_uom_conversion_tb.DELETE;
1745
1746 POPULATE_DYNAMIC_REPL_DEMAND(p_repl_level => p_repl_level,
1747 p_org_id => p_org_id,
1748 P_Batch_id => P_Batch_id,
1749 p_Release_Sequence_Rule_Id => p_Release_Sequence_Rule_Id,
1750 x_consol_item_repl_tbl => L_consol_item_repl_tbl,
1751 x_return_status => l_return_status,
1752 x_msg_count => x_msg_count,
1753 x_msg_data => x_msg_data
1754 );
1755 -- API for dynamic replenishment should not return error
1756 -- The API needs to revert the original status of WDD
1757 -- Even if it errors out for what ever reason, all WDDs
1758 -- should be reverted in the called API at the very least
1759 -- and return status of success with no records in consol table
1760 IF l_RETURN_status = fnd_api.g_ret_sts_success THEN
1761 IF (l_debug = 1) THEN
1762 PRINT_DEBUG('Demand records populated successfully');
1763 END IF;
1764 ELSE
1765 l_consol_item_repl_tbl.DELETE;
1766 IF (l_debug = 1) THEN
1767 PRINT_DEBUG('Error from API POPULATE_dynamic_REPL_DEMAND');
1768 END IF;
1769 RAISE fnd_api.g_exc_unexpected_error;
1770 END IF;
1771
1772 -- To populate the demand table - WMS_REPL_DEMAND_GTMP - Get values in l_consol_item_repl_tbl
1773 -- Cache information about relevant items
1774 -- Call the core replenishment processing API - PROCESS_REPLENISHMENT()
1775
1776
1777
1778 -- ==========TEST CODE starts ===========
1779 -- This code is for debugging purpose only, this code should be in
1780 -- l_debug = 1 only
1781 IF (l_debug = 1) THEN
1782 IF l_consol_item_repl_tbl.COUNT <> 0 THEN
1783 print_debug('*******AFTER POPULATE_DYNAMIC_REPL_DEMAND****');
1784 FOR i IN l_consol_item_repl_tbl.FIRST .. l_consol_item_repl_tbl.LAST LOOP
1785
1786 IF (NOT l_consol_item_repl_tbl.exists(i)) THEN
1787 print_debug('RECORD has been deleted from consol table, Skipping it');
1788 ELSE
1789 print_debug('ITEM_ID, Total_qty, available_OH, open_MO_QTY, Final_repl_qty ');
1790 print_debug( l_consol_item_repl_tbl(i).ITEM_ID || ' , ' ||
1791 l_consol_item_repl_tbl(i).total_demand_qty || ' , '||
1792 l_consol_item_repl_tbl(i).available_onhand_qty|| ' , '||
1793 l_consol_item_repl_tbl(i).open_mo_qty|| ' , '||
1794 l_consol_item_repl_tbl(i).final_replenishment_qty);
1795
1796 END IF;
1797 END LOOP;
1798 END IF;
1799 END IF;
1800 -- ==========TEST CODE ends ===========
1801
1802
1803
1804 IF l_consol_item_repl_tbl.COUNT <> 0 THEN
1805 PROCESS_REPLENISHMENT (
1806 P_repl_level => P_repl_level,
1807 p_repl_type => 2, --Dynamic Replenishment
1808 p_Repl_Lot_Size => NULL,
1809 P_consol_item_repl_tbl => l_consol_item_repl_tbl,
1810 p_Create_Reservation => 'Y',
1811 p_Auto_Allocate => 'Y',
1812 p_Plan_Tasks => p_Plan_Tasks,
1813 x_return_status => l_return_status ,
1814 x_msg_count => x_msg_count ,
1815 x_msg_data => x_msg_data );
1816
1817 IF l_RETURN_status = fnd_api.g_ret_sts_success THEN
1818 IF (l_debug = 1) THEN
1819 PRINT_DEBUG('processed replenishment successfully');
1820 END IF;
1821
1822 ELSE
1823 IF (l_debug = 1) THEN
1824 PRINT_DEBUG('Error from API process_replenishment');
1825 END IF;
1826 -- To call revert of WDD status for all WDDs
1827 RAISE fnd_api.g_exc_unexpected_error;
1828 END IF;
1829 ELSE
1830
1831 IF (l_debug = 1) THEN
1832 print_debug('No Demand Records Identified for Chosen Criteria..Exiting...');
1833 END IF;
1834 END IF;
1835
1836
1837 -- Call an API to backorder all demands lines that were stored to be backordered
1838 -- We do not fail the transaction even if the backordering fails
1839
1840 IF (l_debug = 1) THEN
1841 print_debug( 'Number of WDDs to backorder :'||g_backorder_deliv_tab.COUNT());
1842 END IF;
1843
1844 IF g_backorder_deliv_tab.COUNT() <> 0 THEN
1845 Backorder_wdd_for_repl( l_return_status );
1846 IF l_RETURN_status <> fnd_api.g_ret_sts_success THEN
1847 IF (l_debug = 1) THEN
1848 PRINT_DEBUG('Call to Backorder_wdd_for_repl API returned failure..DO NOTHING');
1849 END IF;
1850 END IF;
1851 END IF;
1852
1853
1854 COMMIT;
1855 x_return_status := FND_API.g_ret_sts_success;
1856
1857 IF (l_debug = 1) THEN
1858 PRINT_DEBUG('Done with the Pull/Dynamic Replenishment');
1859 END IF;
1860
1861
1862 EXCEPTION
1863 WHEN OTHERS THEN
1864 ROLLBACK TO dynamic_replenishment_sp;
1865 l_consol_item_repl_tbl.DELETE;
1866 IF l_debug = 1 THEN
1867 print_debug('SHOULD NOT HAPPEN Error in DYNAMIC_REPLENISHMENT: ' || sqlcode || ', ' || sqlerrm);
1868 END IF;
1869
1870 -- To call revert of WDD status for all WDDs
1871 -- need to revert all WDD status back
1872 Revert_ALL_WDD_dynamic_repl (p_org_id => p_org_id
1873 , p_batch_id => p_batch_id
1874 , x_return_status => l_return_status
1875 );
1876
1877 IF l_debug = 1 THEN
1878 print_debug('status:'||l_return_status);
1879 END IF;
1880 COMMIT;
1881
1882 x_return_status:= FND_API.g_ret_sts_error;
1883 END DYNAMIC_REPLENISHMENT;
1884
1885
1886
1887 PROCEDURE POPULATE_PUSH_REPL_DEMAND
1888 (p_repl_level IN NUMBER,
1889 p_Item_id IN NUMBER,
1890 p_organization_id IN NUMBER,
1891 p_ABC_assignment_group_id IN NUMBER, -- For ABC Compile Group
1892 p_abc_class_id IN NUMBER, -- For Item Classification
1893 p_Order_Type_id IN NUMBER,
1894 p_Carrier_id IN NUMBER,
1895 p_customer_class IN VARCHAR2,
1896 p_customer_id IN NUMBER,
1897 p_Ship_Method_code IN VARCHAR2,
1898 p_Scheduled_Ship_Date_To IN NUMBER,
1899 p_Scheduled_Ship_Date_From IN NUMBER,
1900 p_Forward_Pick_Sub IN VARCHAR2,
1901 p_repl_UOM IN VARCHAR2,
1902 p_Release_Sequence_Rule_Id IN NUMBER,
1903 p_Min_Order_lines_threshold IN NUMBER,
1904 p_Min_repl_qty_threshold IN NUMBER,
1905 p_max_NUM_items_for_repl IN NUMBER,
1906 p_Sort_Criteria IN NUMBER,
1907 x_consol_item_repl_tbl OUT NOCOPY CONSOL_ITEM_REPL_TBL,
1908 x_return_status OUT NOCOPY VARCHAR2,
1909 x_msg_count OUT NOCOPY NUMBER,
1910 x_msg_data OUT NOCOPY VARCHAR2
1911 )
1912 IS
1913
1914
1915
1916 -- Note: This procedure/concurrent program will be launced for a
1917 -- specific organization. All demand lines for same organizations should be together but here it
1918 -- will not matter (for dynamic repl,it will be ordered by org_id as well
1919
1920 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
1921
1922 L_ORDER_ID_SORT VARCHAR2(4) := NULL;
1923 L_INVOICE_VALUE_SORT VARCHAR2(4) := NULL;
1924 L_SCHEDULE_DATE_SORT VARCHAR2(4) := NULL;
1925 L_TRIP_STOP_DATE_SORT VARCHAR2(4) := NULL;
1926 L_SHIPMENT_PRI_SORT VARCHAR2(4) := NULL;
1927
1928 L_INDEX NUMBER;
1929 l_progress VARCHAR2(10);
1930 l_quantity_in_repl_uom NUMBER;
1931 L_match_found NUMBER;
1932 l_return_value BOOLEAN;
1933
1934
1935 --TEST : if sub is specified on the SO, we exclude that unless it is same
1936 -- AS forward pick Sub
1937
1938 CURSOR c_repl_demand_cur IS
1939 SELECT
1940 item_id,header_id,line_id,delivery_detail_id,demand_type_id,requested_quantity,requested_quantity_uom,
1941 quantity_in_repl_uom, expected_ship_date , replenishment_status,released_status,
1942 sort_attribute1 ,sort_attribute2,sort_attribute3,sort_attribute4,sort_attribute5
1943
1944 FROM (
1945 SELECT wdd.inventory_item_id as item_id,
1946 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) AS header_id,
1947 wdd.source_line_id AS line_id,
1948 wdd.delivery_detail_id delivery_detail_id,
1949 decode(wdd.source_document_type_id, 10, 8, 2) as demand_type_id, -- for SO=2 and Internal Order=8
1950 wdd.requested_quantity requested_quantity, -- this is always stored in primary UOM
1951 wdd.requested_quantity_uom requested_quantity_uom,
1952 ROUND((wdd.requested_quantity * get_conversion_rate(wdd.inventory_item_id,
1953 wdd.requested_quantity_uom,
1954 p_repl_UOM)),g_conversion_precision) as quantity_in_repl_uom,
1955
1956 decode(p_Scheduled_Ship_Date_To,
1957 null,
1958 decode(p_Scheduled_Ship_Date_From,
1959 null,
1960 null,
1961 NVL(WMS_REPLENISHMENT_PVT.Get_Expected_Time(decode(wdd.source_document_type_id, 10, 8, 2),
1962 wdd.source_header_id,
1963 wdd.source_line_id,
1964 wdd.delivery_detail_id),
1965 WDD.date_scheduled)),
1966
1967 NVL(WMS_REPLENISHMENT_PVT.Get_Expected_Time(decode(wdd.source_document_type_id, 10, 8, 2),
1968 wdd.source_header_id,
1969 wdd.source_line_id,
1970 wdd.delivery_detail_id),
1971 WDD.date_scheduled)) as expected_ship_date,
1972 wdd.replenishment_status,
1973 wdd.released_status,
1974
1975 -- For order clause by select column values for WSH_PICK_SEQUENCE_RULES
1976 -- get for sort_attribute1
1977 To_number(DECODE(p_Release_Sequence_Rule_Id,
1978 null,
1979 null,
1980 DECODE(g_ordered_psr(1).attribute_name,
1981 'ORDER_NUMBER',
1982 DECODE(L_ORDER_ID_SORT,
1983 'ASC',
1984 To_number(wdd.source_header_number),
1985 'DESC',
1986 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
1987 null),
1988 'SHIPMENT_PRIORITY',
1989 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
1990 'High',
1991 20,
1992 'Standard',
1993 10,
1994 NULL),
1995 'INVOICE_VALUE',
1996 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
1997 L_INVOICE_VALUE_SORT),
1998 'SCHEDULE_DATE',
1999 DECODE(L_SCHEDULE_DATE_SORT,
2000 'ASC',
2001 (WDD.DATE_SCHEDULED -
2002 TO_DATE('01-01-1700 23:59:59',
2003 'DD-MM-YYYY HH24:MI:SS')),
2004 'DESC',
2005 (TO_DATE('01-01-1700 23:59:59',
2006 'DD-MM-YYYY HH24:MI:SS') -
2007 WDD.DATE_SCHEDULED),
2008 null),
2009 'TRIP_STOP_DATE',
2010 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
2011 L_TRIP_STOP_DATE_SORT),
2012 NULL))) as sort_attribute1,
2013
2014 -- get for sort_attribute2
2015 To_number(DECODE(p_Release_Sequence_Rule_Id,
2016 null,
2017 null,
2018 DECODE(g_ordered_psr(2).attribute_name,
2019 'ORDER_NUMBER',
2020 DECODE(L_ORDER_ID_SORT,
2021 'ASC',
2022 To_number(wdd.source_header_number),
2023 'DESC',
2024 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
2025 null),
2026 'SHIPMENT_PRIORITY',
2027 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
2028 'High',
2029 20,
2030 'Standard',
2031 10,
2032 NULL),
2033 'INVOICE_VALUE',
2034 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
2035 L_INVOICE_VALUE_SORT),
2036 'SCHEDULE_DATE',
2037 DECODE(L_SCHEDULE_DATE_SORT,
2038 'ASC',
2039 (WDD.DATE_SCHEDULED -
2040 TO_DATE('01-01-1700 23:59:59',
2041 'DD-MM-YYYY HH24:MI:SS')),
2042 'DESC',
2043 (TO_DATE('01-01-1700 23:59:59',
2044 'DD-MM-YYYY HH24:MI:SS') -
2045 WDD.DATE_SCHEDULED),
2046 null),
2047 'TRIP_STOP_DATE',
2048 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
2049 L_TRIP_STOP_DATE_SORT),
2050 NULL))) as sort_attribute2,
2051
2052 -- get for sort_attribute3
2053 To_number(DECODE(p_Release_Sequence_Rule_Id,
2054 null,
2055 null,
2056 DECODE(g_ordered_psr(3).attribute_name,
2057 'ORDER_NUMBER',
2058 DECODE(L_ORDER_ID_SORT,
2059 'ASC',
2060 To_number(wdd.source_header_number),
2061 'DESC',
2062 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
2063 null),
2064 'SHIPMENT_PRIORITY',
2065 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
2066 'High',
2067 20,
2068 'Standard',
2069 10,
2070 NULL),
2071 'INVOICE_VALUE',
2072 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
2073 L_INVOICE_VALUE_SORT),
2074 'SCHEDULE_DATE',
2075 DECODE(L_SCHEDULE_DATE_SORT,
2076 'ASC',
2077 (WDD.DATE_SCHEDULED -
2078 TO_DATE('01-01-1700 23:59:59',
2079 'DD-MM-YYYY HH24:MI:SS')),
2080 'DESC',
2081 (TO_DATE('01-01-1700 23:59:59',
2082 'DD-MM-YYYY HH24:MI:SS') -
2083 WDD.DATE_SCHEDULED),
2084 null),
2085 'TRIP_STOP_DATE',
2086 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
2087 L_TRIP_STOP_DATE_SORT),
2088 NULL))) as sort_attribute3,
2089
2090 -- get for sort_attribute4
2091 To_number(DECODE(p_Release_Sequence_Rule_Id,
2092 null,
2093 null,
2094 DECODE(g_ordered_psr(4).attribute_name,
2095 'ORDER_NUMBER',
2096 DECODE(L_ORDER_ID_SORT,
2097 'ASC',
2098 To_number(wdd.source_header_number),
2099 'DESC',
2100 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
2101 null),
2102 'SHIPMENT_PRIORITY',
2103 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
2104 'High',
2105 20,
2106 'Standard',
2107 10,
2108 NULL),
2109 'INVOICE_VALUE',
2110 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
2111 L_INVOICE_VALUE_SORT),
2112 'SCHEDULE_DATE',
2113 DECODE(L_SCHEDULE_DATE_SORT,
2114 'ASC',
2115 (WDD.DATE_SCHEDULED -
2116 TO_DATE('01-01-1700 23:59:59',
2117 'DD-MM-YYYY HH24:MI:SS')),
2118 'DESC',
2119 (TO_DATE('01-01-1700 23:59:59',
2120 'DD-MM-YYYY HH24:MI:SS') -
2121 WDD.DATE_SCHEDULED),
2122 null),
2123 'TRIP_STOP_DATE',
2124 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
2125 L_TRIP_STOP_DATE_SORT),
2126 NULL))) as sort_attribute4,
2127
2128 -- get for sort_attribute5
2129 To_number(DECODE(p_Release_Sequence_Rule_Id,
2130 null,
2131 null,
2132 DECODE(g_ordered_psr(5).attribute_name,
2133 'ORDER_NUMBER',
2134 DECODE(L_ORDER_ID_SORT,
2135 'ASC',
2136 To_number(wdd.source_header_number),
2137 'DESC',
2138 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
2139 null),
2140 'SHIPMENT_PRIORITY',
2141 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
2142 'High',
2143 20,
2144 'Standard',
2145 10,
2146 null),
2147 'INVOICE_VALUE',
2148 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
2149 L_INVOICE_VALUE_SORT),
2150 'SCHEDULE_DATE',
2151 DECODE(L_SCHEDULE_DATE_SORT,
2152 'ASC',
2153 (WDD.DATE_SCHEDULED -
2154 TO_DATE('01-01-1700 23:59:59',
2155 'DD-MM-YYYY HH24:MI:SS')),
2156 'DESC',
2157 (TO_DATE('01-01-1700 23:59:59',
2158 'DD-MM-YYYY HH24:MI:SS') -
2159 WDD.DATE_SCHEDULED),
2160 null),
2161 'TRIP_STOP_DATE',
2162 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
2163 L_TRIP_STOP_DATE_SORT),
2164 NULL))) as sort_attribute5
2165
2166 FROM oe_order_lines_all oel,
2167 wsh_delivery_details wdd
2168 WHERE wdd.organization_id = p_organization_id
2169 AND wdd.source_code = 'OE'
2170 AND oel.booked_flag = 'Y'
2171 AND oel.open_flag = 'Y'
2172 AND wdd.requested_quantity > 0
2173 AND oel.line_id = wdd.source_line_id
2174 -- excluding Replenishment requested status
2175 AND wdd.released_status in ('R', 'B')
2176 and nvl(wdd.replenishment_status, 'C') = 'C'
2177 -- there might not be reservation
2178 AND not exists
2179 (select 1
2180 from mtl_reservations mr
2181 WHERE MR.DEMAND_SOURCE_LINE_ID = wdd.source_line_id
2182 and MR.DEMAND_SOURCE_HEADER_ID =
2183 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id)
2184 AND MR.SUBINVENTORY_CODE IS NOT NULL) --locator is not needed -- Exclude detailed RSV
2185
2186 --Exclude those demands that have suub
2187 -- specified, we can not use sub = Forward_pick_sub either
2188 -- becs FP sub info is not availble while marking 'RC' at the pick drop time when rsv = N
2189 AND wdd.subinventory IS NULL
2190 /*10131943- Made the query on MTL_ABC_ASSIGNMENTS a sub-query because an item can have multiple ABC compile/group assignments*/
2191 AND (NOT EXISTS (SELECT 1
2192 FROM mtl_abc_assignments maa
2193 WHERE maa.inventory_item_id = oel.inventory_item_id)
2194 OR EXISTS (SELECT 1
2195 FROM mtl_abc_assignments maa
2196 WHERE maa.inventory_item_id = oel.inventory_item_id
2197 AND Nvl(maa.assignment_group_id, -1) = Nvl(p_ABC_assignment_group_id, Nvl(maa.assignment_group_id, -1))
2198 AND Nvl(maa.abc_class_id, -1) = Nvl(p_abc_class_id, Nvl(maa.abc_class_id, -1))
2199 )
2200 )
2201 AND (nvl(wdd.customer_id, -1) = nvl(p_customer_id,nvl(wdd.customer_id, -1))
2202 OR wdd.customer_id in (SELECT party_id FROM hz_cust_accounts
2203 WHERE customer_class_code = p_customer_class
2204 AND status <> 'I'
2205 AND party_id = nvl(p_customer_id,party_id)))
2206 AND wdd.source_header_type_id = nvl(P_ORDER_TYPE_ID,source_header_type_id)
2207 AND NOT exists
2208 (select wrd.demand_line_detail_id
2209 from WMS_REPLENISHMENT_DETAILS wrd
2210 where wrd.demand_line_detail_id = wdd.delivery_detail_id
2211 and wrd.demand_line_id = wdd.source_line_id
2212 and wrd.organization_id = wdd.organization_id
2213 And wrd.organization_id = p_organization_id)
2214
2215 AND wdd.INVENTORY_ITEM_ID = NVL(P_ITEM_ID, wdd.INVENTORY_ITEM_ID)
2216 AND nvl(wdd.carrier_id, -1) =
2217 NVL(p_Carrier_id, nvl(wdd.carrier_id, -1))
2218 AND nvl(wdd.SHIP_METHOD_CODE, '@@@') =
2219 NVL(p_Ship_Method_code, nvl(wdd.SHIP_METHOD_CODE, '@@@')) -- mandatory field
2220
2221 ) X
2222
2223 WHERE x.quantity_in_repl_uom > 0
2224 AND x.expected_ship_date <= (SYSDATE + p_scheduled_ship_date_to )-- MANDATORY FIELD
2225
2226 ORDER BY
2227 x.sort_attribute1,
2228 x.sort_attribute2,
2229 x.sort_attribute3,
2230 x.sort_attribute4,
2231 x.sort_attribute5
2232 FOR UPDATE SKIP LOCKED;
2233
2234 --<<Those demands that are still in Order Management and
2235 -- not scheduled yet are not considering in the demand
2236 -- cursor. Only those demands that are scheduled, means that
2237 --are booked and they exist in WDD are being considered as
2238 --valid demand>>
2239
2240
2241 -- DESTINATION SUB IS SAME FOR ALL THESE RECORDS in c_item_repl_cur
2242 CURSOR c_item_repl_cur IS
2243 SELECT X.inventory_item_id inventory_item_id,
2244 X.total_demand_qty total_demand_qty,
2245 X.date_required date_required
2246 FROM (SELECT inventory_item_id,
2247 sum(quantity_in_repl_uom) as total_demand_qty,
2248 MIN(expected_ship_date) as date_required,
2249 MIN(repl_sequence_id) AS order_priority -- to avoid conflicting situation
2250 FROM WMS_REPL_DEMAND_GTMP
2251 where organization_id = p_organization_id
2252 group by inventory_item_id
2253 order by decode(p_Sort_Criteria,
2254 1,
2255 sum(quantity_in_repl_uom),
2256 count(1)) DESC, order_priority ASC) X
2257 WHERE ROWNUM <= nvl(p_max_NUM_items_for_repl, 1e25);
2258
2259
2260
2261
2262 --BULK OPERATION: Table to store results from the open demand for replenishment
2263 l_item_id_tb num_tab;
2264 l_header_id_tb num_tab;
2265 l_line_id_tb num_tab;
2266 l_delivery_detail_id_tb num_tab;
2267 l_demand_type_id_tb num_tab;
2268 l_requested_quantity_tb num_tab;
2269 l_requested_quantity_uom_tb uom_tab;
2270 l_quantity_in_repl_uom_tb num_tab;
2271 l_expected_ship_date_tb date_tab;
2272 l_repl_status_tb char1_tab;
2273 l_released_status_tb char1_tab;
2274 l_attr1_tab num_tab;
2275 l_attr2_tab num_tab;
2276 l_attr3_tab num_tab;
2277 l_attr4_tab num_tab;
2278 l_attr5_tab num_tab;
2279
2280
2281 -- BULK OPERATION: Table to store consolidate demand results for replenishment
2282 l_total_demand_qty_tb num_tab;
2283 l_date_required_tb date_tab;
2284
2285 l_temp_cnt NUMBER; -- for debugging only
2286 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
2287 BEGIN
2288 x_return_status := l_return_status;
2289
2290 IF (l_debug = 1) THEN
2291 print_debug('Inside POPULATE_PUSH_REPL_DEMAND Release_Sequence_Rule_Id: '||p_Release_Sequence_Rule_Id);
2292 END IF;
2293
2294
2295 -- Get the Order By Clause based on Pick Release Rule
2296 --initialize gloabl variables
2297 --delete old value
2298 g_ordered_psr.DELETE;
2299 init_rules(p_pick_seq_rule_id => p_Release_Sequence_Rule_Id,
2300 x_order_id_sort => L_ORDER_ID_SORT,
2301 x_INVOICE_VALUE_SORT => L_INVOICE_VALUE_SORT,
2302 x_SCHEDULE_DATE_SORT => L_SCHEDULE_DATE_SORT,
2303 x_trip_stop_date_sort => L_TRIP_STOP_DATE_SORT,
2304 x_SHIPMENT_PRI_SORT => l_shipment_pri_sort,
2305 x_ordered_psr => g_ordered_psr,
2306 x_api_status => l_return_status );
2307
2308 IF (l_debug = 1) THEN
2309 print_debug('Status after calling init_rules'||l_return_status);
2310 END IF;
2311 IF (l_return_status <> fnd_api.g_ret_sts_success) THEN
2312 x_return_status := l_return_status;
2313 -- caller rollsback everything if error
2314 RETURN;
2315 END IF;
2316
2317 --Clear all tables for bulk operation
2318 l_item_id_tb.DELETE;
2319 l_header_id_tb.DELETE;
2320 l_line_id_tb.DELETE;
2321 l_delivery_detail_id_tb.DELETE;
2322 l_demand_type_id_tb.DELETE;
2323 l_requested_quantity_tb.DELETE;
2324 l_requested_quantity_uom_tb.DELETE;
2325 l_quantity_in_repl_uom_tb.DELETE;
2326 l_expected_ship_date_tb.DELETE;
2327 l_repl_status_tb.DELETE;
2328 l_released_status_tb.DELETE;
2329 l_attr1_tab.DELETE;
2330 l_attr2_tab.DELETE;
2331 l_attr3_tab.DELETE;
2332 l_attr4_tab.DELETE;
2333 l_attr5_tab.DELETE;
2334
2335 -- BULK Fetch all data from the demand cursor
2336 BEGIN
2337 OPEN c_repl_demand_cur;
2338 FETCH c_repl_demand_cur BULK COLLECT INTO l_item_id_tb,l_header_id_tb, l_line_id_tb, l_delivery_detail_id_tb,
2339 l_demand_type_id_tb, l_requested_quantity_tb,l_requested_quantity_uom_tb,
2340 l_quantity_in_repl_uom_tb,l_expected_ship_date_tb,l_repl_status_tb,l_released_status_tb,
2341 l_attr1_tab,l_attr2_tab,l_attr3_tab,l_attr4_tab,l_attr5_tab ;
2342
2343 IF (l_debug = 1) THEN
2344 print_debug('InProcess ROWCOUNT :'|| c_repl_demand_cur%ROWCOUNT );
2345 END IF;
2346 CLOSE c_repl_demand_cur;
2347
2348 EXCEPTION
2349 WHEN OTHERS THEN
2350 IF (l_debug = 1) THEN
2351 print_debug('Exception retrieving open repl demand records :'||SQLCODE ||' '||SQLERRM);
2352 END IF;
2353 -- caller rollsback everything if error
2354 x_return_status := fnd_api.g_ret_sts_error;
2355 RETURN;
2356 END;
2357
2358
2359 --BULK insert all demand records in the GTMP table
2360 BEGIN
2361 FORALL k IN INDICES OF l_delivery_detail_id_tb
2362 insert into WMS_REPL_DEMAND_GTMP
2363 (Repl_Sequence_id,
2364 repl_level,
2365 Inventory_item_id,
2366 Organization_id,
2367 demand_header_id,
2368 demand_line_id,
2369 demand_line_detail_id,
2370 demand_type_id,
2371 Quantity,
2372 Uom_code,
2373 quantity_in_repl_uom,
2374 REPL_UOM_code,
2375 Expected_ship_date,
2376 Repl_To_Subinventory_code,
2377 filter_item_flag,
2378 repl_status,
2379 repl_type,
2380 RELEASED_STATUS)
2381 values
2382 (WMS_REPL_DEMAND_GTMP_S.NEXTVAL,
2383 p_repl_level,
2384 l_item_id_tb(k),
2385 p_organization_id,
2386 l_header_id_tb(k),
2387 l_line_id_tb(k),
2388 l_delivery_detail_id_tb(k),
2389 l_demand_type_id_tb(k),
2390 l_requested_quantity_tb(k),
2391 l_requested_quantity_uom_tb(k),
2392 l_quantity_in_repl_uom_tb(k),
2393 p_repl_UOM,
2394 l_expected_ship_date_tb(k),
2395 P_Forward_Pick_Sub,
2396 NULL,
2397 l_repl_status_tb(k),
2398 1,
2399 l_released_status_tb(k)); -- for Push replenishment
2400
2401
2402 /*
2403 -- p_Scheduled_Ship_Date_FROM is long enough to go to take the
2404 -- expected_date TO the last month, the query used to fail.
2405 -- AND x.expected_ship_date >=
2406 -- DECODE(NVL(p_Scheduled_Ship_Date_FROM, -1),-1,x.expected_ship_date,(SYSDATE - p_scheduled_ship_date_from))
2407 -- NULL value of p_Scheduled_Ship_Date_FROM is fine,
2408 -- running seperate query from dual with problematic value is also fine
2409 -- So I removed the condition from the main query and have put here
2410 -- AS extra CHECK ON p_scheduled_ship_date_from value condition
2411 */
2412
2413 IF p_scheduled_ship_date_from IS NOT NULL THEN
2414 DELETE FROM WMS_REPL_DEMAND_GTMP
2415 WHERE expected_ship_date < (SYSDATE - p_scheduled_ship_date_from);
2416 END IF;
2417
2418
2419 -- NOTE: Only those records were inserted in the GTMP table for which there is no detailed reservation
2420 -- Delete records in the GTMP table for which total demand qty for an
2421 -- item is below the p_Min_repl_qty_threshold (Minimum threshold for Replenishment);
2422
2423 IF p_Min_repl_qty_threshold is NOT NULL THEN
2424 DELETE FROM WMS_REPL_DEMAND_GTMP
2425 WHERE (inventory_item_id)
2426 IN (SELECT inventory_item_id
2427 from WMS_REPL_DEMAND_GTMP
2428 where organization_id = p_organization_id
2429 group by inventory_item_id
2430 having sum(quantity_in_repl_uom) < p_Min_repl_qty_threshold);
2431
2432 END IF;
2433
2434
2435 -- Delete records in the GTMP table for which number of order lines are below p_Min_Order_lines_threshold
2436 -- (Minimum Order lines threshold)
2437 IF p_Min_Order_lines_threshold IS NOT NULL THEN
2438 DELETE FROM WMS_REPL_DEMAND_GTMP
2439 where(inventory_item_id) in
2440 (SELECT inventory_item_id from WMS_REPL_DEMAND_GTMP
2441 where organization_id = p_organization_id group by inventory_item_id
2442 having count(1) < Nvl(p_min_order_lines_threshold,1));
2443
2444 END IF;
2445 EXCEPTION
2446 WHEN OTHERS THEN
2447 IF (l_debug = 1) THEN
2448 print_debug('Error inserting wms_repl_demand_gtmp table');
2449 END IF;
2450 -- caller rollsback everything if error
2451 x_return_status := fnd_api.g_ret_sts_error;
2452 RETURN;
2453 END;
2454
2455
2456 -- Sort the remaining records based on the Sort Criteria specified (1 =
2457 --Total Demand Quantity; 2= Number of Order lines)
2458 --and then apply the filter p_max_NUM_items_for_repl ( Number of Items to be considered for Replenishment )
2459 -- Now the cursor c_consol_item_repl_cur will apply two filter: p_sort_criteria and p_max_num_items_for_repl
2460 -- Now store these final Item records for consolidated demand in the PL/SQL table
2461 -- l_consol_item_repl_tbl . This PL/SQL table will have more information (available onhand qty
2462 -- open move order qty and final_replenishment_qty populated in later calculation.
2463
2464 -- USE BULK UPLOAD
2465
2466 -- Clear tables for bulk operation
2467 l_item_id_tb.DELETE;
2468 l_total_demand_qty_tb.DELETE;
2469 l_date_required_tb.DELETE;
2470
2471 BEGIN
2472 OPEN c_item_repl_cur;
2473 FETCH c_item_repl_cur BULK COLLECT INTO l_item_id_tb, l_total_demand_qty_tb, l_date_required_tb;
2474 CLOSE c_item_repl_cur;
2475 EXCEPTION
2476 WHEN OTHERS THEN
2477 IF (l_debug = 1) THEN
2478 print_debug('Exception retrieving item repl records');
2479 END IF;
2480 x_return_status := fnd_api.g_ret_sts_error;
2481 -- caller rollback everything if error
2482 RETURN;
2483 END;
2484
2485 IF (l_debug = 1) THEN
2486 print_debug('Total Number of consolidate Repl Records:'||l_item_id_tb.COUNT);
2487 END IF;
2488
2489
2490
2491 -- Proceed following only if anything need to be processed
2492 IF l_item_id_tb.COUNT = 0 THEN
2493
2494 IF (l_debug = 1) THEN
2495 print_debug('No record to be processed..Exiting');
2496 END IF;
2497
2498
2499 ELSE -- means there are records are to be processed
2500
2501 --Clear consolidated table
2502 x_consol_item_repl_tbl.DELETE;
2503 IF (l_item_id_tb.count>0) THEN --bug#10185153
2504 FOR k IN l_item_id_tb.FIRST .. l_item_id_tb.LAST LOOP
2505 x_consol_item_repl_tbl(k).Organization_id := p_organization_id;
2506 x_consol_item_repl_tbl(k).Item_id := l_item_id_tb(k);
2507 x_consol_item_repl_tbl(k).total_demand_qty := l_total_demand_qty_tb(k);
2508 x_consol_item_repl_tbl(k).date_required := l_date_required_tb(k);
2509
2510 x_consol_item_repl_tbl(k).available_onhand_qty := 0; --calculated later
2511 x_consol_item_repl_tbl(k).open_mo_qty := 0; --calculated later
2512 x_consol_item_repl_tbl(k).final_replenishment_qty := 0; --calculated later
2513
2514 x_consol_item_repl_tbl(k).repl_to_subinventory_code := P_Forward_Pick_sub; --same for batch
2515 x_consol_item_repl_tbl(k).repl_uom_code := p_repl_UOM; --same for a batch
2516
2517 END LOOP;
2518 END IF;
2519
2520
2521
2522 -- ===========================================
2523 -- Delete all records from the GTMP table for all items that is not part
2524 -- of the l_consol_item_repl_tbl pl/sql table. here are steps TO DO it
2525
2526 --1- BULK Insert again all item records in the PL/SQL table with
2527 -- Filter_item_flag columns = 'Y into the GTMP table, We want to keep
2528 -- all original item records in GTMP that corresponds to these newly inserted item_id records
2529 --2-Delete those item records in the GTMP table whose item_ids are not same as item_id
2530 -- records that correspond to Filter_item_flag columns = Y records
2531 --3-Remove all records in the table that correspond to Filter_item_flag columns = 'Y'
2532 -- ===========================================
2533
2534 --1 BULK Insert again all item records in the PL/SQL table with
2535 BEGIN
2536 FORALL k IN 1 .. l_item_id_tb.COUNT
2537 INSERT INTO WMS_REPL_DEMAND_GTMP
2538 (Repl_Sequence_id,
2539 repl_level,
2540 Inventory_item_id,
2541 Organization_id,
2542 demand_header_id,
2543 demand_line_id,
2544 demand_line_detail_id,
2545 demand_type_id,
2546 quantity_in_repl_uom,
2547 REPL_UOM_code,
2548 Quantity,
2549 Uom_code,
2550 Expected_ship_date,
2551 Repl_To_Subinventory_code,
2552 filter_item_flag,
2553 repl_status,
2554 repl_type,
2555 RELEASED_STATUS)
2556 VALUES
2557 (WMS_REPL_DEMAND_GTMP_S.NEXTVAL,
2558 p_repl_level,
2559 l_item_id_tb(k),
2560 p_organization_id, --for push repl, it is same though
2561 -9999,
2562 -9999,
2563 -9999,
2564 -9999,
2565 -9999,
2566 p_repl_UOM,
2567 -9999,
2568 '@@@',
2569 l_date_required_tb(k),
2570 P_Forward_Pick_Sub,
2571 'Y',
2572 NULL,
2573 1, -- For Push replenishment
2574 NULL);
2575
2576
2577 --2 Delete those item records in the GTMP table whose item_ids are not same as item_id
2578 --records that correspond to Filter_item_flag columns = 'Y' records
2579 DELETE FROM wms_repl_demand_gtmp
2580 WHERE filter_item_flag IS NULL
2581 AND inventory_item_id NOT IN (SELECT inventory_item_id FROM
2582 wms_repl_demand_gtmp WHERE
2583 Nvl(filter_item_flag,'N') = 'Y');
2584
2585
2586 --3 Remove all records in the table that correspond to Filter_item_flag columns = 'Y'
2587 DELETE FROM wms_repl_demand_gtmp
2588 WHERE filter_item_flag = 'Y';
2589
2590 EXCEPTION
2591 WHEN OTHERS THEN
2592 IF (l_debug = 1) THEN
2593 print_debug('Error inserting in WRDG temp table with Filter_item_flag = y : '||SQLCODE ||' '||SQLERRM);
2594 END IF;
2595 -- caller rollsback everything if error
2596 x_return_status := fnd_api.g_ret_sts_error;
2597 x_consol_item_repl_tbl.DELETE;
2598 RETURN;
2599 END;
2600
2601
2602 -- Discard all demand lines from Push Repl consideration that could not be
2603 -- Fulfilled BY available Effective atr in the entire the organizatrion
2604 -- Adjust ALL qty in consol_table and GTMP accordingly for all items
2605 IF x_consol_item_repl_tbl.COUNT() <> 0 THEN
2606 ADJUST_ATR_FOR_ITEM (p_repl_level => p_repl_level
2607 , p_repl_type => g_push_repl
2608 , x_consol_item_repl_tbl => x_consol_item_repl_tbl
2609 , x_return_status => l_return_status
2610 );
2611
2612 IF l_return_status <> 'S' THEN
2613 IF l_debug = 1 THEN
2614 print_debug('API ADJUST_ATR_FOR_ITEM returned error');
2615 END IF;
2616 x_return_status := fnd_api.g_ret_sts_error;
2617 x_consol_item_repl_tbl.DELETE;
2618 RETURN;
2619 END IF;
2620
2621 IF l_debug = 1 THEN
2622 print_debug('Return Status after call to ADJUST_ATR_FOR_ITEM :'|| l_return_status);
2623 END IF;
2624
2625 END IF;
2626
2627 --=====================TEST CODE STARTS =======
2628 -- ONLY for debugging purpose
2629 IF l_debug = 1 THEN
2630 SELECT COUNT(1) INTO l_temp_cnt FROM wms_repl_demand_gtmp;
2631 print_debug(' FINAL record count in gtmp :'||l_temp_cnt);
2632 print_debug(' number of records in consol table :'||x_consol_item_repl_tbl.COUNT());
2633 END IF;
2634 --=====================TEST CODE ENDS =======
2635
2636 END IF; -- IF l_item_id_tb.COUNT = 0
2637
2638 x_return_status := FND_API.g_ret_sts_success;
2639
2640 IF l_debug = 1 THEN
2641 print_debug('Done with API populate_push_repl_demand');
2642 END IF;
2643
2644 EXCEPTION
2645 WHEN OTHERS THEN
2646 IF (l_debug = 1) THEN
2647 print_debug('Error in populate_push_repl_demand SQLCODE:'||SQLCODE ||' '||SQLERRM );
2648 END IF;
2649 --
2650 -- caller rollsback everything if error
2651 x_return_status := fnd_api.g_ret_sts_unexp_error;
2652 x_consol_item_repl_tbl.DELETE;
2653 --
2654 END populate_push_repl_demand ;
2655
2656 PROCEDURE check_for_next_level_repl(p_move_order_header_id IN NUMBER,
2657 p_move_order_line_id IN NUMBER,
2658 p_organization_id IN NUMBER,
2659 p_inventory_item_id IN NUMBER,
2660 p_repl_level IN NUMBER,
2661 x_source_sub_atr IN OUT nocopy NUMBER,
2662 x_create_qty OUT nocopy VARCHAR2,
2663 x_return_status OUT nocopy VARCHAR2,
2664 x_msg_count OUT nocopy NUMBER,
2665 x_msg_data OUT nocopy VARCHAR2)
2666 IS
2667 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
2668 l_repl_level NUMBER := p_repl_level;
2669 l_create_qty NUMBER := 0; -- 0 to signify it was not created
2670 l_source_sub_atr NUMBER := x_source_sub_atr;
2671 l_pending_mo_qty NUMBER;
2672 l_mo_source_sub VARCHAR2(50);
2673 l_mo_source_loc NUMBER;
2674 l_is_revision_ctrl BOOLEAN := FALSE;
2675 l_is_lot_ctrl BOOLEAN := FALSE;
2676 l_is_serial_ctrl BOOLEAN := FALSE;
2677 l_qoh NUMBER;
2678 l_rqoh NUMBER;
2679 l_qr NUMBER;
2680 l_qs NUMBER;
2681 l_atr NUMBER;
2682 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
2683 l_next_lvl_src_sub VARCHAR(30);
2684 BEGIN
2685 x_create_qty := l_create_qty;
2686 x_return_status := fnd_api.g_ret_sts_success;
2687
2688 IF l_source_sub_atr IS NULL THEN
2689 l_source_sub_atr := -9999;
2690 END IF;
2691
2692 IF l_repl_level IS NULL THEN
2693 BEGIN
2694 SELECT repl_level
2695 INTO l_repl_level
2696 FROM wms_replenishment_details
2697 WHERE source_type_id = 4
2698 AND organization_id = p_organization_id
2699 AND inventory_item_id = p_inventory_item_id
2700 AND source_header_id = p_move_order_header_id
2701 AND source_line_id = p_move_order_line_id
2702 AND ROWNUM = 1;
2703 EXCEPTION
2704 WHEN no_data_found THEN
2705 l_repl_level := 1;
2706 WHEN OTHERS THEN
2707 l_repl_level := 4;
2708 END;
2709 END IF;
2710 IF (l_debug = 1) THEN
2711 print_debug('l_repl_level:'||l_repl_level);
2712 END IF;
2713
2714 IF l_repl_level >= 4 THEN
2715 x_return_status := fnd_api.g_ret_sts_success;
2716 x_create_qty := 0;
2717 RETURN;
2718 END IF;
2719
2720
2721 BEGIN
2722 SELECT (quantity - Nvl(quantity_detailed,0) - Nvl(quantity_delivered,0))
2723 , from_subinventory_code
2724 , from_locator_id
2725 INTO l_create_qty
2726 , l_mo_source_sub
2727 , l_mo_source_loc
2728 FROM mtl_txn_request_lines
2729 WHERE line_id = p_move_order_line_id
2730 AND organization_id = p_organization_id
2731 AND inventory_item_id = p_inventory_item_id;
2732 IF (l_debug = 1) THEN
2733 print_debug('l_create_qty:'||l_create_qty);
2734 print_debug('l_mo_source_sub:'||l_mo_source_sub);
2735 print_debug('l_mo_source_loc:'||l_mo_source_loc);
2736 END IF;
2737 IF ((l_create_qty <= 0) OR (l_mo_source_sub IS NULL)) THEN
2738 x_return_status := fnd_api.g_ret_sts_success;
2739 x_create_qty := 0;
2740 RETURN;
2741 END IF;
2742 select MISI.SOURCE_SUBINVENTORY into l_next_lvl_src_sub
2743 FROM MTL_ITEM_SUB_INVENTORIES MISI
2744 WHERE MISI.organization_id = p_organization_id
2745 and MISI.INVENTORY_ITEM_ID = p_inventory_item_id
2746 and MISI.source_type = 3 --(for Subinventory)
2747 and MISI.SECONDARY_INVENTORY = l_mo_source_sub
2748 AND ROWNUM = 1;
2749
2750 if l_next_lvl_src_sub is NULL then
2751
2752 if (l_debug = 1) THEN
2753 print_debug('Since no next level setup exists, thus returning' );
2754 END IF;
2755 x_create_qty := 0;
2756 x_return_status := fnd_api.g_ret_sts_success;
2757 return;
2758 end if;
2759
2760
2761 IF l_source_sub_atr = -9999 THEN
2762 -- Get all item details
2763 IF inv_cache.set_item_rec(p_ORGANIZATION_ID, p_inventory_item_id) THEN
2764 IF (l_debug = 1) THEN
2765 print_debug('Getting Item Attribute Details' );
2766 END IF;
2767 IF inv_cache.item_rec.revision_qty_control_code = 2 THEN
2768 l_is_revision_ctrl := TRUE;
2769 ELSE
2770 l_is_revision_ctrl := FALSE;
2771 END IF;
2772
2773 IF inv_cache.item_rec.lot_control_code = 2 THEN
2774 l_is_lot_ctrl := TRUE;
2775 ELSE
2776 l_is_lot_ctrl := FALSE;
2777 END IF;
2778
2779 IF inv_cache.item_rec.serial_number_control_code NOT IN (1,6) THEN
2780 l_is_serial_ctrl := FALSE;
2781 ELSE
2782 l_is_serial_ctrl := TRUE;
2783 END IF;
2784
2785 ELSE
2786 IF (l_debug = 1) THEN
2787 print_debug('Error: Item detail not found');
2788 END IF;
2789 x_return_status := fnd_api.g_ret_sts_success;
2790 x_create_qty := 0;
2791 END IF; -- for inv_cache.set_item_rec
2792
2793 IF (l_debug = 1) THEN
2794 print_debug('Clearing Qty Tree' );
2795 END IF;
2796 --Query Quantity Tree
2797 inv_quantity_tree_pub.clear_quantity_cache;
2798
2799 IF (l_debug = 1) THEN
2800 print_debug('Calling Qty Tree API' );
2801 END IF;
2802
2803 inv_quantity_tree_pub.query_quantities
2804 (
2805 p_api_version_number => 1.0
2806 , p_init_msg_lst => fnd_api.g_false
2807 , x_return_status => l_return_status
2808 , x_msg_count => x_msg_count
2809 , x_msg_data => x_msg_data
2810 , p_organization_id => p_organization_id
2811 , p_inventory_item_id => p_inventory_item_id
2812 , p_tree_mode => inv_quantity_tree_pub.g_transaction_mode
2813 , p_is_revision_control => l_is_revision_ctrl
2814 , p_is_lot_control => l_is_lot_ctrl
2815 , p_is_serial_control => l_is_serial_ctrl
2816 , p_demand_source_type_id => -9999 --should not be null
2817 , p_demand_source_header_id => -9999 --should not be null
2818 , p_demand_source_line_id => -9999
2819 , p_revision => NULL
2820 , p_lot_number => NULL
2821 , p_subinventory_code => l_mo_source_sub
2822 , p_locator_id => l_mo_source_loc
2823 , x_qoh => l_qoh
2824 , x_rqoh => l_rqoh
2825 , x_qr => l_qr
2826 , x_qs => l_qs
2827 , x_att => l_source_sub_atr
2828 , x_atr => l_atr
2829 );
2830
2831 IF (l_debug = 1) THEN
2832 print_debug( 'Return status from QTY TREE:' ||x_return_status);
2833 END IF;
2834 IF l_return_status = fnd_api.g_ret_sts_success THEN
2835 x_source_sub_atr := l_source_sub_atr;
2836 ELSE
2837 l_source_sub_atr := -9999;
2838 END IF;
2839 END IF;
2840 IF (l_debug = 1) THEN
2841 print_debug( 'l_source_sub_atr is: '||l_source_sub_atr);
2842 END IF;
2843 IF l_source_sub_atr <= 0 THEN
2844 x_return_status := fnd_api.g_ret_sts_success;
2845 x_create_qty := l_create_qty;
2846 x_source_sub_atr := 0;
2847 RETURN;
2848 END IF;
2849 x_return_status := fnd_api.g_ret_sts_success;
2850 x_create_qty := 0;
2851 EXCEPTION
2852 WHEN OTHERS THEN
2853 x_return_status := fnd_api.g_ret_sts_success;
2854 x_create_qty := 0;
2855 x_source_sub_atr := NULL;
2856 END;
2857 END check_for_next_level_repl;
2858
2859 PROCEDURE trigger_next_level_repl(p_repl_level IN NUMBER
2860 , p_repl_lot_size IN NUMBER
2861 , p_plan_tasks IN VARCHAR2
2862 , x_return_status OUT nocopy VARCHAR2)
2863 IS
2864 l_return_status VARCHAR2(3);
2865 l_org_id_tb num_tab;
2866 l_item_id_tb num_tab;
2867 l_repl_to_sub_code_tb char_tab;
2868 l_repl_UOM_CODE_tb uom_tab;
2869 l_total_demand_qty_tb num_tab;
2870 l_consol_item_repl_tbl consol_item_repl_tbl;
2871 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
2872
2873 l_msg_count NUMBER;
2874 l_msg_data VARCHAR2(1000);
2875
2876 CURSOR c_distinct_org_id IS
2877 SELECT DISTINCT organization_id
2878 FROM wms_repl_demand_gtmp
2879 WHERE repl_level = p_repl_level;
2880
2881 CURSOR c_item_repl_cur(v_org_id NUMBER) IS
2882 SELECT inventory_item_id,
2883 sum(quantity_in_repl_uom) as total_demand_qty,
2884 repl_to_subinventory_code,
2885 repl_uom_code
2886 FROM wms_repl_demand_gtmp
2887 WHERE organization_id = v_org_id
2888 AND repl_level = p_repl_level
2889 GROUP BY inventory_item_id, repl_to_subinventory_code,repl_uom_code
2890 ORDER BY inventory_item_id, repl_to_subinventory_code;
2891
2892 BEGIN
2893 l_org_id_tb.DELETE;
2894 l_return_status := fnd_api.g_ret_sts_success;
2895
2896 IF (l_debug = 1) THEN
2897 print_debug('Inside API trigger_next_level_repl');
2898 END IF;
2899
2900 BEGIN
2901 OPEN c_distinct_org_id;
2902 FETCH c_distinct_org_id bulk collect INTO l_org_id_tb;
2903 CLOSE c_distinct_org_id;
2904 EXCEPTION
2905 WHEN OTHERS THEN
2906 x_return_status := fnd_api.g_ret_sts_error;
2907 DELETE FROM wms_repl_demand_gtmp WHERE repl_level = p_repl_level;
2908 IF (l_debug = 1) THEN
2909 print_debug('Exception getting orgs:'||p_repl_level);
2910 END IF;
2911 RETURN;
2912 END;
2913
2914 FOR j IN 1..l_org_id_tb.COUNT loop
2915 l_item_id_tb.DELETE;
2916 l_total_demand_qty_tb.DELETE;
2917 l_repl_to_sub_code_tb.DELETE;
2918 l_repl_uom_code_tb.DELETE;
2919 BEGIN
2920
2921 SAVEPOINT new_org_sp;
2922
2923 OPEN c_item_repl_cur(l_org_id_tb(j));
2924 FETCH c_item_repl_cur BULK COLLECT INTO l_item_id_tb,
2925 l_total_demand_qty_tb,
2926 l_repl_to_sub_code_tb,l_repl_uom_code_tb;
2927 CLOSE c_item_repl_cur;
2928
2929 l_consol_item_repl_tbl.DELETE;
2930 IF (l_item_id_tb.count>0) THEN --bug#10185153
2931 FOR k IN l_item_id_tb.FIRST .. l_item_id_tb.LAST LOOP
2932 l_consol_item_repl_tbl(k).Organization_id := l_org_id_tb(j);
2933 l_consol_item_repl_tbl(k).Item_id := l_item_id_tb(k);
2934 l_consol_item_repl_tbl(k).total_demand_qty := l_total_demand_qty_tb(k);
2935 l_consol_item_repl_tbl(k).date_required := sysdate;
2936
2937 l_consol_item_repl_tbl(k).available_onhand_qty := 0;
2938 l_consol_item_repl_tbl(k).open_mo_qty := 0;
2939 l_consol_item_repl_tbl(k).final_replenishment_qty := 0;
2940
2941 l_consol_item_repl_tbl(k).repl_to_subinventory_code := l_repl_to_sub_code_tb(k);
2942 l_consol_item_repl_tbl(k).repl_uom_code := l_repl_uom_code_tb(k);
2943
2944 l_consol_item_repl_tbl(k).final_replenishment_qty:= l_total_demand_qty_tb(k);
2945 END LOOP;
2946 END IF;
2947
2948 IF l_consol_item_repl_tbl.COUNT <> 0 THEN
2949 PROCESS_REPLENISHMENT (
2950 P_repl_level => P_repl_level,
2951 p_repl_type => 2,
2952 p_Repl_Lot_Size => p_Repl_Lot_Size,
2953 P_consol_item_repl_tbl => l_consol_item_repl_tbl,
2954 p_Create_Reservation => 'N',
2955 p_Auto_Allocate => 'Y',
2956 p_Plan_Tasks => p_Plan_Tasks,
2957 x_return_status => l_return_status ,
2958 x_msg_count => l_msg_count ,
2959 x_msg_data => l_msg_data );
2960
2961 IF l_return_status <> 'S' THEN
2962 IF (l_debug = 1) THEN
2963 print_debug('Error performing replenishment for Multi-step');
2964 END IF;
2965 ROLLBACK TO new_org_sp;
2966 DELETE FROM wms_repl_demand_gtmp
2967 WHERE repl_level = p_repl_level
2968 AND organization_id = l_org_id_tb(j);
2969 GOTO next_org;
2970 END IF;
2971 ELSE
2972 IF (l_debug = 1) THEN
2973 print_debug('No Demand Records Identified for this level..Exiting...');
2974 END IF;
2975 END IF;
2976
2977
2978 EXCEPTION
2979 WHEN OTHERS THEN
2980 IF (l_debug = 1) THEN
2981 print_debug('Exception retrieving item repl records for Multi-step');
2982 END IF;
2983 ROLLBACK TO new_org_sp;
2984 DELETE FROM wms_repl_demand_gtmp
2985 WHERE repl_level = p_repl_level
2986 AND organization_id = l_org_id_tb(j);
2987 GOTO next_org;
2988 END;
2989
2990 <<next_org>>
2991 NULL;
2992 END LOOP; -- org loop
2993
2994
2995 IF l_debug = 1 THEN
2996 print_debug('DONE WITH API trigger_next_level_repl');
2997 END IF;
2998 x_return_status := fnd_api.g_ret_sts_success;
2999
3000 EXCEPTION
3001 WHEN OTHERS THEN
3002 IF l_debug = 1 THEN
3003 print_debug('Exception in trigger_next_level_repl: ' || sqlcode || ', ' || sqlerrm);
3004 END IF;
3005
3006 END trigger_next_level_repl;
3007
3008
3009 PROCEDURE PROCESS_REPLENISHMENT( p_Repl_level IN NUMBER,
3010 p_repl_type IN NUMBER,
3011 p_Repl_Lot_Size IN NUMBER,
3012 P_consol_item_repl_tbl IN OUT NOCOPY CONSOL_ITEM_REPL_TBL,
3013 p_Create_Reservation IN VARCHAR2,
3014 p_Auto_Allocate IN VARCHAR2,
3015 p_Plan_Tasks IN VARCHAR2,
3016 x_return_status OUT NOCOPY VARCHAR2,
3017 x_msg_count OUT NOCOPY NUMBER,
3018 x_msg_data OUT NOCOPY
3019 VARCHAR2)
3020 IS
3021
3022 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
3023 l_temp_cnt NUMBER; -- for debugging only
3024 l_repl_level NUMBER;
3025 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
3026
3027 BEGIN
3028 x_return_status := l_return_status;
3029
3030 -- At this point WMS_REPL_DEMAND_GTMP table should have all the correct demand records and
3031 --l_consol_item_repl_tbl should have all the consolidated quantities grouped by for Item_Id and Repl_To_Subinventory_Code.
3032 -- Now for each entry in the p_consol_item_repl_tbl, get available onhand qty and update records in the p_consol_item_repl_tbl.
3033
3034 -- it does not make sense to net off onhand/open MOs for
3035 -- next level of Replenishment MOs
3036 -- We would get the quantity after the first level made use
3037 -- of the atr, open MOs and the remaining qty on first level repl
3038 -- MO could not be allocated.
3039 IF (Nvl(p_repl_level,1) = 1) THEN
3040 GET_AVAILABLE_ONHAND_QTY(p_repl_level => p_repl_level,
3041 p_repl_type => p_repl_type,
3042 p_Create_Reservation => p_Create_Reservation,
3043 x_consol_item_repl_tbl => P_consol_item_repl_tbl,
3044 x_return_status => l_return_status,
3045 x_msg_count => x_msg_count,
3046 x_msg_data => x_msg_data);
3047 IF l_return_status <> fnd_api.g_ret_sts_success THEN
3048 x_return_status := fnd_api.g_ret_sts_error;
3049 RETURN;
3050 END IF;
3051 END IF;
3052
3053
3054 -- ==========TEST CODE start ===========
3055 -- for debugging purpise only, entire code should be inside l_debug = 1
3056 IF (l_debug = 1) THEN
3057 IF P_consol_item_repl_tbl.COUNT <> 0 THEN
3058 print_debug('*******AFTER GET_AVAILABLE_ONHAND_QTY*******');
3059
3060 FOR i IN p_consol_item_repl_tbl.FIRST .. p_consol_item_repl_tbl.LAST LOOP
3061 IF (NOT p_consol_item_repl_tbl.exists(i)) THEN
3062 IF (l_debug = 1) THEN
3063 print_debug('CURRENT INDEX IN THE CONSOL TABLE HAS BEEN Discarded - moving TO next consol RECORD' );
3064 END IF;
3065 ELSE
3066 IF (l_debug = 1) THEN
3067 print_debug('ITEM_ID, Total_qty, available_OH, open_MO_QTY, Final_repl_qty ');
3068 print_debug( p_consol_item_repl_tbl(i).ITEM_ID || ' , ' ||
3069 p_consol_item_repl_tbl(i).total_demand_qty || ' , '||
3070 p_consol_item_repl_tbl(i).available_onhand_qty|| ' , '||
3071 p_consol_item_repl_tbl(i).open_mo_qty|| ' , '||
3072 p_consol_item_repl_tbl(i).final_replenishment_qty);
3073
3074 END IF;
3075 END IF;
3076 END LOOP;
3077
3078 SELECT COUNT(1) INTO l_temp_cnt FROM wms_repl_demand_gtmp;
3079 IF (l_debug = 1) THEN
3080 print_debug(' NUMBER OF RECORDS IN wms_repl_demand_gtmp l_temp_cnt :'||l_temp_cnt);
3081 END IF;
3082 END IF;
3083 END IF;
3084
3085 -- ==========TEST CODE ends ===========
3086
3087
3088 -- For Each Item, Net Off on Hand on the Forward Pick Subinventory passed in the program
3089 -- and keep updating l_consol_item_repl_tbl(l_index).final_replenishment_qty as well
3090 -- Now for each entry in the P_consol_item_repl_tbl, get
3091 --Open move order qty and update records in the P_consol_item_repl_tbl.
3092
3093 -- it does not make sense to net off onhand/open MOs for
3094 -- next level of Replenishment MOs
3095 -- We would get the quantity after the first level made use
3096 -- of the atr, open MOs and the remaining qty on first level repl
3097 -- MO could not be allocated.
3098 IF (Nvl(p_repl_level,1) = 1) THEN
3099 GET_OPEN_MO_QTY(p_repl_level => p_repl_level,
3100 p_repl_type => p_repl_type,
3101 p_Create_Reservation => p_Create_Reservation,
3102 x_consol_item_repl_tbl => P_consol_item_repl_tbl,
3103 x_return_status => l_return_status,
3104 x_msg_count => x_msg_count,
3105 x_msg_data => x_msg_data);
3106 IF l_return_status <> fnd_api.g_ret_sts_success THEN
3107 x_return_status := fnd_api.g_ret_sts_error;
3108 RETURN;
3109 END IF;
3110 END IF;
3111
3112
3113 -- ==========TEST CODE starts ===========
3114 -- for debugging purpise only, entire code should be inside l_debug = 1
3115 IF (l_debug = 1) THEN
3116 IF P_consol_item_repl_tbl.COUNT <> 0 THEN
3117 print_debug('********AFTER GET_OPEN_MO_QTY API call*******');
3118
3119 FOR i IN p_consol_item_repl_tbl.FIRST .. p_consol_item_repl_tbl.LAST LOOP
3120 IF (NOT p_consol_item_repl_tbl.exists(i)) THEN
3121 IF (l_debug = 1) THEN
3122 print_debug('CURRENT INDEX IN THE CONSOL TABLE HAS BEEN Discarded - moving TO next consol RECORD' );
3123 END IF;
3124 ELSE
3125
3126 IF (l_debug = 1) THEN
3127 print_debug('ITEM_ID, Total_qty, available_OH, open_MO_QTY, Final_repl_qty ');
3128 print_debug( p_consol_item_repl_tbl(i).ITEM_ID || ' , ' ||
3129 p_consol_item_repl_tbl(i).total_demand_qty || ' , '||
3130 p_consol_item_repl_tbl(i).available_onhand_qty|| ' , '||
3131 p_consol_item_repl_tbl(i).open_mo_qty|| ' , '||
3132 p_consol_item_repl_tbl(i).final_replenishment_qty);
3133
3134 END IF;
3135 END IF;
3136 END LOOP;
3137 END IF;
3138 END IF; -- IF (l_debug = 1) THEN
3139 -- ==========TEST CODE ends ===========
3140
3141
3142 -- For Each Item, Net Off Open Move Orders in the Forward Pick Subinventory and keep updating l_consol_item_repl_tbl(l_index).final_replenishment_qty as well
3143 -- At this point P_consol_item_repl_tbl should have total replenishment quantity to create MO for. It is done inside the API - GET_OPEN_MO_QTY().
3144 -- Now create Replenishment Move Orders for effective demand that could not be fulfilled by available onhand or open move order
3145 -- Make sure to upp the replenishment quantity in the
3146 --p_consol_item_repl_tbl(l_index).final_replenishment_qty
3147 -- based on the p_Repl_Lot_Size parameter passed in the program. other
3148 -- parameters p_Create_Reservation, p_Auto_Allocate AND p_Plan_Tasks parameters will be honored inside following call.
3149
3150
3151 CREATE_REPL_MOVE_ORDER(p_repl_level => p_repl_level,
3152 p_repl_type => p_repl_type,
3153 P_consol_item_repl_tbl => P_consol_item_repl_tbl,
3154 p_Create_Reservation => p_Create_Reservation,
3155 p_Repl_Lot_Size => p_Repl_Lot_Size,
3156 p_Auto_Allocate => p_Auto_Allocate,
3157 p_Plan_Tasks => p_Plan_Tasks,
3158 x_return_status => l_return_status,
3159 x_msg_count => x_msg_count,
3160 x_msg_data => x_msg_data);
3161 IF l_return_status <> fnd_api.g_ret_sts_success THEN
3162 x_return_status := fnd_api.g_ret_sts_error;
3163 RETURN;
3164 END IF;
3165
3166
3167 --TODO : Satish
3168 -- Delete from WMS_REPL_DEMAND_GTMP for current level of replenishment. There might be records remaining in this table for the mext level of replenishment.
3169 -- Trigger next level of replenishment IF
3170 -- Replenishment level < 4 (Ea < CS < PLT < SupPLT)
3171 -- And there are records in the GTMP for the next level. It should have been already inserted by now
3172
3173
3174 DELETE FROM wms_repl_demand_gtmp WHERE repl_level=Nvl(p_repl_level,1);
3175
3176
3177 x_return_status := 'S';
3178
3179 --TODO: Blocking Multi-Level Code changes
3180 -- Multi step change
3181 IF ((p_repl_level < 4) AND (p_auto_allocate = 'Y')) THEN
3182 BEGIN
3183
3184 l_repl_level := Nvl(p_repl_level,1) + 1;
3185 COMMIT;
3186
3187 IF (l_debug = 1) THEN
3188 print_debug('STARTING THE NEXT LEVEL REPL :'||L_repl_level);
3189 END IF;
3190
3191
3192
3193 trigger_next_level_repl(p_repl_level => l_repl_level
3194 , p_repl_lot_size => p_repl_lot_size
3195 , p_plan_tasks => p_plan_tasks
3196 , x_return_status => l_return_status);
3197 EXCEPTION
3198 WHEN OTHERS THEN
3199 l_return_status := 'E';
3200 END;
3201 IF l_return_status <> 'S' THEN
3202 DELETE FROM wms_repl_demand_gtmp WHERE repl_level = (Nvl(p_repl_level,1)+1);
3203 END IF;
3204
3205 END IF;
3206
3207
3208 EXCEPTION
3209 WHEN OTHERS THEN
3210 IF l_debug = 1 THEN
3211 print_debug('PROCESS_REPLENISHMENT: Exception block: ' || sqlcode || ', ' || sqlerrm);
3212 END IF;
3213 --
3214 x_return_status := fnd_api.g_ret_sts_unexp_error;
3215 --
3216 END PROCESS_REPLENISHMENT;
3217
3218
3219
3220
3221 PROCEDURE CREATE_REPL_MOVE_ORDER(p_Repl_level IN NUMBER,
3222 p_repl_type IN NUMBER,
3223 p_consol_item_repl_tbl IN OUT NOCOPY CONSOL_ITEM_REPL_TBL,
3224 p_Create_Reservation IN VARCHAR2,
3225 p_Repl_Lot_Size IN NUMBER,
3226 p_Auto_Allocate IN VARCHAR2,
3227 p_Plan_Tasks IN VARCHAR2,
3228 x_return_status OUT NOCOPY VARCHAR2,
3229 x_msg_count OUT NOCOPY NUMBER,
3230 x_msg_data OUT NOCOPY VARCHAR2
3231 )
3232 IS
3233
3234 -- Note: UI will insure that if p_Create_Reservation = No then p_Auto_Allocate must be No
3235 -- In case of Push Replenishement, once all replenishment tasks are
3236 -- completed, user will perform pick release manually.
3237 -- Just to keep in mind, we do not distinguish dynamic and push in the Allocate_repl_move_order Conc Request
3238
3239 l_trohdr_rec INV_Move_Order_PUB.Trohdr_Rec_Type;
3240 l_trohdr_val_rec INV_Move_Order_PUB.Trohdr_Val_Rec_Type;
3241 l_x_trohdr_rec INV_Move_Order_PUB.Trohdr_Rec_Type;
3242 l_x_trohdr_val_rec INV_Move_Order_PUB.Trohdr_Val_Rec_Type;
3243 l_commit VARCHAR2(1) := FND_API.G_TRUE;
3244
3245 l_trolin_tbl INV_Move_Order_PUB.Trolin_Tbl_Type;
3246 l_trolin_val_tbl INV_Move_Order_PUB.Trolin_Val_Tbl_Type;
3247 l_x_trolin_tbl INV_Move_Order_PUB.Trolin_Tbl_Type;
3248 l_x_trolin_val_tbl INV_Move_Order_PUB.Trolin_Val_Tbl_Type;
3249
3250 l_return_status VARCHAR2(1);
3251 l_msg_count NUMBER;
3252 l_msg_data VARCHAR2(1000);
3253 l_msg VARCHAR2(250);
3254 l_plan_tasks BOOLEAN;
3255 l_repl_lot_size_prim NUMBER;
3256
3257 -- Multi step change
3258 l_source_sub_atr NUMBER;
3259 l_create_qty NUMBER;
3260 l_prev_item_id NUMBER;
3261 l_prev_sub_code VARCHAR2(10);
3262
3263 l_item_id_tb num_tab;
3264 l_org_id_tb num_tab;
3265 l_demand_header_id_tb num_tab;
3266 l_demand_line_id_tb num_tab;
3267 l_demand_type_id_tb num_tab;
3268 l_requested_quantity_tb num_tab;
3269 l_requested_quantity_uom_tb uom_tab;
3270 l_quantity_in_repl_uom_tb num_tab;
3271 l_expected_ship_date_tb date_tab;
3272 l_repl_to_sub_code_tb char_tab;
3273 l_repl_UOM_CODE_tb uom_tab;
3274 l_next_repl_cntr NUMBER := 0;
3275
3276 l_del_index NUMBER;
3277 l_del_consol_item_tb num_tab;
3278
3279 l_src_sub VARCHAR2(10);
3280 l_order_count NUMBER ;
3281
3282 l_demand_header_id NUMBER;
3283 L_demand_line_id NUMBER;
3284 L_demand_line_detail_id NUMBER;
3285 L_demand_quantity NUMBER;
3286 L_demand_quantity_in_repl_uom NUMBER;
3287 L_demand_uom_code VARCHAR2(3);
3288 L_demand_type_id NUMBER;
3289 L_sequence_id NUMBER;
3290 l_expected_ship_date date;
3291 l_repl_level NUMBER;
3292 l_repl_type NUMBER;
3293
3294 l_repl_UOM_code VARCHAR2(3);
3295 l_Repl_Lot_Size NUMBER;
3296
3297 l_rsv_tbl_tmp inv_reservation_global.mtl_reservation_tbl_type;
3298 l_rsv_rec inv_reservation_global.mtl_reservation_tbl_type;
3299 l_serial_number inv_reservation_global.serial_number_tbl_type;
3300 l_to_serial_number inv_reservation_global.serial_number_tbl_type;
3301 l_quantity_reserved NUMBER;
3302 l_quantity_reserved2 NUMBER;
3303 l_rsv_id NUMBER;
3304 l_error_code NUMBER;
3305 l_mo_uom_code VARCHAR2(3);
3306
3307 l_detail_info_tab WSH_INTERFACE_EXT_GRP.delivery_details_Attr_tbl_Type;
3308 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
3309 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
3310
3311 l_rsv_temp_rec inv_reservation_global.mtl_reservation_rec_type;
3312 l_rsv_temp_rec_2 inv_reservation_global.mtl_reservation_rec_type;
3313 l_line_num NUMBER ;
3314
3315 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
3316
3317 l_index NUMBER;
3318 l_prev_org_id NUMBER;
3319 l_MAX_MINMAX_QUANTITY NUMBER;
3320 l_mtl_reservation_count NUMBER;
3321 l_fixed_lot_multiple NUMBER;
3322 l_src_pick_uom VARCHAR2(3);
3323 l_txn_prim_qty NUMBER;
3324
3325
3326 -- For bulk upload in the WRD table
3327 l_organization_id_tab num_tab;
3328 l_mo_header_id_tab num_tab;
3329 l_mo_line_id_tab num_tab;
3330 l_demand_header_id_tab num_tab;
3331 l_demand_line_id_tab num_tab;
3332 l_demand_line_detail_id_tab num_tab;
3333 l_demand_type_id_tab num_tab;
3334 l_item_id_tab num_tab;
3335 l_demand_uom_code_tab uom_tab;
3336 l_demand_quantity_tab num_tab;
3337 l_sequence_id_tab num_tab;
3338 l_repl_level_tab num_tab;
3339 l_repl_type_tab num_tab;
3340
3341 l_conversion NUMBER;
3342
3343 l_quantity_detailed NUMBER;
3344 l_quantity_detailed_conv NUMBER;
3345 l_num_detail_recs NUMBER;
3346 l_prim_quantity_detailed NUMBER;
3347 l_mo_line_id NUMBER;
3348 l_task_id NUMBER;
3349
3350 CURSOR c_demand_lines_for_item(p_org_id NUMBER, p_item_id number, P_FP_SUB VARCHAR2) IS
3351 Select repl_sequence_id,
3352 demand_header_id,
3353 demand_line_id,
3354 demand_line_detail_id,
3355 demand_type_id,
3356 quantity,
3357 uom_code,
3358 expected_ship_date,
3359 quantity_in_repl_uom,
3360 repl_uom_code,
3361 Nvl(repl_level,1),
3362 repl_type
3363 FROM WMS_REPL_DEMAND_GTMP
3364 WHERE ORGANIZATION_ID = p_org_id
3365 AND inventory_item_id = p_item_id
3366 AND REPL_TO_SUBINVENTORY_CODE = P_FP_SUB
3367 order by Repl_Sequence_id;
3368
3369 CURSOR c_mmtt_rec IS
3370 SELECT transaction_temp_id
3371 FROM mtl_material_transactions_temp
3372 WHERE move_order_line_id = l_mo_line_id;
3373
3374 BEGIN
3375 --Note: by the time this API is called p_consol_item_repl_tbl(i).final_replenishment_qty
3376 -- will store the Correct qty (rounded up) to create replenishment MO for each Item
3377
3378 l_src_sub := NULL;
3379
3380 l_trohdr_rec.created_by := fnd_global.user_id;
3381 l_trohdr_rec.creation_date := sysdate;
3382 l_trohdr_rec.header_status := INV_Globals.g_to_status_preapproved;
3383 l_trohdr_rec.last_updated_by := fnd_global.user_id;
3384 l_trohdr_rec.last_update_date := sysdate;
3385 l_trohdr_rec.last_update_login := fnd_global.user_id;
3386 l_trohdr_rec.organization_id := NULL; -- assigned inside the loop
3387 l_trohdr_rec.status_date := sysdate;
3388 l_trohdr_rec.move_order_type := INV_GLOBALS.G_MOVE_ORDER_REPLENISHMENT;
3389 l_trohdr_rec.transaction_type_id := INV_GLOBALS.G_TYPE_TRANSFER_ORDER_SUBXFR;
3390 l_trohdr_rec.operation := INV_GLOBALS.G_OPR_CREATE;
3391 l_trohdr_rec.db_flag := FND_API.G_TRUE;
3392
3393 -- Multi step change
3394 l_item_id_tb.DELETE;
3395 l_org_id_tb.DELETE;
3396 l_demand_header_id_tb.DELETE;
3397 l_demand_line_id_tb.DELETE;
3398 l_demand_type_id_tb.DELETE;
3399 l_requested_quantity_tb.DELETE;
3400 l_requested_quantity_uom_tb.DELETE;
3401 l_quantity_in_repl_uom_tb.DELETE;
3402 l_expected_ship_date_tb.DELETE;
3403 l_repl_to_sub_code_tb.DELETE;
3404 l_repl_uom_code_tb.DELETE;
3405 l_next_repl_cntr := 1;
3406
3407
3408 IF l_debug = 1 THEN
3409 print_debug('Inside the API CREATE_REPL_MOVE_ORDER');
3410 END IF;
3411
3412 l_del_index := 0;
3413 IF (p_consol_item_repl_tbl.count>0) THEN --bug#10185153
3414 FOR i IN p_consol_item_repl_tbl.FIRST.. p_consol_item_repl_tbl.LAST LOOP
3415
3416
3417 IF (NOT p_consol_item_repl_tbl.exists(i)) THEN
3418
3419 IF (l_debug = 1) THEN
3420 print_debug('CURRENT INDEX IN THE CONSOL TABLE HAS BEEN Discarded - moving TO next consol RECORD' );
3421
3422 END IF;
3423 ELSE
3424
3425
3426
3427 IF l_debug = 1 THEN
3428 print_debug('Final Replenishment Qty for item - '|| p_consol_item_repl_tbl(i).Item_id
3429 ||' ,Qty : '||p_consol_item_repl_tbl(i).final_replenishment_qty);
3430 END IF;
3431
3432 IF p_consol_item_repl_tbl(i).final_replenishment_qty <= 0 THEN
3433
3434 IF l_debug = 1 THEN
3435 print_debug('No Need of Replenishment for this Item....Moving to next consol Item');
3436 END IF;
3437
3438 ELSE
3439
3440 --******* Create Move Order Header per organization ******
3441 -- Per organization, create a single MO header for all items. p_consol_item_repl_tbl has recorde ordered by
3442 -- organization_id
3443
3444 IF (l_prev_org_id IS NULL) OR (l_prev_org_id <> p_consol_item_repl_tbl(i).organization_id) THEN
3445 --values for other parameters for header as same so assigned outside the loop
3446
3447 l_trohdr_rec.organization_id := p_consol_item_repl_tbl(i).organization_id;
3448
3449 -- Create MO Header
3450 IF l_debug = 1 THEN
3451 print_debug('CALLING INV_Move_Order_PUB.Create_Move_Order_Header');
3452 END IF;
3453
3454 INV_Move_Order_PUB.Create_Move_Order_Header(p_api_version_number => 1.0,
3455 p_init_msg_list => FND_API.G_FALSE,
3456 p_return_values => FND_API.G_TRUE,
3457 p_commit => l_commit,
3458 x_return_status => l_return_status,
3459 x_msg_count => l_msg_count,
3460 x_msg_data => l_msg_data,
3461 p_trohdr_rec => l_trohdr_rec,
3462 p_trohdr_val_rec => l_trohdr_val_rec,
3463 x_trohdr_rec => l_x_trohdr_rec,
3464 x_trohdr_val_rec => l_x_trohdr_val_rec,
3465 p_validation_flag => inv_move_order_pub.g_validation_yes
3466 );
3467
3468
3469 IF l_debug = 1 THEN
3470 print_debug('After Calling Create_Move_Order_Header');
3471 END IF;
3472
3473 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
3474 IF l_debug = 1 THEN
3475 print_debug('Creating MO Header failed with unexpected error returning message: ' ||
3476 l_msg_data);
3477 END IF;
3478 RAISE fnd_api.g_exc_unexpected_error;
3479 -- If cant create a common MOH, do no repl stuff
3480 ELSIF l_return_status = FND_API.G_RET_STS_UNEXP_ERROR THEN
3481 IF l_debug = 1 THEN
3482 print_debug('Creating MO Header failed with expected error returning message: ' ||
3483 l_msg_data);
3484 END IF;
3485 RAISE fnd_api.g_exc_error;
3486 -- If cant create a common MOH, do no repl stuff
3487 ELSE
3488 IF l_debug = 1 THEN
3489 print_debug('Creating MO Header returned success with MO Header Id: ' || l_x_trohdr_rec.header_id);
3490 END IF;
3491 END IF;
3492
3493 --set line number for MO lines under this header
3494 l_line_num := 0;
3495
3496 END IF; --Create MO header per organization
3497
3498 --******* Create Move Order Line for a mover order header in an organization ******
3499 -- Create MO Lines for all Items in the pl/sql table under the same MO header for an organization
3500 -- Create replenishment MO lines only if the quantity can not be fulfilled by available OH or Open MO
3501
3502 SAVEPOINT Current_MOL_SP;
3503
3504 -- Get the source sub from the item+sub desktop form for the Front Pick Sub OR let rules
3505 -- engine decide while performing allocation
3506 IF l_debug = 1 THEN
3507 print_debug('Calling Get_Source_Sub_Dest_Loc_Info....');
3508 END IF;
3509 -- Get source sub and loc information for the repl MO, if available
3510 l_return_status := fnd_api.g_ret_sts_success;
3511 Get_Source_Sub_Dest_Loc_Info(p_Org_id => p_consol_item_repl_tbl(i).ORGANIZATION_ID,
3512 p_Item_id => p_consol_item_repl_tbl(i).Item_id,
3513 p_Picking_Sub => p_consol_item_repl_tbl(i).Repl_To_Subinventory_code,
3514 x_source_sub => l_src_sub,
3515 x_src_pick_uom => l_src_pick_uom,
3516 x_MAX_MINMAX_QUANTITY => l_MAX_MINMAX_QUANTITY,
3517 x_fixed_lot_multiple => l_fixed_lot_multiple,
3518 x_return_status => l_return_status);
3519
3520 IF l_return_status <> fnd_api.g_ret_sts_success THEN
3521 GOTO next_consol_rec;
3522 END IF;
3523
3524 -- Final Replenishment Quantity = Maximum of min-max qty + Sum of
3525 -- unallocated demand + Sum of Allocated but not executed tasks
3526 -- Available On Hand - Sum of unallocated replenishment move orders with destination sub ] .
3527
3528 --By the time, code comes at this point, last 2 are already
3529 --subtracted. Maximum of min-max qty should alWays be in the fixed
3530 --lot multiple. It is restrained by the UI on the item-sub form
3531
3532 p_consol_item_repl_tbl(i).final_replenishment_qty :=
3533 p_consol_item_repl_tbl(i).final_replenishment_qty + L_MAX_MINMAX_QUANTITY;
3534
3535 IF l_debug = 1 THEN
3536 print_debug('getting right qty and uom for the move order line creation' );
3537 print_debug('Current Final Qty: '||p_consol_item_repl_tbl(i).final_replenishment_qty);
3538 END IF;
3539
3540 -- For DYNAMIC REPL, How to stamp the qty and UOM on the newly created Replenishment Move Order
3541 --example:
3542 -- Destination Sub = CASE (Pick_UOM = CS)
3543 -- 1CS = 10 Ea
3544 -- Final calculated Repl Qty = 3CS
3545 --
3546 -- Fixed-Lot-multiplier(200 ea) Src-sub(bulk) Pick-uom-Src-sub (PLT=100 Ea) Example (Qty ON repl mo)
3547 -- Y Y Y 2PLT
3548 -- Y y N 20CS
3549 -- n y y 1PLT
3550 -- n y n 10CS
3551 -- n n Not applicable 3CS
3552 --
3553
3554 -- If open MO and available Onhand can offset the current demand, then do not create Replenishment MO for those records
3555 IF p_consol_item_repl_tbl(i).final_replenishment_qty > 0 THEN
3556
3557 -- Upp the replenishment qty appropriately
3558
3559 --set the item info in cache
3560 IF inv_cache.set_item_rec(p_consol_item_repl_tbl(i).ORGANIZATION_ID, p_consol_item_repl_tbl(i).item_id) THEN
3561
3562 -- for Dynamic replenishment or next level repl, p_Repl_Lot_Size will be passed as NULL
3563 IF p_repl_lot_size IS NULL THEN
3564 IF l_debug = 1 THEN
3565 print_debug('repl_lot_size is NULL, Either Dynamic Or Next LEVEL Repl');
3566 END IF;
3567
3568 -- means final qty and uom code need to change with following condition
3569 IF l_fixed_lot_multiple <> -1 OR (l_src_pick_uom IS NOT NULL AND
3570 l_src_pick_uom <> p_consol_item_repl_tbl(i).repl_uom_code) THEN
3571
3572
3573
3574 IF l_fixed_lot_multiple <> -1 THEN
3575 l_repl_lot_size_prim := l_fixed_lot_multiple;
3576
3577 -- If lot multiplier is specified and src_pick_uom IS specified
3578 -- The qty should be tracked in src_pick_uom
3579 IF l_src_pick_uom IS NOT NULL THEN -- pushing with bug 7201888
3580 l_conversion := ROUND(get_conversion_rate(p_consol_item_repl_tbl(i).Item_id,
3581 l_src_pick_uom,
3582 inv_cache.item_rec.primary_uom_code),
3583 g_conversion_precision);
3584
3585 END IF;
3586
3587 ELSIF l_src_pick_uom IS NOT NULL THEN
3588 -- GET THE MULITPLE OF THE "UNIT QTY CONVERSION OF the source sub pick UOM"
3589 l_conversion := ROUND(get_conversion_rate(p_consol_item_repl_tbl(i).Item_id,
3590 l_src_pick_uom,
3591 inv_cache.item_rec.primary_uom_code),
3592 g_conversion_precision);
3593
3594
3595 IF l_debug = 1 THEN
3596 print_debug('Unit Conversion qty for Source UOM :'||l_conversion);
3597 END IF;
3598
3599 -- what if UOM conversion not defined
3600 IF l_conversion > 0 THEN
3601 l_repl_lot_size_prim := l_conversion;
3602 END IF;
3603 END IF; -- IF l_fixed_lot_multiple <> -1
3604
3605
3606 IF l_debug = 1 THEN
3607 print_debug('Value of repl_lot_size in Primary UOM: '||l_repl_lot_size_prim);
3608 END IF;
3609
3610 -- GET THE FINAL PRIMARY MOVE ORDER QTY
3611 -- This UOM conversion will be defined, otherwise code
3612 -- will not come here, repl_uom_code in consol table
3613 -- would not have been marked otherwise
3614 l_txn_prim_qty :=
3615 ROUND((p_consol_item_repl_tbl(i).final_replenishment_qty * get_conversion_rate(p_consol_item_repl_tbl(i).Item_id,
3616 p_consol_item_repl_tbl(i).repl_uom_code,
3617 inv_cache.item_rec.primary_uom_code)),
3618 g_conversion_precision);
3619
3620 -- UPP the PRIMARY QTY in the INTEGRAL MULITPLE of l_repl_lot_size_prim
3621 -- to habndle the case in which Repl_Lot_Size is exact multiple of repl qty
3622 IF MOD(l_txn_prim_qty,l_Repl_Lot_Size_prim) <> 0 THEN
3623 l_txn_prim_qty := l_repl_lot_size_prim * (1 + FLOOR(l_txn_prim_qty/l_repl_lot_size_prim));
3624 END IF;
3625
3626
3627 -- Now take care of stamping right UOM and updated qty
3628 IF (l_src_pick_uom IS NOT NULL) THEN
3629 IF l_conversion > 0 THEN
3630 -- convert the final qty into apporopriate qty based on l_src_pick_uom
3631 p_consol_item_repl_tbl(i).final_replenishment_qty :=
3632 ROUND((l_txn_prim_qty * get_conversion_rate(p_consol_item_repl_tbl(i).Item_id,
3633 inv_cache.item_rec.primary_uom_code,
3634 l_src_pick_uom )),
3635 g_conversion_precision);
3636
3637 -- UPDATE THE UOM CODE AS WELL
3638 p_consol_item_repl_tbl(i).repl_uom_code := l_src_pick_uom;
3639 END IF;
3640
3641 ELSE -- means source sub UOM code is not available
3642 --ADJUST THE INCREASED QTY IN THE p_consol_item_repl_tbl(i).repl_uom_code uom only
3643 IF l_conversion > 0 THEN
3644 p_consol_item_repl_tbl(i).final_replenishment_qty :=
3645 ROUND((l_txn_prim_qty * get_conversion_rate(p_consol_item_repl_tbl(i).Item_id,
3646 inv_cache.item_rec.primary_uom_code,
3647 p_consol_item_repl_tbl(i).Repl_UOM_Code )),
3648 g_conversion_precision);
3649
3650 -- UOM_CODE remains same here
3651 END IF; -- IF l_conversion > 0
3652 END IF; --IF (l_src_pick_uom IS NOT NULL)
3653
3654 END IF; -- means final qty and uom code need TO CHANGE
3655
3656
3657 ELSE -- means p_repl_lot_size IS NOT NULL, First level of PUSH Replenishment
3658 -- For Push Replenishment NULL value for p_Repl_Lot_Size will be treated as 1
3659 IF p_Repl_Lot_Size IS NULL THEN
3660 L_Repl_Lot_Size := 1;
3661 ELSE
3662 L_Repl_Lot_Size := p_Repl_Lot_Size;
3663 END IF;
3664
3665 -- to habndle the case in which Repl_Lot_Size is exact multiple of repl qty
3666 IF MOD(p_consol_item_repl_tbl(i).final_replenishment_qty,l_Repl_Lot_Size) <> 0 THEN
3667
3668 p_consol_item_repl_tbl(i).final_replenishment_qty :=
3669 l_Repl_Lot_Size * (1 + FLOOR(p_consol_item_repl_tbl(i).final_replenishment_qty / l_Repl_Lot_Size));
3670 END IF;
3671 END IF; -- for p_repl_lot_size IS NOT NULL
3672
3673 END IF; -- FOR inv_cache.set_item_rec
3674
3675 ELSE -- menas final_replenishment_qty <= 0
3676 -- Mark negative qty to avoid further considerations and creating MO
3677 p_consol_item_repl_tbl(i).final_replenishment_qty := -9999;
3678
3679 END IF; --for final_replenishment_qty > 0
3680
3681
3682
3683
3684 IF l_debug = 1 THEN
3685 print_debug('After Upp qty by Repl_Lot_Size, Final Repl qty :'||
3686 p_consol_item_repl_tbl(i).final_replenishment_qty);
3687 print_debug('After Upp qty by Repl_Lot_Size, Final UOM CODE :'||
3688 p_consol_item_repl_tbl(i).repl_uom_code);
3689 END IF;
3690
3691
3692 -- While creating the MO, we have decided NOT to check for
3693 -- availability of item. Even if the qty is available now, still. create repl MO.
3694 -- Customer might be expecting some shipment and he would like Move Order to be already created.
3695
3696 -- We do not create MO lines qty in the multiple of 'fixed lot multiple' specified on the Item-sub form.
3697 --It will create too many move order lines and will end up having
3698 --remaining left over quantities with lot of lines.
3699 --Instead let rules engine allocate in that fashion if needed.
3700
3701 IF p_consol_item_repl_tbl(i).final_replenishment_qty <> -9999 THEN
3702
3703 l_trolin_tbl.DELETE;
3704 l_order_count:= 1;
3705
3706 -- Create MO Lines
3707 IF l_debug = 1 THEN
3708 print_debug('CALLING INV_Move_Order_PUB.Create_Move_Order_Lines');
3709 END IF;
3710 l_line_num := l_line_num + 1;
3711 l_trolin_tbl(l_order_count).header_id := l_x_trohdr_rec.header_id;
3712 l_trolin_tbl(l_order_count).created_by := fnd_global.user_id;
3713 l_trolin_tbl(l_order_count).creation_date := sysdate;
3714 l_trolin_tbl(l_order_count).date_required := p_consol_item_repl_tbl(i).date_required;
3715 l_trolin_tbl(l_order_count).from_subinventory_code := l_src_sub;
3716 l_trolin_tbl(l_order_count).line_number := l_line_num;
3717 l_trolin_tbl(l_order_count).inventory_item_id := p_consol_item_repl_tbl(i).Item_id;
3718 l_trolin_tbl(l_order_count).last_updated_by := fnd_global.user_id;
3719 l_trolin_tbl(l_order_count).last_update_date := sysdate;
3720 l_trolin_tbl(l_order_count).last_update_login := fnd_global.user_id;
3721 l_trolin_tbl(l_order_count).line_status := INV_Globals.g_to_status_preapproved;
3722 l_trolin_tbl(l_order_count).organization_id := p_consol_item_repl_tbl(i).ORGANIZATION_ID;
3723 l_trolin_tbl(l_order_count).quantity := p_consol_item_repl_tbl(i).final_replenishment_qty;
3724 l_trolin_tbl(l_order_count).uom_code := p_consol_item_repl_tbl(i).Repl_UOM_Code;
3725 l_trolin_tbl(l_order_count).status_date := sysdate;
3726 l_trolin_tbl(l_order_count).to_subinventory_code := p_consol_item_repl_tbl(i).Repl_To_Subinventory_code;
3727 l_trolin_tbl(l_order_count).to_locator_id := NULL; -- Let Rule engine decide based ON avail_capacity
3728 l_trolin_tbl(l_order_count).transaction_source_type_id :=INV_GLOBALS.G_SOURCETYPE_MOVEORDER; -- 4
3729 l_trolin_tbl(l_order_count).transaction_type_id := INV_GLOBALS.G_TYPE_TRANSFER_ORDER_SUBXFR;
3730 l_trolin_tbl(l_order_count).db_flag := FND_API.G_TRUE;
3731 l_trolin_tbl(l_order_count).operation := INV_GLOBALS.G_OPR_CREATE;
3732
3733 --Begin 12396907
3734 IF inv_cache.set_item_rec(p_consol_item_repl_tbl(i).ORGANIZATION_ID, p_consol_item_repl_tbl(i).item_id) THEN
3735
3736 IF (inv_cache.item_rec.tracking_quantity_ind = 'PS') THEN
3737 l_trolin_tbl(l_order_count).secondary_uom := inv_cache.item_rec.secondary_uom_code;--12396907
3738 l_trolin_tbl(l_order_count).secondary_quantity := ROUND(
3739 (p_consol_item_repl_tbl(i).final_replenishment_qty * get_conversion_rate(p_consol_item_repl_tbl(i).Item_id,
3740 p_consol_item_repl_tbl(i).repl_uom_code,
3741 inv_cache.item_rec.secondary_uom_code)),
3742 g_conversion_precision);--12396907
3743
3744 END IF;
3745 END IF;
3746
3747 IF l_debug = 1 THEN
3748 print_debug('The values after conversion for secondary UOM'|| l_trolin_tbl(l_order_count).secondary_uom);
3749 print_debug('The values after conversion for secondary quantity'|| l_trolin_tbl(l_order_count).secondary_quantity);
3750 END IF;
3751 --End 12396907
3752
3753 -- NO NEED TO CALL THIS API FOR EACH LINE. STORE ALL LINES FOR A
3754 -- mo header IN THE l_trolin_tbl TABLE AND THEN CALL ONLY ONCE FOR
3755 -- PERFORMACE REASON. THEN FOR EACH MO LINE FROM THE SAME TABLE,
3756 -- CREATE RESERVATION FOR CORRESPONDING DEMAND LINES, IF NEEDED
3757 l_return_status := fnd_api.g_ret_sts_success;
3758 INV_Move_Order_PUB.Create_Move_Order_Lines(
3759 p_api_version_number => 1.0,
3760 p_init_msg_list => FND_API.G_FALSE,
3761 p_commit => FND_API.G_FALSE, --BUG14504260
3762 x_return_status => l_return_status,
3763 x_msg_count => l_msg_count,
3764 x_msg_data => l_msg_data,
3765 p_trolin_tbl => l_trolin_tbl,
3766 p_trolin_val_tbl => l_trolin_val_tbl,
3767 x_trolin_tbl => l_x_trolin_tbl,
3768 x_trolin_val_tbl => l_x_trolin_val_tbl,
3769 p_validation_flag => 'Y' );
3770
3771
3772 IF L_DEBUG = 1 THEN
3773 print_debug('After call to INV_Move_Order_PUB.Create_Move_Order_Lines');
3774 END IF;
3775
3776 IF l_return_status = FND_API.G_RET_STS_ERROR THEN
3777
3778 IF L_DEBUG = 1 THEN
3779 print_debug('INV_Move_Order_PUB.Create_Move_Order_Lines failed with expected error returning message: ' || l_msg_data || l_msg_count);
3780 END IF;
3781 IF l_msg_count > 0 THEN
3782 FOR i in 1 .. l_msg_count LOOP
3783 l_msg := fnd_msg_pub.get(i, 'F');
3784 print_debug(l_msg);
3785 fnd_msg_pub.delete_msg(i);
3786 END LOOP;
3787 END IF;
3788 l_line_num := l_line_num - 1;
3789 l_trolin_tbl.DELETE(l_order_count);
3790 GOTO next_consol_rec;
3791 ELSIF l_return_status = FND_API.G_RET_STS_UNEXP_ERROR THEN
3792 IF L_DEBUG= 1 THEN
3793 print_debug('INV_Move_Order_PUB.Create_Move_Order_Lines failed with unexpected error returning message: ' || l_msg_data);
3794 END IF;
3795
3796 IF l_msg_count > 0 THEN
3797 FOR i in 1 .. l_msg_count LOOP
3798 l_msg := fnd_msg_pub.get(i, 'F');
3799 print_debug(l_msg);
3800 fnd_msg_pub.delete_msg(i);
3801 END LOOP;
3802 END IF;
3803 l_line_num := l_line_num - 1;
3804 l_trolin_tbl.DELETE(l_order_count);
3805 GOTO next_consol_rec;
3806 ELSE
3807 IF L_DEBUG = 1 THEN
3808 print_debug('INV_Move_Order_PUB.Create_Move_Order_Lines returned success');
3809 END IF;
3810 END IF;
3811
3812
3813
3814 IF p_Create_Reservation = 'Y' THEN --and Nvl(repl_level,1) = 1 THEN
3815 IF L_DEBUG = 1 THEN
3816 print_debug('******Create_Reservation = Y and repl_LEVEL = 1');
3817 END IF;
3818 l_index := 1;
3819
3820 -- Loop through all demand lines for the repl MO and Create rsv
3821 -- At this point, for an item, sum (quantity) for demand lines in the GTMP table should be in sync with mol_qty
3822 OPEN c_demand_lines_for_item(p_consol_item_repl_tbl(i).ORGANIZATION_ID, p_consol_item_repl_tbl(i).item_id, p_consol_item_repl_tbl(i).repl_to_subinventory_code);
3823
3824 LOOP
3825 FETCH c_demand_lines_for_item INTO
3826 L_sequence_id, L_demand_header_id,
3827 L_demand_line_id,
3828 L_demand_line_detail_id, l_demand_type_id,
3829 L_demand_quantity,
3830 L_demand_uom_code, l_expected_ship_date,
3831 l_demand_quantity_in_repl_uom, l_repl_uom_code,
3832 l_repl_level, l_repl_type;
3833 EXIT WHEN c_demand_lines_for_item%notfound;
3834
3835 IF L_DEBUG = 1 THEN
3836 print_debug('Fetch the Demand Line detail id: '|| L_demand_line_detail_id);
3837 print_debug('Check if reservation exists');
3838 END IF;
3839
3840 -- Create Org Level reservation for every demand line, if it does not exist
3841
3842 -- Check if an Org level reservation exists for corresponding order line
3843 -- Clear out old values
3844 l_rsv_temp_rec := l_rsv_temp_rec_2;
3845
3846 -- Assign all new values
3847 l_rsv_temp_rec.organization_id := p_consol_item_repl_tbl(i).ORGANIZATION_ID;
3848 l_rsv_temp_rec.inventory_item_id := p_consol_item_repl_tbl(i).item_id;
3849 l_rsv_temp_rec.DEMAND_SOURCE_TYPE_ID := l_demand_type_id;
3850 l_rsv_temp_rec.DEMAND_SOURCE_HEADER_ID := l_demand_header_id;
3851 l_rsv_temp_rec.DEMAND_SOURCE_LINE_ID := l_demand_line_id;
3852
3853 l_return_status := fnd_api.g_ret_sts_success;
3854 inv_reservation_pub.query_reservation(p_api_version_number =>1.0,
3855 x_return_status => l_return_status,
3856 x_msg_count => x_msg_count,
3857 x_msg_data => x_msg_data,
3858 p_query_input => l_rsv_temp_rec,
3859 x_mtl_reservation_tbl => l_rsv_rec,
3860 x_mtl_reservation_tbl_count => l_mtl_reservation_count,
3861 x_error_code => l_error_code);
3862
3863 IF l_RETURN_status = fnd_api.g_ret_sts_success THEN
3864 IF L_DEBUG = 1 THEN
3865 PRINT_DEBUG('Number of reservations found: ' || l_mtl_reservation_count);
3866 END IF;
3867 ELSE
3868 IF L_DEBUG = 1 THEN
3869 PRINT_DEBUG('Error: ' || X_msg_data);
3870 END IF;
3871 l_line_num := l_line_num - 1;
3872 l_trolin_tbl.DELETE(l_order_count);
3873 GOTO next_consol_rec;
3874 END IF;
3875
3876 -- If no org level reservation found then create it
3877
3878 IF l_mtl_reservation_count = 0 then
3879 -- Create high-level reservation
3880 IF L_DEBUG = 1 THEN
3881 PRINT_DEBUG('Calling Create_RSV >>>');
3882 END IF;
3883 l_return_status := fnd_api.g_ret_sts_success;
3884 Create_RSV(p_replenishment_type => 1, -- 1- Stock Up/Push; 2- Dynamic/Pull
3885 l_debug => l_debug,
3886 l_organization_id => p_consol_item_repl_tbl(i).ORGANIZATION_ID,
3887 l_inventory_item_id => p_consol_item_repl_tbl(i).item_id,
3888 l_demand_type_id => l_demand_type_id,
3889 l_demand_so_header_id => L_demand_header_id,
3890 l_demand_line_id => L_demand_line_id,
3891 l_split_wdd_id => NULL,
3892 l_primary_uom_code => l_demand_uom_code,
3893 l_supply_uom_code => l_demand_uom_code, -- 13942999
3894 l_atd_qty => L_demand_quantity,
3895 l_atd_prim_qty => L_demand_quantity,
3896 l_supply_type_id => 13,
3897 l_supply_header_id => NULL, -- since high level rsv
3898 l_supply_line_id => NULL, -- since high level rsv
3899 l_supply_line_detail_id => NULL, -- since high level rsv
3900 l_supply_expected_time => SYSDATE,
3901 l_demand_expected_time => l_expected_ship_date,
3902 l_rsv_rec => l_rsv_temp_rec, -- only need to provide good enough information FOR high LEVEL reservation, only one row will do
3903 l_serial_number => l_serial_number,
3904 l_to_serial_number => l_to_serial_number,
3905 l_quantity_reserved => l_quantity_reserved,
3906 l_quantity_reserved2 => l_quantity_reserved2,
3907 l_rsv_id => l_rsv_id,
3908 x_return_status => l_return_status,
3909 x_msg_count => x_msg_count,
3910 x_msg_data => x_msg_data
3911 );
3912
3913 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
3914 IF (l_debug = 1) THEN
3915 print_debug('Error returned from create_reservation API: ' || l_return_status);
3916 END IF;
3917 l_line_num := l_line_num - 1;
3918 l_trolin_tbl.DELETE(l_order_count);
3919 GOTO next_consol_rec;
3920 ELSE -- reservation creation successful
3921 IF (l_debug = 1) THEN
3922 print_debug('Successfully created a RSV record');
3923 END IF;
3924
3925 END IF;
3926
3927 ELSE -- means l_mtl_reservation_count <> 0, rsv already exists
3928 --DO NOTHING
3929 NULL;
3930
3931 END IF; -- for l_mtl_reservation_count == 0
3932
3933 -- Put the WDDs to 'Replenishment Requested' RR status
3934 -- Call Shipping API to mark the Delivery Detail to 'RR'
3935
3936 IF l_demand_type_id <> 4 THEN
3937 -- Mark wdd RR only for first level
3938 -- WHEN demand is WDD and NOT mover order of next level
3939 IF (l_debug = 1) THEN
3940 print_debug('Mark Delivery Detail to RR');
3941 END IF;
3942 update_wdd_repl_status (p_deliv_detail_id => l_demand_line_detail_id
3943 , p_repl_status => 'R' -- for completed status
3944 , x_return_status => l_return_status
3945 );
3946
3947 IF l_return_status <> fnd_api.g_ret_sts_success THEN
3948 l_line_num := l_line_num - 1;
3949 l_trolin_tbl.DELETE(l_order_count);
3950 GOTO next_consol_rec;
3951 END IF;
3952 END IF; -- for IF l_demand_type_id <> 4 THEN
3953
3954 -- Add an entry into WRD table for consumed Demand lines
3955 -- STORE DATA here and do BULK INSERT later
3956 l_organization_id_tab(l_index) := p_consol_item_repl_tbl(i).organization_id;
3957 l_mo_header_id_tab(l_index) := l_x_trolin_tbl(l_order_count).header_id;
3958 l_mo_line_id_tab(l_index) := l_x_trolin_tbl(l_order_count).line_id;
3959 l_demand_header_id_tab(l_index) := l_demand_header_id;
3960 l_demand_line_id_tab(l_index) := l_demand_line_id;
3961 l_demand_line_detail_id_tab(l_index) := l_demand_line_detail_id;
3962 l_demand_type_id_tab(l_index) := l_demand_type_id;
3963 l_item_id_tab(l_index) := p_consol_item_repl_tbl(i).item_id;
3964 l_demand_uom_code_tab(l_index) := l_demand_uom_code;
3965 l_demand_quantity_tab(l_index) := l_demand_quantity;
3966 l_sequence_id_tab(l_index) := l_sequence_id;
3967 l_repl_level_tab(l_index) := l_repl_level;
3968 l_repl_type_tab(l_index) := l_repl_type;
3969 l_index := l_index +1;
3970
3971
3972 -- NOTE: For all demand records that would be consumed by newly created MO lines, corresponding
3973 -- entry in the GTMP table will be deleted at the end of the processing of the replenishment calls
3974
3975 END LOOP; -- for each demand line for an item
3976 CLOSE c_demand_lines_for_item;
3977
3978 IF (l_debug = 1) THEN
3979 print_debug('Bulk Upload records in WRD');
3980 END IF;
3981
3982 -- BULK UPLOAD ALL DEMAND RECORDS IN THE WRD TABLE
3983 FORALL k in 1 .. l_demand_line_detail_id_tab.COUNT()
3984 INSERT INTO wms_replenishment_details
3985 (Replenishment_id,
3986 Organization_id,
3987 source_header_id,
3988 Source_line_id,
3989 Source_line_detail_id,
3990 Source_type_id,
3991 demand_header_id,
3992 demand_line_id,
3993 demand_line_detail_id,
3994 demand_type_id,
3995 Inventory_item_id,
3996 Primary_UOM,
3997 Primary_Quantity,
3998 demand_sort_order,
3999 repl_level,
4000 repl_type,
4001 CREATION_DATE,
4002 LAST_UPDATE_DATE,
4003 CREATED_BY,
4004 LAST_UPDATED_BY,
4005 LAST_UPDATE_LOGIN
4006 )VALUES (
4007 WMS_REPLENISHMENT_DETAILS_S.NEXTVAL,
4008 l_organization_id_tab(k),
4009 l_mo_header_id_tab(k),
4010 l_mo_line_id_tab(k),
4011 NULL,
4012 4, -- For Move Orders
4013 l_demand_header_id_tab(k),
4014 l_demand_line_id_tab(k),
4015 l_demand_line_detail_id_tab(k),
4016 l_demand_type_id_tab(k),
4017 l_item_id_tab(k),
4018 l_demand_uom_code_tab(k),
4019 l_demand_quantity_tab(k),
4020 l_sequence_id_tab(k),
4021 l_repl_level_tab(k),
4022 l_repl_type_tab(k),
4023 Sysdate,
4024 Sysdate,
4025 fnd_global.user_id,
4026 fnd_global.user_id,
4027 fnd_global.user_id);
4028
4029 -- CLEAR all entries in the tables
4030 l_organization_id_tab.DELETE;
4031 l_mo_header_id_tab.DELETE;
4032 l_mo_line_id_tab.DELETE;
4033 l_demand_header_id_tab.DELETE;
4034 l_demand_line_id_tab.DELETE;
4035 l_demand_line_detail_id_tab.DELETE;
4036 l_demand_type_id_tab.DELETE;
4037 l_item_id_tab.DELETE;
4038 l_demand_uom_code_tab.DELETE;
4039 l_demand_quantity_tab.DELETE;
4040 l_sequence_id_tab.DELETE;
4041 l_repl_level_tab.DELETE;
4042 l_repl_type_tab.DELETE;
4043
4044
4045 IF (l_debug = 1) THEN
4046 print_debug('After Bulk Upload records in WRD');
4047 END IF;
4048
4049
4050 ELSIF ( p_repl_level > 1 AND p_Create_Reservation = 'N') THEN
4051
4052 -- means next level of replenishment
4053 -- just insert records into the WRD table
4054 IF L_DEBUG = 1 THEN
4055 print_debug('******Create_Reservation = N and Next LEVEL repl');
4056 print_debug('Bulk Upload records in WRD');
4057 END IF;
4058
4059
4060 -----------------------
4061 -- this is within the loop for each item
4062
4063 IF inv_cache.set_item_rec(p_consol_item_repl_tbl(i).ORGANIZATION_ID, p_consol_item_repl_tbl(i).item_id) THEN
4064 l_txn_prim_qty :=
4065 ROUND((p_consol_item_repl_tbl(i).final_replenishment_qty * get_conversion_rate(p_consol_item_repl_tbl(i).Item_id,
4066 p_consol_item_repl_tbl(i).repl_uom_code,
4067 inv_cache.item_rec.primary_uom_code)),
4068 g_conversion_precision);
4069
4070
4071 INSERT INTO wms_replenishment_details
4072 (Replenishment_id,
4073 Organization_id,
4074 source_header_id,
4075 Source_line_id,
4076 Source_line_detail_id,
4077 Source_type_id,
4078 demand_header_id,
4079 demand_line_id,
4080 demand_line_detail_id,
4081 demand_type_id,
4082 Inventory_item_id,
4083 Primary_UOM,
4084 Primary_Quantity,
4085 demand_sort_order,
4086 repl_level,
4087 repl_type,
4088 CREATION_DATE,
4089 LAST_UPDATE_DATE,
4090 CREATED_BY,
4091 LAST_UPDATED_BY,
4092 LAST_UPDATE_LOGIN
4093 )
4094 SELECT
4095 WMS_REPLENISHMENT_DETAILS_S.NEXTVAL, --Replenishment_id,
4096 p_consol_item_repl_tbl(i).organization_id, --Organization_id,
4097 l_x_trolin_tbl(1).header_id, -- source_header_id,
4098 l_x_trolin_tbl(1).line_id, -- Source_line_id,
4099 NULL, -- Source_line_detail_id,
4100 4, -- Source_type_id,
4101 demand_header_id,
4102 demand_line_id,
4103 demand_line_detail_id, -- stored as -9999 for next level
4104 demand_type_id, -- stored as 4 for next level
4105 p_consol_item_repl_tbl(i).item_id, -- Inventory_item_id,
4106 inv_cache.item_rec.primary_uom_code, -- Primary_UOM,
4107 l_txn_prim_qty, -- Primary_Quantity,
4108 repl_sequence_id , --demand_sort_order,
4109 repl_level,
4110 repl_type,
4111 Sysdate,
4112 Sysdate,
4113 fnd_global.user_id,
4114 fnd_global.user_id,
4115 fnd_global.user_id
4116 FROM WMS_REPL_DEMAND_GTMP
4117 WHERE ORGANIZATION_ID = p_consol_item_repl_tbl(i).ORGANIZATION_ID
4118 AND inventory_item_id = p_consol_item_repl_tbl(i).item_id
4119 AND REPL_TO_SUBINVENTORY_CODE = p_consol_item_repl_tbl(i).repl_to_subinventory_code;
4120
4121 END IF;
4122
4123 IF (l_debug = 1) THEN
4124 print_debug('After Bulk Upload records in WRD FOR NEXT LEVEL');
4125 END IF;
4126
4127
4128 ELSE -- means p_Create_Reservation = 'N'
4129 -- Do not need to do anything here. We do not need to call the shipping API to revert to original
4130 --line status because For dynamic/pull replenishment p_create_Reservation will
4131 -- always be 'Y' and hence the code will never come here. For Push replenishemnt, The demand
4132 -- line would not have been touched yet. So it will remain in its orignal status.
4133
4134 NULL;
4135 END IF; -- for p_Create_Reservation = 'Y'
4136
4137 -- Create Allocation if parameter is Y. For simplicity, only those mover orders will be considered for
4138 -- allocation that are created newly in this program. Already existing open move orders that could
4139 -- partly satisfy current demands will not be detailed.
4140 -- Note: parameter p_Auto_Allocate will be 'N' if p_Create_Reservation = 'N', UI ensures it
4141
4142 IF p_Auto_Allocate = 'Y' THEN
4143 -- Call the allocation engine
4144
4145 IF (l_debug = 1) THEN
4146 print_debug('l_x_trolin_tbl count :'||l_x_trolin_tbl.COUNT());
4147 print_debug('Auto Allocate is Y, Calling rules engine ..MOL:' ||l_x_trolin_tbl(1).line_id);
4148 END IF;
4149
4150 IF p_Plan_Tasks = 'Y' THEN
4151 L_Plan_Tasks := TRUE;
4152 ELSE
4153 L_Plan_Tasks := FALSE;
4154 END IF;
4155
4156 WMS_Engine_PVT.create_suggestions(
4157 p_api_version => 1.0,
4158 p_init_msg_list => fnd_api.g_false,
4159 p_commit => fnd_api.g_false,
4160 p_validation_level => fnd_api.g_valid_level_none,
4161 x_return_status => l_return_status,
4162 x_msg_count => x_msg_count,
4163 x_msg_data => x_msg_data,
4164 p_transaction_temp_id => l_x_trolin_tbl(1).line_id,
4165 p_reservations => l_rsv_tbl_tmp, --NULL value AS no rsv FOR repl MO
4166 p_suggest_serial => fnd_api.g_false,
4167 p_plan_tasks => l_plan_tasks);
4168
4169 IF (l_debug = 1) THEN
4170 print_debug('after calling create_suggestions API');
4171 END IF;
4172
4173
4174 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4175 IF (l_debug = 1) THEN
4176 print_debug('Error returned from create_suggestions API: ' || l_return_status);
4177 END IF;
4178 -- even though it is failing
4179 -- we want to process the replenishment mo
4180 -- it can be allocated later
4181 -- no reverting so passing success to go to next
4182 -- consol rec. Also should not do any next level
4183 -- stuff which this will help to skip.
4184 l_return_status := fnd_api.g_ret_sts_success;
4185 GOTO next_consol_rec;
4186
4187
4188 ELSE
4189
4190 IF (l_debug = 1) THEN
4191 print_debug('Success returned from create_suggestions API');
4192 print_debug('Now Assign Task Type for all Repl tasks created FOR the MO Line');
4193 END IF;
4194 l_mo_line_id:=l_x_trolin_tbl(1).line_id;
4195
4196 OPEN c_mmtt_rec;
4197 LOOP
4198 FETCH c_mmtt_rec INTO l_task_id;
4199 EXIT WHEN c_mmtt_rec%notfound;
4200
4201 IF (l_debug = 1) THEN
4202 print_debug('Assign Task Type for MMTT_id: '||l_task_id);
4203 END IF;
4204
4205 wms_rule_pvt.assigntt(
4206 p_api_version => 1.0
4207 , p_task_id => l_task_id
4208 , x_return_status => l_return_status
4209 , x_msg_count => x_msg_count
4210 , x_msg_data => x_msg_data
4211 );
4212
4213 END LOOP;
4214 CLOSE c_mmtt_rec;
4215
4216
4217 END IF;
4218
4219
4220 --*************
4221 --update the MO line quantity_detailed field or close the MO
4222 BEGIN
4223 SELECT NVL(SUM(primary_quantity), 0)
4224 ,NVL(sum(transaction_quantity),0)
4225 ,COUNT(*)
4226 INTO l_prim_quantity_detailed
4227 ,l_quantity_detailed_conv
4228 ,l_num_detail_recs
4229 FROM mtl_material_transactions_temp
4230 WHERE move_order_line_id = l_x_trolin_tbl(1).line_id;
4231
4232 IF (l_debug = 1) THEN
4233 print_debug('primary l_quantity detailed is :'|| l_prim_quantity_detailed);
4234 print_debug('l_num_detail_recs is :'|| l_num_detail_recs);
4235 print_debug('Primary UOM code :'||inv_cache.item_rec.primary_uom_code);
4236 END IF;
4237
4238 --Convert the MOL detailed qty into MOL UOM code qty
4239 IF inv_cache.item_rec.primary_uom_code <> p_consol_item_repl_tbl(i).repl_uom_code THEN
4240
4241 l_quantity_detailed :=
4242 ROUND((l_prim_quantity_detailed* get_conversion_rate(p_consol_item_repl_tbl(i).item_id,
4243 inv_cache.item_rec.primary_uom_code,
4244 p_consol_item_repl_tbl(i).Repl_UOM_Code )),
4245 g_conversion_precision);
4246
4247 ELSE
4248 l_quantity_detailed := l_prim_quantity_detailed;
4249 END IF;
4250
4251
4252 EXCEPTION
4253 WHEN NO_DATA_FOUND THEN
4254 IF (l_debug = 1) THEN
4255 print_debug('no detail records found');
4256 END IF;
4257 l_quantity_detailed := 0;
4258 l_quantity_detailed_conv := 0;
4259 l_num_detail_recs := 0;
4260 END;
4261
4262 IF (l_debug = 1) THEN
4263 print_debug('Qty Detailed :'||l_quantity_detailed );
4264 print_debug('MOL Line Qty :'||l_x_trolin_tbl(1).quantity);
4265 print_debug('MOL Line Qty Delivered :'||l_x_trolin_tbl(1).quantity_delivered);
4266 END IF;
4267
4268 -- NOTE: l_quantity_detailed contains all qty of MMTT related TO CURRENT mo line whether in this
4269 -- RUN OR ANY previous runs
4270 IF l_quantity_detailed < (l_x_trolin_tbl(1).quantity - Nvl(l_x_trolin_tbl(1).quantity_delivered,0)) THEN -- partial allocation
4271 -- update the quantity detailed correctly
4272 UPDATE mtl_txn_request_lines mtrl
4273 SET mtrl.quantity_detailed = l_quantity_detailed
4274 where line_id = l_x_trolin_tbl(1).line_id;
4275
4276 IF (l_debug = 1) THEN
4277 print_debug('Updated the detailed qty on the MO line');
4278 END IF;
4279
4280 ELSE -- Fully allocated
4281 -- it has been completely detailed
4282 -- do not close the MO, otherwise pick Drop of repl task fails
4283 UPDATE mtl_txn_request_lines mtrl
4284 SET mtrl.quantity_detailed = l_quantity_detailed
4285 where line_id = l_x_trolin_tbl(1).line_id;
4286
4287 IF (l_debug = 1) THEN
4288 print_debug('MO line completely detailed');
4289 END IF;
4290
4291 END IF; -- for partial allocation
4292
4293 --*************
4294 -- Calling Custom API. This call is for post replenishment custom logic eg. Backorder some lines
4295 IF (WMS_REPL_CUSTOM_APIS_PUB.g_is_api_implemented) THEN
4296 IF (l_debug = 1) THEN
4297 print_debug('custom API enabled. Calling WMS_REPL_CUSTOM_APIS_PUB.POST_REPL_ALLOCATION_CUST');
4298 END IF;
4299
4300
4301 WMS_REPL_CUSTOM_APIS_PUB.POST_REPL_ALLOCATION_CUST(x_return_status => x_return_status,
4302 x_msg_count => x_msg_count,
4303 x_msg_data => x_msg_data,
4304 p_mol_id => l_x_trolin_tbl(1).line_id);
4305
4306 ELSE -- custom API is NOT implemented
4307 -- Multi step change
4308 -- Call to check to insert into temp table next level record after
4309 --
4310 IF (( l_prev_item_id IS NULL AND
4311 l_prev_sub_code IS NULL ) OR
4312 l_prev_org_id <> p_consol_item_repl_tbl(i).organization_id OR
4313 l_prev_item_id <> p_consol_item_repl_tbl(i).Item_id OR
4314 l_prev_sub_code <> l_src_sub) THEN
4315 l_source_sub_atr := NULL;
4316 END IF;
4317
4318 IF (l_debug = 1) THEN
4319 print_debug('Ging to check for Next Level of Replenishment');
4320 END IF;
4321
4322 check_for_next_level_repl(p_move_order_header_id => l_x_trolin_tbl(1).header_id
4323 , p_move_order_line_id => l_x_trolin_tbl(1).line_id
4324 , p_organization_id => p_consol_item_repl_tbl(i).organization_id
4325 , p_inventory_item_id => p_consol_item_repl_tbl(i).Item_id
4326 , p_repl_level => p_repl_level
4327 , x_source_sub_atr => l_source_sub_atr
4328 , x_create_qty => l_create_qty
4329 , x_return_status => l_return_status
4330 , x_msg_count => l_msg_count
4331 , x_msg_data => l_msg_data
4332 );
4333
4334 -- if above api did end up computing the atr
4335 -- it will return a non null value else it will return a null
4336 -- value. If it returns a null, we would like to force a check
4337 -- next time around.
4338 IF l_source_sub_atr IS NULL THEN
4339 l_prev_item_id := NULL;
4340 l_prev_sub_code := NULL;
4341 ELSE
4342 l_prev_item_id := p_consol_item_repl_tbl(i).item_id;
4343 l_prev_sub_code := l_src_sub;
4344 END IF;
4345
4346 IF l_create_qty > 0 THEN
4347 l_item_id_tb(l_next_repl_cntr) := p_consol_item_repl_tbl(i).Item_id;
4348 l_org_id_tb(l_next_repl_cntr) := p_consol_item_repl_tbl(i).organization_id;
4349 l_demand_header_id_tb(l_next_repl_cntr) := l_x_trolin_tbl(1).header_id;
4350 l_demand_line_id_tb(l_next_repl_cntr) := l_x_trolin_tbl(1).line_id;
4351 l_demand_type_id_tb(l_next_repl_cntr) := 4;
4352 l_repl_to_sub_code_tb(l_next_repl_cntr) := l_src_sub;
4353 l_requested_quantity_tb(l_next_repl_cntr) := l_create_qty;
4354 l_requested_quantity_uom_tb(l_next_repl_cntr) := p_consol_item_repl_tbl(i).Repl_UOM_Code;
4355 l_quantity_in_repl_uom_tb(l_next_repl_cntr) := l_create_qty;
4356 l_repl_uom_code_tb(l_next_repl_cntr) := p_consol_item_repl_tbl(i).Repl_UOM_Code;
4357 l_expected_ship_date_tb(l_next_repl_cntr) := NULL;
4358 l_next_repl_cntr := l_next_repl_cntr + 1;
4359 END IF;
4360
4361
4362 END IF; -- for custom API is implemented
4363
4364 END IF; -- for p_Auto_Allocate
4365
4366 END IF; -- for p_consol_item_repl_tbl(i).final_replenishment_qty <> -9999
4367
4368 l_prev_org_id := p_consol_item_repl_tbl(i).ORGANIZATION_ID;
4369
4370 END IF; -- IF p_consol_item_repl_tbl(i).final_replenishment_qty <= 0
4371 <<next_consol_rec>>
4372
4373 IF l_return_status <> fnd_api.g_ret_sts_success then
4374
4375 IF (l_debug = 1) THEN
4376 print_debug('At the nexT_consol_rec rolling back as the l_return_status is ' || l_return_status);
4377 END IF;
4378 IF c_demand_lines_for_item%ISOPEN THEN --BUG14054260
4379 CLOSE c_demand_lines_for_item;
4380 END IF;
4381 l_return_status := fnd_api.g_ret_sts_success;
4382 ROLLBACK TO current_mol_sp;
4383 -- if repl_type 2 and demand_type_id <> 4 then revert that WDD to original status
4384 -- remove all entries for that item from gtmp
4385 -- both done in following API
4386 Revert_Consol_item_changes
4387 ( p_repl_type => l_repl_type
4388 , p_demand_type_id => l_demand_type_id
4389 , P_item_id => p_consol_item_repl_tbl(i).item_ID
4390 , p_org_id => p_consol_item_repl_tbl(i).ORGANIZATION_ID
4391 , x_return_status => l_return_status
4392 );
4393
4394 -- Remove element from consol table, can not do inside this loop
4395 -- AS iterating through the same consol record
4396 -- store the index of the consol table to be deleted outside the loop
4397 l_del_index := l_del_index +1;
4398 l_del_consol_item_tb(l_del_index) := i;
4399
4400 END IF;
4401
4402 END IF; -- IF (NOT p_consol_item_repl_tbl.exists(i))
4403 END LOOP; -- For each consolidated demand Items
4404 END IF;
4405
4406 --REMOVE CONSOL RECORDS THAT HAS BEEN REMOVED FROM MOVE ORDER CREATION
4407 -- THIS WILL KEEP DATA IN SYNC. Remember to use 'FORALL k IN INDICES OF'
4408 -- CREATE_REPL_MOVE_ORDER() is last call for a level. so it does not matter
4409 FOR j IN 1..l_del_consol_item_tb.COUNT() LOOP
4410 p_consol_item_repl_tbl.DELETE(l_del_consol_item_tb(j));
4411 END LOOP;
4412
4413 -- TODO: Blocking Multi-Level Code changes
4414 -- Multi step change
4415 -- Bulk upload all eligible demand lines
4416 FORALL k IN INDICES OF l_demand_line_id_tb
4417 INSERT INTO WMS_REPL_DEMAND_GTMP
4418 (Repl_Sequence_id,
4419 repl_level,
4420 Inventory_item_id,
4421 Organization_id,
4422 demand_header_id,
4423 demand_line_id,
4424 DEMAND_LINE_DETAIL_ID,
4425 demand_type_id,
4426 quantity_in_repl_uom,
4427 REPL_UOM_code,
4428 Quantity,
4429 Uom_code,
4430 Expected_ship_date,
4431 Repl_To_Subinventory_code,
4432 filter_item_flag,
4433 repl_type)
4434 VALUES
4435 (WMS_REPL_DEMAND_GTMP_S.NEXTVAL,
4436 Nvl(p_repl_level,1) + 1,
4437 l_item_id_tb(k),
4438 l_org_id_tb(k),
4439 l_demand_header_id_tb(k),
4440 l_demand_line_id_tb(k),
4441 -9999,
4442 l_demand_type_id_tb(k),
4443 l_quantity_in_repl_uom_tb(k),
4444 l_repl_uom_code_tb(k),
4445 l_requested_quantity_tb(k),
4446 l_requested_quantity_uom_tb(k),
4447 l_expected_ship_date_tb(k),
4448 l_repl_to_sub_code_tb(k),
4449 NULL,
4450 2);
4451
4452
4453
4454 EXCEPTION
4455 WHEN OTHERS THEN
4456 IF l_debug = 1 THEN
4457 print_debug('CREATE_REPL_MOVE_ORDER: Error creating move order: ' || sqlcode || ', ' || sqlerrm);
4458 END IF;
4459 x_return_status := fnd_api.g_ret_sts_error;
4460
4461 END CREATE_REPL_MOVE_ORDER;
4462
4463
4464
4465 PROCEDURE GET_OPEN_MO_QTY(p_Repl_level IN NUMBER,
4466 p_repl_type IN NUMBER,
4467 p_Create_Reservation IN VARCHAR2,
4468 x_consol_item_repl_tbl IN OUT NOCOPY CONSOL_ITEM_REPL_TBL,
4469 x_return_status OUT NOCOPY VARCHAR2,
4470 x_msg_count OUT NOCOPY NUMBER,
4471 x_msg_data OUT NOCOPY VARCHAR2)
4472 IS
4473
4474 L_demand_header_id NUMBER;
4475 L_demand_line_id NUMBER;
4476 L_demand_line_detail_id NUMBER;
4477 L_demand_quantity NUMBER;
4478 L_demand_quantity_in_repl_uom NUMBER;
4479 L_demand_uom_code VARCHAR2(3);
4480 L_demand_type_id NUMBER;
4481 L_sequence_id NUMBER;
4482 L_expected_ship_date date;
4483
4484 L_mo_line_id NUMBER;
4485 L_mo_header_id NUMBER;
4486 L_mo_quantity NUMBER;
4487 L_mo_uom_code VARCHAR2(3);
4488 L_mo_quantity_detailed NUMBER;
4489
4490 l_rsv_temp_rec_2 inv_reservation_global.mtl_reservation_rec_type;
4491 l_rsv_temp_rec inv_reservation_global.mtl_reservation_rec_type;
4492 l_rsv_rec inv_reservation_global.mtl_reservation_tbl_type;
4493 l_serial_number inv_reservation_global.serial_number_tbl_type;
4494 l_to_serial_number inv_reservation_global.serial_number_tbl_type;
4495 l_quantity_reserved NUMBER;
4496 l_quantity_reserved2 NUMBER;
4497 l_rsv_id NUMBER;
4498
4499 l_mtl_reservation_count NUMBER;
4500 l_error_code NUMBER;
4501 l_conversion_rate NUMBER;
4502 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
4503
4504
4505 l_repl_level NUMBER;
4506 l_repl_type NUMBER;
4507
4508 l_detail_info_tab WSH_INTERFACE_EXT_GRP.delivery_details_Attr_tbl_Type;
4509 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
4510 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
4511
4512 -- For bulk upload in the WRD table
4513 l_organization_id_tab num_tab;
4514 l_mo_header_id_tab num_tab;
4515 l_mo_line_id_tab num_tab;
4516 l_demand_header_id_tab num_tab;
4517 l_demand_line_id_tab num_tab;
4518 l_demand_line_detail_id_tab num_tab;
4519 l_demand_type_id_tab num_tab;
4520 l_item_id_tab num_tab;
4521 l_demand_uom_code_tab uom_tab;
4522 l_demand_quantity_tab num_tab;
4523 l_sequence_id_tab num_tab;
4524 l_repl_level_tab num_tab;
4525 l_repl_type_tab num_tab;
4526
4527 l_index NUMBER;
4528
4529 -- For bulk delete from the WRDG table
4530 l_detail_id_delete_tab num_tab;
4531 l_del_index NUMBER;
4532
4533 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
4534 l_detail_removed VARCHAR2(1) := 'N'; -- For bug#10185153
4535
4536 CURSOR c_demand_lines_for_item(P_ORG_ID NUMBER, p_item_id number, p_fp_sub VARCHAR2) IS
4537 SELECT Repl_Sequence_id,
4538 demand_header_id,
4539 demand_line_id,
4540 demand_line_detail_id,
4541 demand_type_id,
4542 Nvl(quantity,0),
4543 uom_code,
4544 expected_ship_date,
4545 Nvl(quantity_in_repl_uom,0),
4546 repl_level,
4547 repl_type
4548 FROM WMS_REPL_DEMAND_GTMP
4549 WHERE ORGANIZATION_ID = P_ORG_ID
4550 AND inventory_item_id = p_item_id
4551 AND repl_to_subinventory_code = p_fp_sub
4552 order by Repl_Sequence_id;
4553
4554
4555 -- TEST: make sure that all qty in correct UOM here
4556 --Store all open MO for the Sub
4557 CURSOR c_open_mo_lines(P_ORG_ID NUMBER, p_item_id NUMBER, P_FP_SUB VARCHAR2) IS
4558 select mtrl.line_id,
4559 mtrl.header_id,
4560 -- get all open move order qty that are not part of WRD
4561 -- once fully transacted, mtrl.QUANTITY = mtrl.QUANTITY_DETAILED + mtrl.QUANTITY_DELIVERED
4562 -- here quantity containes QUANTITY_DETAILED at the current sub as
4563 -- well AS untouched move ORDER qty
4564 (mtrl.QUANTITY - NVL(mtrl.QUANTITY_DELIVERED,0)) AS quantity,
4565 mtrl.uom_code,
4566 Nvl(mtrl.quantity_detailed,0) AS quantity_detailed
4567 from mtl_txn_request_lines mtrl, mtl_txn_request_headers mtrh
4568 where mtrl.header_id = mtrh.header_id
4569 and mtrl.organization_id = P_ORG_ID
4570 and mtrl.inventory_item_id = p_item_id
4571 and mtrl.to_subinventory_code = P_FP_SUB
4572 and mtrl.line_status in (3, 7) -- only approved and pre-approved
4573 and mtrh.move_order_type = 2 -- for replenishment only
4574 AND not exists
4575 (select WRD.Source_line_id
4576 from WMS_REPLENISHMENT_DETAILS wrd
4577 where WRD.source_header_id = MTRL.HEADER_ID
4578 AND WRD.Source_line_id = MTRL.LINE_ID
4579 And wrd.organization_id = mtrl.organization_id
4580 And wrd.organization_id = p_org_id )
4581 UNION
4582 -- get all Open Move Order qty that are left out due to rounding or other reason
4583 select mtrl.line_id,
4584 mtrl.header_id,
4585 -- qty inside function Round(**) below might NOT be allocated yet based on
4586 -- how the stock up was RUN but we have earmarked that much mo qty through WRD for certain demands
4587 -- so we need to subtract that much qty from existing_mo_qty for availble_mo_qty
4588 (mtrl.QUANTITY- NVL(mtrl.QUANTITY_DELIVERED,0) -
4589 ROUND((WMS_REPLENISHMENT_PVT.get_conversion_rate(p_item_id, x.primary_uom, mtrl.uom_code)* Nvl(X.quantity,0)),5)) AS quantity,
4590
4591 mtrl.uom_code,
4592 Nvl(mtrl.quantity_detailed,0) AS quantity_detailed
4593 FROM
4594 mtl_txn_request_lines mtrl,
4595 (
4596 SELECT WRD.Source_line_id, WRD.source_header_id,
4597 wrd.inventory_item_id, SUM(wrd.Primary_quantity) quantity,
4598 wrd.organization_id,wrd.primary_uom
4599 FROM WMS_REPLENISHMENT_DETAILS wrd, wsh_delivery_details wdd
4600 WHERE wrd.demand_line_detail_id = wdd.delivery_detail_id
4601 AND wrd.demand_line_id = wdd.source_line_id
4602 AND wrd.organization_id = P_ORG_ID
4603 AND wrd.organization_id = wdd.organization_id
4604 GROUP BY wrd.organization_id,
4605 WRD.source_header_id,
4606 WRD.Source_line_id,
4607 wrd.inventory_item_id,
4608 wrd.primary_uom) X
4609 WHERE X.inventory_item_id = mtrl.inventory_item_id
4610 and x.source_header_id = MTRL.HEADER_ID
4611 AND x.Source_line_id = MTRL.LINE_ID
4612 and x.organization_id = mtrl.organization_id
4613 and mtrl.organization_id = P_ORG_ID
4614 and mtrl.inventory_item_id = p_item_id
4615 and mtrl.to_subinventory_code = P_FP_SUB
4616 and mtrl.line_status in (3, 7)
4617 order by quantity DESC;
4618
4619
4620
4621 CURSOR c_demands_for_mo(p_org_id NUMBER, p_mo_header_id NUMBER, p_mo_line_id NUMBER) IS
4622 SELECT demand_line_detail_id, demand_line_id
4623 FROM WMS_REPLENISHMENT_DETAILS WRD
4624 WHERE WRD.organization_id = P_ORG_ID
4625 AND WRD.source_header_id = P_mo_header_id
4626 AND WRD.Source_line_id = P_mo_line_id;
4627 BEGIN
4628 x_return_status := l_return_status;
4629 -- For all Items in the pl/sql table
4630 IF (l_debug = 1) THEN
4631 print_debug('Inside the API GET_OPEN_MO_QTY');
4632 END IF;
4633 l_index := 1;
4634 l_del_index := 1;
4635 IF (x_consol_item_repl_tbl.count>0) THEN --bug#10185153
4636 FOR i IN x_consol_item_repl_tbl.FIRST .. x_consol_item_repl_tbl.LAST LOOP
4637
4638 IF (NOT x_consol_item_repl_tbl.exists(i)) THEN
4639
4640 IF (l_debug = 1) THEN
4641 print_debug('CURRENT INDEX IN THE CONSOL TABLE HAS BEEN Discarded - moving TO next consol RECORD' );
4642
4643 END IF;
4644
4645 ELSE
4646
4647 IF (l_debug = 1) THEN
4648 print_debug('Going through consolidated item :'|| x_consol_item_repl_tbl(i).item_id ||
4649 ' , Index :'|| i);
4650 END IF;
4651
4652 --For all Open Move Orders for the item, see if there is any demand lines that can be consumed
4653 -- Loop through all open MO for the item
4654 OPEN c_open_mo_lines(x_consol_item_repl_tbl(i).ORGANIZATION_ID,
4655 x_consol_item_repl_tbl(i).item_id,
4656 x_consol_item_repl_tbl(i).repl_to_subinventory_code);
4657 LOOP
4658 FETCH c_open_mo_lines INTO L_mo_line_id, L_mo_header_id, L_mo_quantity, L_mo_uom_code, L_mo_quantity_detailed;
4659 EXIT WHEN c_open_mo_lines%NOTFOUND;
4660 IF (l_debug = 1) THEN
4661 print_debug('Curent open MO Line Id-'|| L_mo_line_id ||' ,Qty :'||L_mo_quantity||' ,UOM :'||L_mo_uom_code);
4662 END IF;
4663
4664 -- Loop through all demand lines for the item to see if any demand line can be consumed against open MOL
4665 OPEN c_demand_lines_for_item(x_consol_item_repl_tbl(i).ORGANIZATION_ID,
4666 x_consol_item_repl_tbl(i).item_id,
4667 x_consol_item_repl_tbl(i).repl_to_subinventory_code);
4668 LOOP
4669 FETCH c_demand_lines_for_item INTO L_sequence_id,
4670 L_demand_header_id, L_demand_line_id,
4671 L_demand_line_detail_id, l_demand_type_id, L_demand_quantity,
4672 L_demand_uom_code,
4673 l_expected_ship_date, l_demand_quantity_in_repl_uom, l_repl_level,l_repl_type ;
4674 EXIT WHEN c_demand_lines_for_item%NOTFOUND;
4675
4676 l_detail_removed := 'N'; -- For bug#10185153
4677
4678 IF (l_debug = 1) THEN
4679 print_debug('Netting delivery_detail :'||L_demand_line_detail_id||
4680 ' ,Qty_in_repl_uom :'||l_demand_quantity_in_repl_uom);
4681 END IF;
4682
4683 SAVEPOINT Current_Demand_SP;
4684
4685 -- For bug#10185153 start
4686 IF (l_detail_id_delete_tab.COUNT()>0) THEN
4687 FOR d in 1 .. l_detail_id_delete_tab.COUNT() LOOP
4688 IF (l_detail_id_delete_tab(d) = l_demand_line_detail_id) THEN
4689 l_detail_removed := 'Y';
4690 EXIT;
4691 END IF;
4692 END LOOP;
4693 END IF;
4694
4695 IF (l_detail_removed = 'Y') THEN
4696 IF (l_debug = 1) THEN
4697 print_debug('Delivery_detail :'||L_demand_line_detail_id||
4698 ' , already processed. So skipping it');
4699 END IF;
4700 GOTO next_record;
4701 END IF;
4702 -- For bug#10185153 end
4703
4704
4705 -- All quantity comparison should happen in repl_UOM_code because there can be multiple demand for a
4706 -- single MO. It will save the computation.
4707 IF L_mo_uom_code <> x_consol_item_repl_tbl(i).Repl_UOM_Code then
4708
4709 l_conversion_rate := get_conversion_rate(x_consol_item_repl_tbl(i).Item_id,
4710 L_mo_uom_code,
4711 x_consol_item_repl_tbl(i).Repl_UOM_Code);
4712
4713 IF (l_conversion_rate < 0) THEN
4714 IF (l_debug = 1) THEN
4715 print_debug('Error while obtaining L_mo_uom_code conversion rate for demand qty');
4716 END IF;
4717 -- Process the next existing demand record.
4718 GOTO next_record;
4719 END IF;
4720
4721 L_mo_quantity := ROUND(l_conversion_rate * L_mo_quantity,
4722 g_conversion_precision);
4723
4724 END IF;
4725
4726 IF L_mo_quantity < L_demand_quantity_in_repl_uom THEN
4727 -- For simplicity, we will consume only those MOLs that have qty greater than WDD qty
4728 IF (l_debug = 1) THEN
4729 print_debug('MO Qty < Demand Line qty, NOTHING TO DO..');
4730 END IF;
4731
4732 GOTO next_record;
4733
4734 ELSIF L_mo_quantity >= L_demand_quantity_in_repl_uom THEN
4735 -- The specific demand order will be consumed with this Move Order
4736 IF (l_debug = 1) THEN
4737 print_debug('MO Qty > Demand Line qty, Consume Against it');
4738 END IF;
4739
4740 IF p_Create_Reservation = 'Y' THEN
4741
4742 IF (l_debug = 1) THEN
4743 print_debug('Create RSV =Y, Mark Replenishment Status as RR');
4744 END IF;
4745
4746 -- Call Shipping API to mark the Delivery Detail to 'RR'
4747 update_wdd_repl_status (p_deliv_detail_id => l_demand_line_detail_id
4748 , p_repl_status => 'R' -- for completed status
4749 , x_return_status => l_return_status
4750 );
4751
4752 IF l_return_status <> fnd_api.g_ret_sts_success THEN
4753 GOTO next_record;
4754 END IF;
4755
4756
4757 IF (l_debug = 1) THEN
4758 print_debug('Check if Org level RSV exists');
4759 END IF;
4760 -- Check if an Org level reservation exists for corresponding demand line
4761 -- Clear out old values
4762 l_rsv_temp_rec := l_rsv_temp_rec_2;
4763
4764 -- Assign all new values
4765 l_rsv_temp_rec.organization_id := x_consol_item_repl_tbl(i).organization_id;
4766 l_rsv_temp_rec.inventory_item_id := x_consol_item_repl_tbl(i).item_id;
4767 l_rsv_temp_rec.DEMAND_SOURCE_TYPE_ID := l_demand_type_id;
4768 l_rsv_temp_rec.DEMAND_SOURCE_HEADER_ID := l_demand_header_id;
4769 l_rsv_temp_rec.DEMAND_SOURCE_LINE_ID := l_demand_line_id;
4770
4771
4772 inv_reservation_pub.query_reservation(
4773 p_api_version_number =>1.0,
4774 x_return_status => l_return_status,
4775 x_msg_count => x_msg_count,
4776 x_msg_data => x_msg_data,
4777 p_query_input => l_rsv_temp_rec,
4778 x_mtl_reservation_tbl => l_rsv_rec,
4779 x_mtl_reservation_tbl_count => l_mtl_reservation_count,
4780 x_error_code => l_error_code);
4781
4782 IF l_RETURN_status = fnd_api.g_ret_sts_success THEN
4783 IF (l_debug = 1) THEN
4784 PRINT_DEBUG('Number of reservations found: ' ||l_mtl_reservation_count);
4785 END IF;
4786
4787 ELSE
4788 IF (l_debug = 1) THEN
4789 PRINT_DEBUG('Error: ' || X_msg_data);
4790 END IF;
4791 GOTO next_record;
4792 END IF;
4793
4794
4795 -- If no org level reservation found then create it
4796 IF l_mtl_reservation_count = 0 then
4797 IF (l_debug = 1) THEN
4798 PRINT_DEBUG('NO RSV Found, Create High Level RSV');
4799 END IF;
4800
4801 l_rsv_temp_rec.DEMAND_SOURCE_HEADER_ID := l_demand_header_id;
4802 l_rsv_temp_rec.demand_source_line_detail := l_demand_line_detail_id;
4803
4804 -- Create high-level reservation for the demand line against inventory (sypply_type = 13)
4805 Create_RSV(p_replenishment_type => 1, -- 1- Stock Up/Push; 2- Dynamic
4806 l_debug => l_debug,
4807 l_organization_id => x_consol_item_repl_tbl(i).ORGANIZATION_ID,
4808 l_inventory_item_id => x_consol_item_repl_tbl(i).item_id,
4809 l_demand_type_id => l_demand_type_id,
4810 l_demand_so_header_id => L_demand_header_id,
4811 l_demand_line_id => L_demand_line_id,
4812 l_split_wdd_id => NULL,
4813 l_primary_uom_code => L_demand_uom_code, --demand uom are prim
4814 l_supply_uom_code => L_demand_uom_code, -- 13942999
4815 l_atd_qty => L_demand_quantity,
4816 l_atd_prim_qty => L_demand_quantity,
4817 l_supply_type_id => 13, --Inventory
4818 l_supply_header_id => NULL, -- since high level rsv
4819 l_supply_line_id => NULL, -- since high level rsv
4820 l_supply_line_detail_id => NULL, -- since high level rsv
4821 l_supply_expected_time => SYSDATE,
4822 l_demand_expected_time => l_expected_ship_date,
4823 l_rsv_rec => l_rsv_temp_rec, -- only need to provide good enough information FOR high LEVEL reservation, only one row will do
4824 l_serial_number => l_serial_number,
4825 l_to_serial_number => l_to_serial_number,
4826 l_quantity_reserved => l_quantity_reserved,
4827 l_quantity_reserved2 => l_quantity_reserved2,
4828 l_rsv_id => l_rsv_id,
4829 x_return_status => l_return_status,
4830 x_msg_count => x_msg_count,
4831 x_msg_data => x_msg_data);
4832
4833 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
4834 IF (l_debug = 1) THEN
4835
4836 print_debug('Error returned from create_reservation API: ' ||
4837 l_return_status);
4838 END IF;
4839 GOTO next_record;
4840 ELSE
4841 IF (l_debug = 1) THEN
4842 print_debug('Successfully created a RSV record for MO Line');
4843 END IF;
4844 END IF;
4845
4846 END IF; -- for l_mtl_reservation_count = 0
4847
4848 IF (l_debug = 1) THEN
4849 print_debug('Add entry into the WRD Table dmd_detail_id :'||l_demand_line_detail_id);
4850 END IF;
4851 -- Add an entry into WRD table
4852 -- STORE DATA here and do BULK INSERT later
4853 l_organization_id_tab(l_index) := x_consol_item_repl_tbl(i).organization_id;
4854 l_mo_header_id_tab(l_index) := l_mo_header_id;
4855 l_mo_line_id_tab(l_index) := l_mo_line_id;
4856 l_demand_header_id_tab(l_index) := l_demand_header_id;
4857 l_demand_line_id_tab(l_index) := l_demand_line_id;
4858 l_demand_line_detail_id_tab(l_index) := l_demand_line_detail_id;
4859 l_demand_type_id_tab(l_index) := l_demand_type_id;
4860 l_item_id_tab(l_index) := x_consol_item_repl_tbl(i).item_id;
4861 l_demand_uom_code_tab(l_index) := l_demand_uom_code;
4862 l_demand_quantity_tab(l_index) := l_demand_quantity;
4863 l_sequence_id_tab(l_index) := l_sequence_id;
4864 l_repl_level_tab(l_index) := l_repl_level;
4865 l_repl_type_tab(l_index) := l_repl_type;
4866 l_index := l_index +1;
4867
4868 ELSE --means p_create_Reservation = 'N'
4869 -- Do not need to do anything here. We do not need to call the shipping API to revert to original
4870 --line status because For dynamic/pull replenishment p_create_Reservation will
4871 -- always be 'Y' and hence the code will never come here. For Push replenishemnt, The demand
4872 -- line would not have been touched yet. So it will remain in its orignal status.
4873 NULL;
4874 IF (l_debug = 1) THEN
4875 print_debug('Create RSV =N, Do not add in WRD table');
4876 END IF;
4877 END IF; --For p_Create_Reservation = 'Y'
4878
4879
4880 IF (l_debug = 1) THEN
4881 print_debug('Remove the Demand_detail_id from the GTMP: '||l_demand_line_detail_id);
4882 END IF;
4883 -- Remove this DEMAND from the WMS_REPL_DEMAND_GTMP table
4884 -- IRRESPECTIVE OF p_create_reservation value. This demand is already consumed
4885 -- This set can be different than set inserted in the WRD table
4886 -- Store here to BULK DELETE later
4887 l_detail_id_delete_tab(l_del_index) := l_demand_line_detail_id;
4888 l_del_index := l_del_index +1;
4889
4890
4891 IF (l_debug = 1) THEN
4892 print_debug('Add to the open MO Qty in the Consol table');
4893 END IF;
4894 -- In PL/SQL table, increase the open MO qty in repl_UOM by L_demand_quantity_in_repl_uom
4895 x_consol_item_repl_tbl(i).open_mo_qty := x_consol_item_repl_tbl(i).open_mo_qty +L_demand_quantity_in_repl_uom;
4896
4897
4898 -- Decrease the L_mo_quantity to reflect correct available MO qty for next demand line
4899 -- All quantity comparision is in the repl_uom unit
4900 L_mo_quantity := L_mo_quantity - L_demand_quantity_in_repl_uom;
4901
4902
4903 END IF; -- L_mo_quantity >= L_demand_quantity
4904
4905 <<next_record>>
4906 IF (l_debug = 1) THEN
4907 print_debug('At the end of current demand Available Open MO qty: '||L_mo_quantity);
4908 END IF;
4909 IF l_return_status <> fnd_api.g_ret_sts_success THEN
4910 l_return_status := fnd_api.g_ret_sts_success;
4911 ROLLBACK TO current_demand_sp;
4912 END IF;
4913 END LOOP; -- for each demand line
4914 CLOSE c_demand_lines_for_item;
4915
4916 IF (l_debug = 1) THEN
4917 print_debug('Done with Current OPEN MO record');
4918 print_debug('Final Open MO qty that cound not be consumed: '||L_mo_quantity);
4919 END IF;
4920
4921 END LOOP; --for each open MO
4922 CLOSE c_open_mo_lines;
4923
4924 --At the end for Each item In PL/SQL table, update the final_replenishment_qty in Repl_UOM
4925 x_consol_item_repl_tbl(i).final_replenishment_qty :=
4926 (x_consol_item_repl_tbl(i).final_replenishment_qty - x_consol_item_repl_tbl(i).open_mo_qty);
4927
4928 --Note: the final replenishment qty will be upp by the p_Repl_Lot_Size in Create_repl_Move_order() API
4929 IF (l_debug = 1) THEN
4930 print_debug('Done with Current Consolidated record');
4931 END IF;
4932
4933
4934 END IF ; -- IF not x_consol_item_repl_tbl.exists(i)
4935
4936 END LOOP; -- For each consolidated demand lines
4937 END IF;
4938
4939
4940
4941 IF (l_debug = 1) THEN
4942 print_debug('BULK INSERT ALL CONSUMED DEMANDS IN WRD table' );
4943 END IF;
4944
4945 -- BULK INSERT ALL consumed demands IN wms_replenishment_details table
4946 FORALL k IN INDICES OF l_demand_line_detail_id_tab
4947 INSERT INTO WMS_REPLENISHMENT_DETAILS
4948 (Replenishment_id,
4949 Organization_Id,
4950 source_header_id,
4951 Source_line_id,
4952 Source_line_detail_id,
4953 Source_type_id,
4954 demand_header_id,
4955 demand_line_id,
4956 demand_line_detail_id,
4957 demand_type_id,
4958 Inventory_item_id,
4959 Primary_UOM,
4960 Primary_Quantity,
4961 demand_sort_order,
4962 repl_level,
4963 repl_type,
4964 CREATION_DATE,
4965 LAST_UPDATE_DATE,
4966 CREATED_BY,
4967 LAST_UPDATED_BY,
4968 LAST_UPDATE_LOGIN
4969 )VALUES (
4970 WMS_REPLENISHMENT_DETAILS_S.NEXTVAL,
4971 l_organization_id_tab(k),
4972 l_mo_header_id_tab(k),
4973 l_mo_line_id_tab(k),
4974 NULL,
4975 4, -- For Move Orders
4976 l_demand_header_id_tab(k),
4977 l_demand_line_id_tab(k),
4978 l_demand_line_detail_id_tab(k),
4979 l_demand_type_id_tab(k),
4980 l_item_id_tab(k),
4981 l_demand_uom_code_tab(k),
4982 l_demand_quantity_tab(k),
4983 l_sequence_id_tab(k),
4984 l_repl_level_tab(k),
4985 l_repl_type_tab(k),
4986 Sysdate,
4987 Sysdate,
4988 fnd_global.user_id,
4989 fnd_global.user_id,
4990 fnd_global.user_id
4991 );
4992
4993 -- CLEAR all entries in the tables
4994 l_organization_id_tab.DELETE;
4995 l_mo_header_id_tab.DELETE;
4996 l_mo_line_id_tab.DELETE;
4997 l_demand_header_id_tab.DELETE;
4998 l_demand_line_id_tab.DELETE;
4999 l_demand_line_detail_id_tab.DELETE;
5000 l_demand_type_id_tab.DELETE;
5001 l_item_id_tab.DELETE;
5002 l_demand_uom_code_tab.DELETE;
5003 l_demand_quantity_tab.DELETE;
5004 l_sequence_id_tab.DELETE;
5005 l_repl_level_tab.DELETE;
5006 l_repl_type_tab.DELETE;
5007
5008 IF (l_debug = 1) THEN
5009 print_debug('BULK REMOVE ALL CONSUMED DEMANDS FROM GTMP table' );
5010 END IF;
5011 -- BULK Remove all consumed demands from WMS_REPL_DEMAND_GTMP table
5012 FORALL k in 1 .. l_detail_id_delete_tab.COUNT()
5013 DELETE From WMS_REPL_DEMAND_GTMP
5014 WHERE demand_line_detail_id = l_detail_id_delete_tab(k);
5015
5016 -- CLEAR all entries in the tables
5017 l_detail_id_delete_tab.DELETE;
5018
5019 IF (l_debug = 1) THEN
5020 print_debug('DONE WITH API - GET_OPEN_MO_QTY' );
5021 END IF;
5022 x_return_status := fnd_api.g_ret_sts_success;
5023 EXCEPTION
5024 WHEN OTHERS THEN
5025 x_return_status := fnd_api.g_ret_sts_error;
5026 IF c_demand_lines_for_item%ISOPEN THEN
5027 CLOSE c_demand_lines_for_item;
5028 END IF;
5029 IF c_open_mo_lines%ISOPEN THEN
5030 CLOSE c_open_mo_lines;
5031 END IF;
5032
5033 IF (l_debug = 1) THEN
5034 print_debug('Error in GET_OPEN_MO_QTY SQLCODE: '||SQLCODE ||' : '||SQLERRM );
5035 END IF;
5036
5037 END GET_OPEN_MO_QTY;
5038
5039
5040 PROCEDURE GET_AVAILABLE_ONHAND_QTY(p_Repl_level IN NUMBER,
5041 p_repl_type IN NUMBER,
5042 p_Create_Reservation IN VARCHAR2,
5043 x_consol_item_repl_tbl IN OUT NOCOPY CONSOL_ITEM_REPL_TBL,
5044 x_return_status OUT NOCOPY VARCHAR2,
5045 x_msg_count OUT NOCOPY NUMBER,
5046 x_msg_data OUT NOCOPY VARCHAR2)
5047 IS
5048
5049
5050 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
5051 l_demand_header_id NUMBER;
5052 l_demand_type_id NUMBER;
5053 l_sequence_id NUMBER;
5054 l_demand_line_id NUMBER;
5055 l_demand_line_detail_id NUMBER;
5056 l_demand_quantity NUMBER;
5057 l_demand_uom_code VARCHAR2(3);
5058 l_expected_ship_date DATE;
5059 l_demand_quantity_in_repl_uom NUMBER;
5060
5061 l_last_sub VARCHAR2(30) := NULL;
5062 l_qoh NUMBER;
5063 l_rqoh NUMBER;
5064 l_qr NUMBER;
5065 l_qs NUMBER;
5066 l_att NUMBER;
5067 l_atr NUMBER;
5068 l_mtl_reservation_count NUMBER;
5069
5070 l_rsv_temp_rec inv_reservation_global.mtl_reservation_rec_type;
5071 l_rsv_temp_rec_2 inv_reservation_global.mtl_reservation_rec_type;
5072 l_rsv_rec inv_reservation_global.mtl_reservation_tbl_type;
5073
5074 l_prev_org_id NUMBER;
5075 l_prev_item_id NUMBER;
5076 l_prev_sub_code VARCHAR2(10);
5077 l_qty_tree_demand_line_id NUMBER;
5078
5079 l_rsv_id_tb num_tab;
5080 l_detail_info_tab WSH_INTERFACE_EXT_GRP.delivery_details_Attr_tbl_Type;
5081 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
5082 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
5083
5084 l_serial_number inv_reservation_global.serial_number_tbl_type;
5085 l_to_serial_number inv_reservation_global.serial_number_tbl_type;
5086 l_quantity_reserved NUMBER;
5087 l_quantity_reserved2 NUMBER;
5088 l_rsv_id NUMBER;
5089 l_error_code NUMBER;
5090
5091 l_is_revision_ctrl BOOLEAN;
5092 l_is_lot_ctrl BOOLEAN;
5093 l_is_serial_ctrl BOOLEAN;
5094
5095 l_del_index NUMBER;
5096 l_del_consol_item_tb num_tab;
5097 l_repl_status VARCHAR2(1);
5098 l_bkorder_cnt NUMBER;
5099
5100 CURSOR c_demand_lines_for_item(p_org_id NUMBER, p_item_id number, p_fp_sub VARCHAR2) IS
5101 SELECT repl_sequence_id, demand_header_id, demand_line_id,
5102 demand_line_detail_id,
5103 demand_type_id, quantity, uom_code, expected_ship_date,
5104 quantity_in_repl_uom, repl_status
5105 FROM WMS_REPL_DEMAND_GTMP
5106 WHERE ORGANIZATION_ID = P_ORG_ID
5107 AND inventory_item_id = p_item_id
5108 AND repl_to_subinventory_code = p_fp_sub
5109 order by Repl_Sequence_id;
5110
5111 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
5112 BEGIN
5113
5114 x_return_status := l_return_status;
5115
5116 IF (l_debug = 1) THEN
5117 print_debug('Inside GET_AVAILABLE_ONHAND_QTY API' );
5118 END IF;
5119
5120 -- For all Items in the pl/sql table
5121 IF (x_consol_item_repl_tbl.count>0) THEN --bug#10185153
5122 FOR i IN x_consol_item_repl_tbl.FIRST.. x_consol_item_repl_tbl.LAST LOOP
5123 IF (l_debug = 1) THEN
5124 print_debug('Consol record Index :' || i);
5125 END IF;
5126
5127 IF (NOT x_consol_item_repl_tbl.exists(i)) THEN
5128
5129 IF (l_debug = 1) THEN
5130 print_debug('CURRENT INDEX IN THE CONSOL TABLE HAS BEEN Discarded - moving TO next consol RECORD' );
5131
5132 END IF;
5133 ELSE
5134
5135
5136 SAVEPOINT onhd_consol_rec_sp;
5137 -- For all demand lines net the available OnHand
5138 OPEN c_demand_lines_for_item(x_consol_item_repl_tbl(i).ORGANIZATION_ID,
5139 x_consol_item_repl_tbl(i).item_id,
5140 x_consol_item_repl_tbl(i).repl_to_subinventory_code);
5141 LOOP
5142 SAVEPOINT onhd_demand_line_sp;
5143
5144 FETCH c_demand_lines_for_item INTO L_sequence_id,
5145 L_demand_header_id, L_demand_line_id,
5146 L_demand_line_detail_id, l_demand_type_id, L_demand_quantity,
5147 L_demand_uom_code,
5148 l_expected_ship_date, l_demand_quantity_in_repl_uom, l_repl_status;
5149 EXIT WHEN c_demand_lines_for_item%notfound;
5150
5151 IF (l_debug = 1) THEN
5152 print_debug('=======Netting onhand for NEW Demand line=======');
5153 print_debug('Next Demand for consol Item Record :' ||l_demand_line_detail_id ||', Dmd_QTY :'||l_demand_quantity
5154 ||', Qty_in_repl_UOM :'||l_demand_quantity_in_repl_uom);
5155 print_debug('l_demand_type_id :'||l_demand_type_id);
5156 END IF;
5157
5158 -- For an Org+item+Sub combination, the qty tree should be called only once
5159 IF (( l_prev_org_id IS NULL AND l_prev_item_id IS NULL AND
5160 l_prev_sub_code IS NULL ) OR
5161 l_prev_org_id <> x_consol_item_repl_tbl(i).ORGANIZATION_ID OR
5162 l_prev_item_id <> x_consol_item_repl_tbl(i).item_id OR
5163 l_prev_sub_code <> x_consol_item_repl_tbl(i).repl_to_subinventory_code ) THEN
5164
5165 l_atr := 0;
5166 -- Get all item details
5167 IF inv_cache.set_item_rec(x_consol_item_repl_tbl(i).ORGANIZATION_ID, x_consol_item_repl_tbl(i).item_id) THEN
5168
5169 IF (l_debug = 1) THEN
5170 print_debug('Getting Item Attribute Details' );
5171 END IF;
5172
5173 IF inv_cache.item_rec.revision_qty_control_code = 2 THEN
5174 l_is_revision_ctrl := TRUE;
5175 ELSE
5176 l_is_revision_ctrl := FALSE;
5177 END IF;
5178
5179 IF inv_cache.item_rec.lot_control_code = 2 THEN
5180 l_is_lot_ctrl := TRUE;
5181 ELSE
5182 l_is_lot_ctrl := FALSE;
5183 END IF;
5184
5185 IF inv_cache.item_rec.serial_number_control_code NOT IN (1,6) THEN
5186 l_is_serial_ctrl := FALSE;
5187 ELSE
5188 l_is_serial_ctrl := TRUE;
5189 END IF;
5190
5191 ELSE
5192 IF (l_debug = 1) THEN
5193 print_debug('Error: Item detail not found');
5194 END IF;
5195 l_return_status := fnd_api.g_ret_sts_error;
5196 GOTO next_onhd_consol_rec;
5197 END IF; -- for inv_cache.set_item_rec
5198
5199
5200 IF (l_debug = 1) THEN
5201 print_debug('Clearing Qty Tree' );
5202 END IF;
5203 --Query Quantity Tree
5204 inv_quantity_tree_pub.clear_quantity_cache;
5205
5206 IF (l_debug = 1) THEN
5207 print_debug('Calling Qty Tree API' );
5208 END IF;
5209
5210 inv_quantity_tree_pub.query_quantities
5211 (
5212 p_api_version_number => 1.0
5213 , p_init_msg_lst => fnd_api.g_false
5214 , x_return_status => l_return_status
5215 , x_msg_count => x_msg_count
5216 , x_msg_data => x_msg_data
5217 , p_organization_id => x_consol_item_repl_tbl(i).organization_id
5218 , p_inventory_item_id => x_consol_item_repl_tbl(i).item_id
5219 , p_tree_mode => inv_quantity_tree_pub.g_transaction_mode
5220 , p_is_revision_control => l_is_revision_ctrl
5221 , p_is_lot_control => l_is_lot_ctrl
5222 , p_is_serial_control => l_is_serial_ctrl
5223 , p_demand_source_type_id => l_demand_type_id -- 2 (OE) / 8 for Internal Order
5224 , p_demand_source_header_id => L_demand_header_id
5225 , p_demand_source_line_id => L_demand_line_id
5226 , p_revision => NULL
5227 , p_lot_number => NULL
5228 , p_subinventory_code => x_consol_item_repl_tbl(i).repl_to_subinventory_code
5229 , p_locator_id => NULL
5230 , x_qoh => l_qoh
5231 , x_rqoh => l_rqoh
5232 , x_qr => l_qr
5233 , x_qs => l_qs
5234 , x_att => l_att
5235 , x_atr => l_atr
5236 );
5237
5238 IF (l_debug = 1) THEN
5239 print_debug( 'Return status from QTY TREE:' ||l_return_status);
5240 print_debug( 'l_atr is: '||l_atr);
5241 END IF;
5242 IF (l_return_status <> fnd_api.g_ret_sts_success) THEN
5243 GOTO next_onhd_consol_rec;
5244 END IF;
5245 -- Store the demand line for which the qty tree was called
5246 l_qty_tree_demand_line_id := l_demand_line_id;
5247
5248
5249 END IF; --For an Org+item+Sub combination
5250
5251
5252 -- In transaction_mode call to API inv_quantity_tree_pub.query_quantities pass parameters: item_id, demand header, demand line, subinventory
5253
5254 --For l_atr calculation for all high level reservations, qty_tree first consumes all available material from outside the current SUB then bite from the current sub if remaining any.
5255
5256 --(l_atr) will be available qty to reserve. It includes rsv_qty
5257 --for current demand line (if detailed at current sub OR high level rsv).
5258 --It does not include qty if the current demand is detailed at other sub.
5259 --It deduct any detailed rsv by other demand lines at the current sub
5260
5261 --l_qr - detailed resv by ALL Other demands at the CURRENT sub (does not include rsv_qty by current demand line)
5262
5263 IF l_atr > 0 THEN
5264
5265 -- Note: if l_atr < l_demand_qty, then we would rather
5266 --create new replenishment MO than splitting the demand line FOR simplicity
5267
5268 IF l_atr >= l_demand_quantity THEN
5269 IF (l_debug = 1) THEN
5270 PRINT_DEBUG('Enough Qty - Consuming this demand :' ||L_demand_line_detail_id);
5271 END IF;
5272
5273 -- Check if rsv exists for the current demand line from table mtl_reservations
5274 -- Use Query_reservation() API
5275 -- Make sure that if rsv exists all qty must be either high level rsv or must be all completely detailed.
5276 -- Lets say that we get l_existing_rsv_qty from MR table for current demand which
5277 -- should be less than or equal to l_demand_qty
5278
5279 IF (l_debug = 1) THEN
5280 PRINT_DEBUG('****Check if Reservation exists for current demand');
5281 END IF;
5282
5283 -- Check if reservation exists for corresponding order line
5284 -- Clear out old values
5285 l_rsv_temp_rec := l_rsv_temp_rec_2;
5286
5287 -- Assign all new values
5288 l_rsv_temp_rec.organization_id := x_consol_item_repl_tbl(i).organization_id;
5289 l_rsv_temp_rec.inventory_item_id := x_consol_item_repl_tbl(i).item_id;
5290 l_rsv_temp_rec.DEMAND_SOURCE_TYPE_ID := l_demand_type_id;
5291 l_rsv_temp_rec.DEMAND_SOURCE_HEADER_ID := l_demand_header_id;
5292 l_rsv_temp_rec.DEMAND_SOURCE_LINE_ID := l_demand_line_id;
5293
5294 inv_reservation_pub.query_reservation(
5295 p_api_version_number =>1.0,
5296 x_return_status => l_return_status,
5297 x_msg_count => x_msg_count,
5298 x_msg_data => x_msg_data,
5299 p_query_input => l_rsv_temp_rec,
5300 x_mtl_reservation_tbl => l_rsv_rec,
5301 x_mtl_reservation_tbl_count => l_mtl_reservation_count,
5302 x_error_code => l_error_code);
5303
5304 IF l_RETURN_status = fnd_api.g_ret_sts_success THEN
5305 IF (l_debug = 1) THEN
5306 PRINT_DEBUG('*****Number of reservations found: ' ||l_mtl_reservation_count);
5307 END IF;
5308
5309 ELSE
5310 IF (l_debug = 1) THEN
5311 PRINT_DEBUG('Error: ' || X_msg_data);
5312 END IF;
5313 GOTO next_dmd_record;
5314 END IF;
5315
5316 -- IMP NOTE: only HIGH LEVEL RSV can exists for 'demands slated for replenishment' at this point for
5317 -- BOTH type of replenishments since detailed rsv has been discarded from the original demand cursor
5318 -- BUT if somehow in between the time duration, user details one of the high
5319 -- LEVEL reservation demand line, we assume that he does not
5320 -- break reservation across different sub TO consume the demand qty
5321
5322
5323 IF l_mtl_reservation_count <> 0 THEN -- RSV EXISTS
5324
5325 -- FIND IF ALL RECORDS HAVE SAME TYPE OF RSV
5326 -- means EITHER HIGH LEVEL OR detail LEVEL at the SAME subinventory
5327 -- Note: Reservation can not be made for qty greater than demand_qty on the order
5328
5329
5330 l_rsv_id_tb.DELETE;
5331 IF (l_rsv_rec.count>0) THEN --bug#10185153
5332 FOR i IN l_rsv_rec.first.. l_rsv_rec.last LOOP
5333 l_rsv_id_tb(i) := l_rsv_rec(i).reservation_id;
5334 IF i <> 1 THEN
5335 IF (l_rsv_rec(i).subinventory_code IS NULL AND l_last_sub IS NOT NULL)
5336 OR
5337 (l_rsv_rec(i).subinventory_code IS NOT NULL AND l_last_sub IS NULL)
5338 OR (l_rsv_rec(i).subinventory_code IS NOT NULL AND
5339 l_last_sub IS NOT NULL AND l_rsv_rec(i).subinventory_code <> l_last_sub)
5340 THEN
5341 IF (l_debug = 1) THEN
5342 print_debug('SKIP Current Demand: Mixed level of reservation');
5343 END IF;
5344 -- means mixed level of rsv, we will rather CREATE NEW replenishment
5345 -- We will not account for these rsv in this case
5346 -- Since we need to skip to next demand and
5347 -- behave as if this demand is in error
5348 l_return_status := fnd_api.g_ret_sts_error;
5349 GOTO next_dmd_record;
5350 END IF;
5351
5352 END IF;
5353 l_last_sub := l_rsv_rec(i).subinventory_code;
5354
5355 -- What if the reserved qty is less than the demand
5356 -- qty, there IS left OUT qty FOR the line TO be reserved
5357 END LOOP;
5358 END IF;
5359
5360 IF (l_debug = 1) THEN
5361 print_debug('If Sub Level RSV, SUB :'||l_last_sub);
5362 END IF;
5363
5364 -- If the l_last_sub is not null, means detailed rsv
5365 -- because all rsv data has to be of same type either NULL OR same subinventory
5366
5367 IF l_last_sub is NULL THEN -- high level rsv
5368
5369 IF (l_debug = 1) THEN
5370 print_debug('****** It is High Level RSV Exists');
5371 print_debug('****** Call WSH to make Lines as RC');
5372 END IF;
5373
5374 -- Call Shipping API to mark the Delivery Detail TO 'RC'.
5375 update_wdd_repl_status (p_deliv_detail_id => l_demand_line_detail_id
5376 , p_repl_status => 'C' -- for completed status
5377 , x_return_status => l_return_status
5378 );
5379
5380 IF l_return_status <> fnd_api.g_ret_sts_success THEN
5381 GOTO next_dmd_record;
5382 END IF;
5383
5384
5385 -- Remove the entry from the WMS_REPL_DEMAND_GTMP table
5386 IF (l_debug = 1) THEN
5387 print_debug('Remove Entry from WRDG table');
5388 END IF;
5389 DELETE FROM wms_repl_demand_gtmp
5390 WHERE Organization_id = x_consol_item_repl_tbl(i).organization_id
5391 AND INVENTORY_ITEM_ID = x_consol_item_repl_tbl(i).item_id
5392 AND demand_type_id = l_demand_type_id
5393 AND DEMAND_LINE_DETAIL_ID = l_demand_line_detail_id
5394 AND demand_header_id = l_demand_header_id
5395 AND demand_line_id = l_demand_line_id;
5396
5397 -- Detail the reservation to the current sub. We will consume right here
5398 IF (l_debug = 1) THEN
5399 print_debug('Detail High Level Rsv to Detailed CURRENT sub :'
5400 || x_consol_item_repl_tbl(i).repl_to_subinventory_code);
5401 END IF;
5402 FORALL k in 1 .. l_rsv_rec.COUNT()
5403 UPDATE mtl_reservations
5404 SET subinventory_code = x_consol_item_repl_tbl(i).repl_to_subinventory_code
5405 WHERE reservation_id = l_rsv_id_tb(k);
5406
5407
5408 IF (l_debug = 1) THEN
5409 print_debug('Add to the available onhand for this item');
5410 END IF;
5411 -- In PL/SQL table, increase the available OnHand qty in repl_UOM by L_demand_quantity_in_repl_uom
5412 x_consol_item_repl_tbl(i).available_onhand_qty :=
5413 x_consol_item_repl_tbl(i).available_onhand_qty + L_demand_quantity_in_repl_uom;
5414
5415
5416 --Decrease the l_atr to reflect correct available OnHand qty for next demand line.
5417 --This seems to be a pessimistic approach. If all demands are at high level in the set and all material is in the current, then l_atr
5418 -- would already have deducted for all demands. If we deduct it again, we are asking for twice the qty than it should.
5419
5420 -- But above will not be a very common business scenario because if all material is in the current sub, then we will not be talking of replenishment here.
5421 -- In general pick areas will have minial quantity and major qty are stores in bulk areas in the facility
5422
5423 IF (l_debug = 1) THEN
5424 print_debug('decrese the consumed qty from the curent atr FOR this demand');
5425 END IF;
5426 -- All quantity comparision is in the primary unit
5427 l_atr := l_atr - l_demand_quantity;
5428
5429
5430 ELSIF l_last_sub = x_consol_item_repl_tbl(i).repl_to_subinventory_code THEN
5431 -- means detailed at Current sub
5432 IF (l_debug = 1) THEN
5433 print_debug('It is Detailed RSV at the current FP sub');
5434 print_debug('Call WSH to mark current dmand RC');
5435 END IF;
5436
5437
5438 -- Call Shipping API to mark the Delivery Detail TO 'RC'.
5439 update_wdd_repl_status (p_deliv_detail_id => l_demand_line_detail_id
5440 , p_repl_status => 'C' -- for completed status
5441 , x_return_status => l_return_status
5442 );
5443
5444 IF l_return_status <> fnd_api.g_ret_sts_success THEN
5445 GOTO next_dmd_record;
5446 END IF;
5447
5448 IF (l_debug = 1) THEN
5449 print_debug('Remove the entry from the WRDG table');
5450 END IF;
5451 -- Remove the entry from the WMS_REPL_DEMAND_GTMP table
5452 DELETE FROM wms_repl_demand_gtmp
5453 WHERE Organization_id = x_consol_item_repl_tbl(i).organization_id
5454 AND INVENTORY_ITEM_ID = x_consol_item_repl_tbl(i).item_id
5455 AND demand_type_id = l_demand_type_id
5456 AND DEMAND_LINE_DETAIL_ID = l_demand_line_detail_id
5457 AND demand_header_id = l_demand_header_id
5458 AND demand_line_id = l_demand_line_id;
5459
5460
5461 IF (l_debug = 1) THEN
5462 print_debug('Add to the available onhand for this item');
5463 END IF;
5464 -- In PL/SQL table, increase the available OnHand qty in repl_UOM by L_demand_quantity_in_repl_uom
5465 x_consol_item_repl_tbl(i).available_onhand_qty := x_consol_item_repl_tbl(i).available_onhand_qty + L_demand_quantity_in_repl_uom;
5466
5467
5468 --If the qty_tree is run the current_demand in the set then there we must decrease the demand_qty from l_atr BUT if the qty_tree was not run for
5469 --the current_demand then demand_qty should not be decreased from
5470 -- l_atr becse it has already been deducted when qty_tree returned
5471 -- l_atr.
5472
5473 IF (l_debug = 1) THEN
5474 print_debug('decrese the consumed qty only if atr was calculated FOR curent demand');
5475 END IF;
5476
5477 IF l_qty_tree_demand_line_id = l_demand_line_id THEN
5478 -- All quantity comparision is in the primary unit
5479 l_atr := l_atr - l_demand_quantity;
5480 END IF;
5481
5482
5483 ELSE -- menas detailed at other sub
5484 -- SKIP current demand line assuming it will be fulfilled up by other sub
5485 -- Since we need to skip to next demand and
5486 -- behave as if this demand is in error
5487 l_return_status := fnd_api.g_ret_sts_error;
5488 GOTO next_dmd_record;
5489 END IF;
5490
5491
5492
5493 ELSE --means rsv does not exists
5494
5495 IF (l_debug = 1) THEN
5496 print_debug('NO RESERVATION EXISTS FOR CURRENT DEMAND');
5497 END IF;
5498
5499
5500 IF p_Create_Reservation = 'Y' THEN
5501
5502 IF (l_debug = 1) THEN
5503 print_debug('p_Create_Rsv is Y and qty available - Creating detailed rsv AT FP sub' );
5504 END IF;
5505
5506 --TEST: CALL Create_RSV() API to create reservation AT DETAILED LEVEL to this sub
5507 l_return_status := fnd_api.g_ret_sts_success;
5508 Create_RSV(p_replenishment_type => 1, -- 1- Stock Up/Push; 2- Dynamic/Pull
5509 l_debug => l_debug,
5510 l_organization_id => x_consol_item_repl_tbl(i).ORGANIZATION_ID,
5511 l_inventory_item_id => x_consol_item_repl_tbl(i).item_id,
5512 l_demand_type_id => l_demand_type_id,
5513 l_demand_so_header_id => L_demand_header_id,
5514 l_demand_line_id => L_demand_line_id,
5515 l_split_wdd_id => NULL,
5516 l_primary_uom_code => l_demand_uom_code,
5517 l_supply_uom_code => l_demand_uom_code,
5518 l_atd_qty => L_demand_quantity,
5519 l_atd_prim_qty => L_demand_quantity,
5520 l_supply_type_id => 13,
5521 l_supply_header_id => NULL, -- since sub LEVEL from inventory
5522 l_supply_line_id => NULL, -- since sub LEVEL from inventory
5523 l_supply_line_detail_id => NULL, -- since sub LEVEL from inventory
5524 l_supply_expected_time => SYSDATE,
5525 l_demand_expected_time => l_expected_ship_date,
5526 l_subinventory_code => x_consol_item_repl_tbl(i).repl_to_subinventory_code,
5527 l_rsv_rec => l_rsv_temp_rec,
5528 l_serial_number => l_serial_number,
5529 l_to_serial_number => l_to_serial_number,
5530 l_quantity_reserved => l_quantity_reserved,
5531 l_quantity_reserved2 => l_quantity_reserved2,
5532 l_rsv_id => l_rsv_id,
5533 x_return_status => l_return_status,
5534 x_msg_count => x_msg_count,
5535 x_msg_data => x_msg_data
5536 );
5537
5538 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5539 IF (l_debug = 1) THEN
5540 print_debug('Error returned from create_reservation API: ' || l_return_status);
5541 END IF;
5542 -- Proceed to next record. In this case we might have extra amount on MOL than rsv
5543 GOTO next_dmd_record;
5544
5545 ELSE -- reservation creation successful
5546 IF (l_debug = 1) THEN
5547 print_debug('Successfully created a RSV for demand ');
5548 END IF;
5549
5550 END IF;
5551
5552 ELSE -- means p_Create_Reservation = 'N'
5553 -- DO nothing
5554 IF (l_debug = 1) THEN
5555 print_debug('p_Create_Rsv is N and qty available' );
5556 END IF;
5557 END IF; --p_Create_Reservation = 'Y'
5558
5559 -- Mark these demand records as 'RC'.
5560 -- These demand lines Status go directly from Ready to
5561 -- release to RC because material is physically present AT the sub
5562 -- < in case of open move order, we will not it will NOT be marked RC though>
5563 -- Note: In some cases lines might already by in
5564 -- repl_status = RC here BECS original demand cursol includes repl_status = 'C' demand lines
5565
5566 IF (l_debug = 1) THEN
5567 print_debug('call WSH to mark lines as RC' );
5568 END IF;
5569
5570 IF l_repl_status <> 'C' THEN
5571 update_wdd_repl_status (p_deliv_detail_id => l_demand_line_detail_id
5572 , p_repl_status => 'C' -- for completed status
5573 , x_return_status => l_return_status
5574 );
5575
5576 IF l_return_status <> fnd_api.g_ret_sts_success THEN
5577 GOTO next_dmd_record;
5578 END IF;
5579
5580 END IF; -- FOR IF l_repl_status <> 'C'
5581
5582
5583
5584 IF (l_debug = 1) THEN
5585 print_debug('Remove entry from GTMP table');
5586 END IF;
5587 -- Remove the demand entry from the WMS_REPL_DEMAND_GTMP table
5588 DELETE FROM wms_repl_demand_gtmp
5589 WHERE Organization_id = x_consol_item_repl_tbl(i).organization_id
5590 AND INVENTORY_ITEM_ID = x_consol_item_repl_tbl(i).item_id
5591 AND demand_type_id = l_demand_type_id
5592 AND DEMAND_LINE_DETAIL_ID = l_demand_line_detail_id
5593 AND demand_header_id = l_demand_header_id
5594 AND demand_line_id = l_demand_line_id;
5595
5596
5597 IF (l_debug = 1) THEN
5598 print_debug('Increase availble onhand and decrese l_atr');
5599 END IF;
5600 -- In PL/SQL table, increase the available OnHand qty in repl_UOM by L_demand_quantity_in_repl_uom
5601 x_consol_item_repl_tbl(i).available_onhand_qty
5602 := x_consol_item_repl_tbl(i).available_onhand_qty + L_demand_quantity_in_repl_uom;
5603
5604 -- Decrease the l_atr to reflect correct available OnHand qty for next demand line
5605 -- All quantity comparision is in the primary unit
5606 l_atr := l_atr - l_demand_quantity;
5607
5608
5609 END IF; -- FOR RSV EXISTS
5610
5611
5612 ELSE -- means l_atr < l_demand_qty
5613 -- Here it can come in one case when
5614 -- L_atr > 0 and l_atr < l_demand_qty in subsequent loops after consuming from l_atr
5615 -- Once l_atr becomes 0, it goes to other part of the else condition below
5616
5617 -- Available onhand (atr) = 22 at location [ out of this 22 QTY, 20 was for D1 initially but in this run another high priority otrder D2 has come above D1]
5618
5619 -- Demand demand_qty priority status Action/new status
5620 -- D2 10 high RC
5621 -- D1 20 low RC (no rsv exists for d1) Revert to original stat
5622 -- D3 2 lower Will be marked RC
5623 -- D4 5 lowest RC (no rsv exists for d1) Revert to original stat
5624 -- D5 10 lowest Do not touch
5625 -- After D2 gets processed and the at the time of processing D1, l_atr = 12 and l_demand_qty = 20
5626 -- D3 will be processed in the conditional block of 'l_atr >= l_demand_qty' above
5627 -- D5 will be processed in the conditional block ELSE -- means l_atr <= 0 below
5628
5629 IF (l_debug = 1) THEN
5630 print_debug('Here l_atr < l_demand_qty. Nothing to do..');
5631 END IF;
5632
5633
5634 IF l_repl_status = 'C' THEN
5635
5636 IF (l_debug = 1) THEN
5637 print_debug('DmdLine alredy RC, but this run does NOT have enough qty any longer ');
5638 print_debug('Backorder delivery_detail - l_demand_line_detail_id ');
5639 END IF;
5640 -- Code will come here only for Push Repl if Create_rsv = N
5641 -- Add to the global variable table to be backordered later
5642
5643 l_bkorder_cnt := g_backorder_deliv_tab.COUNT()+1;
5644
5645 g_backorder_deliv_tab(l_bkorder_cnt):= l_demand_line_detail_id;
5646 g_backorder_qty_tab(l_bkorder_cnt) := l_demand_quantity;
5647 -- since we are backordering entire qty parameters
5648 -- p_bo_qtys AND p_req_qtys will have same value
5649 g_dummy_table(l_bkorder_cnt) := 0;
5650
5651 END IF; -- FOR l_repl_status = 'C'
5652
5653
5654
5655 END IF; -- l_atr > l_demand_qty
5656
5657 ELSE -- MEANS l_atr <= 0
5658
5659 IF (l_debug = 1) THEN
5660 print_debug('Here l_atr <= 0 '||l_atr);
5661 END IF;
5662
5663 IF l_repl_status = 'C' THEN
5664
5665 IF (l_debug = 1) THEN
5666 print_debug('DmdLine already RC - but this run does NOT have enough qty any longer');
5667 print_debug('Backorder delivery_detail - l_demand_line_detail_id ');
5668 END IF;
5669 -- Code will come here only for Push Repl if Create_rsv = N
5670 -- Add to the global variable table to be backordered later
5671
5672 l_bkorder_cnt := g_backorder_deliv_tab.COUNT()+1;
5673
5674 g_backorder_deliv_tab(l_bkorder_cnt):= l_demand_line_detail_id;
5675 g_backorder_qty_tab(l_bkorder_cnt) := l_demand_quantity;
5676 -- since we are backordering entire qty parameters
5677 -- p_bo_qtys AND p_req_qtys will have same value
5678 g_dummy_table(l_bkorder_cnt) := 0;
5679
5680 END IF; --FOR l_repl_status = 'C'
5681
5682 END IF; -- FOR l_atr > 0
5683
5684 <<next_dmd_record>>
5685 l_prev_org_id := x_consol_item_repl_tbl(i).ORGANIZATION_ID ;
5686 l_prev_item_id := x_consol_item_repl_tbl(i).item_id;
5687 l_prev_sub_code := x_consol_item_repl_tbl(i).repl_to_subinventory_code;
5688 print_debug( 'l_atr AT THE END OF CURRENT DEMAND LINE: '||l_atr);
5689
5690 IF l_return_status <> fnd_api.g_ret_sts_success THEN
5691 IF (l_debug = 1 ) THEN
5692 print_debug('Move to next demand record ignoring this one');
5693 END IF;
5694 ROLLBACK TO onhd_demand_line_sp;
5695 l_return_status := fnd_api.g_ret_sts_success;
5696 x_consol_item_repl_tbl(i).total_demand_qty :=
5697 x_consol_item_repl_tbl(i).total_demand_qty - l_demand_quantity_in_repl_uom;
5698
5699 -- For pull and demand_type_id<>4, Backorder the WDD
5700 -- Add to the global variable table to be called at the end of
5701 -- the dynamic repl process
5702
5703 -- We do not need to do it for Push repl since rollback takes care
5704 -- of it whereas for Pull repl, shipping has committed his change and
5705 -- hence we need to make explicit call to backorder it
5706
5707 IF l_demand_type_id <> 4 AND p_repl_type = g_dynamic_repl AND
5708 Nvl(p_repl_level,1) = 1 THEN
5709
5710 l_bkorder_cnt := g_backorder_deliv_tab.COUNT()+1;
5711
5712 g_backorder_deliv_tab(l_bkorder_cnt):= l_demand_line_detail_id;
5713 g_backorder_qty_tab(l_bkorder_cnt) := l_demand_quantity;
5714 -- since we are backordering entire qty parameters
5715 -- p_bo_qtys AND p_req_qtys will have same value
5716 g_dummy_table(l_bkorder_cnt) := 0;
5717
5718 END IF;
5719
5720
5721 DELETE FROM wms_repl_demand_gtmp
5722 WHERE Organization_id = x_consol_item_repl_tbl(i).organization_id
5723 AND INVENTORY_ITEM_ID = x_consol_item_repl_tbl(i).item_id
5724 AND demand_type_id = l_demand_type_id
5725 AND DEMAND_LINE_DETAIL_ID = l_demand_line_detail_id
5726 AND demand_header_id = l_demand_header_id
5727 AND demand_line_id = l_demand_line_id;
5728
5729 END IF;
5730
5731 END LOOP; -- for each demand line
5732 CLOSE c_demand_lines_for_item;
5733
5734 --At the end for Each item+Sub In PL/SQL table, update the final_replenishment_qty in Repl_UOM
5735 x_consol_item_repl_tbl(i).final_replenishment_qty
5736 := (x_consol_item_repl_tbl(i).total_demand_qty - x_consol_item_repl_tbl(i).available_onhand_qty);
5737
5738 --Note: the final replenishment qty will be upp by the p_Repl_Lot_Size in Create_repl_Move_order() API
5739 <<next_onhd_consol_rec>>
5740 IF l_return_status <> fnd_api.g_ret_sts_success then
5741 l_return_status := fnd_api.g_ret_sts_success;
5742 ROLLBACK TO onhd_consol_rec_sp;
5743 -- if repl_type 2 and demand_type_id <> 4 then revert that WDD to original status
5744 -- remove all entries for that item from gtmp
5745 -- both done in following API
5746 Revert_Consol_item_changes
5747 ( p_repl_type => p_repl_type
5748 , p_demand_type_id => l_demand_type_id
5749 , P_item_id => x_consol_item_repl_tbl(i).item_ID
5750 , p_org_id => x_consol_item_repl_tbl(i).ORGANIZATION_ID
5751 , x_return_status => l_return_status
5752 );
5753
5754 -- Remove element from consol table, can not do inside this loop
5755 -- AS iterating through the same consol record
5756 -- store the index of the consol table to be deleted outside the loop
5757 l_del_index := l_del_index +1;
5758 l_del_consol_item_tb(l_del_index) := i;
5759
5760 END IF;
5761
5762
5763 END IF; --IF not x_consol_item_repl_tbl.exists(i)
5764
5765 END LOOP; -- main loop on pl/sql table
5766 END IF;
5767
5768 --REMOVE CONSOL RECORDS THAT HAS BEEN REMOVED FROM MOVER ORDER CREATION
5769 -- THIS WILL KEEP DATA IN SYNC
5770 FOR j IN 1..l_del_consol_item_tb.COUNT() LOOP
5771 x_consol_item_repl_tbl.DELETE(l_del_consol_item_tb(j));
5772 END LOOP;
5773
5774
5775 IF (l_debug = 1 ) THEN
5776 print_debug('DONE WITH GET_AVAILABLE_ONHAND_QTY API');
5777 END IF;
5778 x_return_status := fnd_api.g_ret_sts_success;
5779 EXCEPTION
5780 WHEN OTHERS THEN
5781 IF c_demand_lines_for_item%ISOPEN THEN
5782 CLOSE c_demand_lines_for_item;
5783 END IF;
5784 IF (l_debug = 1) THEN
5785 print_debug('Error in GET_AVAILABLE_ONHAND_QTY SQLCODE:'||SQLCODE ||' '||SQLERRM );
5786 END IF;
5787 x_return_status := fnd_api.g_ret_sts_error;
5788 END GET_AVAILABLE_ONHAND_QTY;
5789
5790
5791
5792
5793 PROCEDURE CREATE_RSV(p_replenishment_type IN NUMBER, -- 1- Stock Up/Push; 2- Dynamic
5794 l_debug IN NUMBER,
5795 l_organization_id IN NUMBER,
5796 l_inventory_item_id IN NUMBER,
5797 l_demand_type_id IN NUMBER,
5798 l_demand_so_header_id IN NUMBER,
5799 l_demand_line_id IN NUMBER,
5800 l_split_wdd_id IN NUMBER,
5801 l_primary_uom_code IN VARCHAR2,
5802 l_supply_uom_code IN VARCHAR2,
5803 l_atd_qty IN NUMBER,
5804 l_atd_prim_qty IN NUMBER,
5805 l_supply_type_id IN NUMBER,
5806 l_supply_header_id IN NUMBER,
5807 l_supply_line_id IN NUMBER,
5808 l_supply_line_detail_id IN NUMBER,
5809 l_supply_expected_time IN DATE,
5810 l_demand_expected_time IN DATE,
5811 l_subinventory_code IN VARCHAR2 DEFAULT NULL,
5812 l_rsv_rec IN OUT NOCOPY inv_reservation_global.mtl_reservation_rec_type,
5813 l_serial_number IN OUT NOCOPY inv_reservation_global.serial_number_tbl_type,
5814 l_to_serial_number IN OUT NOCOPY inv_reservation_global.serial_number_tbl_type,
5815 l_quantity_reserved IN OUT NOCOPY NUMBER,
5816 l_quantity_reserved2 IN OUT NOCOPY NUMBER,
5817 l_rsv_id IN OUT NOCOPY NUMBER,
5818 x_return_status IN OUT NOCOPY VARCHAR2,
5819 x_msg_count IN OUT NOCOPY NUMBER,
5820 x_msg_data IN OUT NOCOPY VARCHAR2)
5821 IS
5822
5823
5824 l_progress VARCHAR2(10);
5825
5826 BEGIN
5827
5828 --
5829 -- Set the values for the reservation record to be created
5830 IF (l_debug = 1) THEN
5831 print_debug('Requirement Date: ' || l_demand_expected_time);
5832 END IF;
5833
5834 l_rsv_rec.reservation_id := NULL;
5835 l_rsv_rec.requirement_date := l_demand_expected_time;
5836 l_rsv_rec.organization_id := l_organization_id;
5837 l_rsv_rec.inventory_item_id := l_inventory_item_id;
5838 l_rsv_rec.demand_source_name := NULL;
5839 l_rsv_rec.demand_source_type_id := l_demand_type_id;
5840 l_rsv_rec.demand_source_header_id := l_demand_so_header_id;
5841 -- here l_demand_so_header_id is inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id)
5842 l_rsv_rec.demand_source_line_id := l_demand_line_id;
5843 l_rsv_rec.orig_demand_source_type_id := l_demand_type_id;
5844 l_rsv_rec.orig_demand_source_header_id := l_demand_so_header_id;
5845 l_rsv_rec.orig_demand_source_line_id := l_demand_line_id;
5846
5847 -- For now supply is only from Inventory supply_source_type_id = 13
5848 l_rsv_rec.demand_source_line_detail := l_split_wdd_id;
5849 l_rsv_rec.orig_demand_source_line_detail := l_split_wdd_id;
5850
5851 l_rsv_rec.demand_source_delivery := NULL;
5852 l_rsv_rec.primary_uom_code := l_primary_uom_code;
5853 l_rsv_rec.primary_uom_id := NULL;
5854 l_rsv_rec.secondary_uom_code := null;
5855 l_rsv_rec.secondary_uom_id := NULL;
5856 l_rsv_rec.reservation_uom_code := l_supply_uom_code;
5857 l_rsv_rec.reservation_uom_id := NULL;
5858 l_rsv_rec.reservation_quantity := l_atd_qty;
5859 l_rsv_rec.primary_reservation_quantity := l_atd_prim_qty;
5860 l_rsv_rec.secondary_reservation_quantity := null;
5861 l_rsv_rec.detailed_quantity := NULL;
5862 l_rsv_rec.secondary_detailed_quantity := NULL;
5863 l_rsv_rec.autodetail_group_id := NULL;
5864 l_rsv_rec.external_source_code := 'REPL'; -- Mark the external source
5865 l_rsv_rec.external_source_line_id := NULL;
5866 l_rsv_rec.supply_source_type_id := l_supply_type_id;
5867 l_rsv_rec.orig_supply_source_type_id := l_supply_type_id;
5868 l_rsv_rec.supply_source_name := NULL;
5869
5870 l_rsv_rec.supply_source_header_id := l_supply_header_id;
5871 l_rsv_rec.supply_source_line_id := l_supply_line_id;
5872 l_rsv_rec.supply_source_line_detail := l_supply_line_detail_id;
5873 l_rsv_rec.orig_supply_source_header_id := l_supply_header_id;
5874 l_rsv_rec.orig_supply_source_line_id := l_supply_line_id;
5875 l_rsv_rec.orig_supply_source_line_detail := l_supply_line_detail_id;
5876
5877 l_rsv_rec.revision := NULL;
5878 l_rsv_rec.subinventory_code := l_subinventory_code;
5879 l_rsv_rec.subinventory_id := NULL;
5880 l_rsv_rec.locator_id := NULL;
5881 l_rsv_rec.lot_number := NULL;
5882 l_rsv_rec.lot_number_id := NULL;
5883 l_rsv_rec.pick_slip_number := NULL;
5884 l_rsv_rec.lpn_id := NULL;
5885 l_rsv_rec.attribute_category := NULL;
5886 l_rsv_rec.attribute1 := NULL;
5887 l_rsv_rec.attribute2 := NULL;
5888 l_rsv_rec.attribute3 := NULL;
5889 l_rsv_rec.attribute4 := NULL;
5890 l_rsv_rec.attribute5 := NULL;
5891 l_rsv_rec.attribute6 := NULL;
5892 l_rsv_rec.attribute7 := NULL;
5893 l_rsv_rec.attribute8 := NULL;
5894 l_rsv_rec.attribute9 := NULL;
5895 l_rsv_rec.attribute10 := NULL;
5896 l_rsv_rec.attribute11 := NULL;
5897 l_rsv_rec.attribute12 := NULL;
5898 l_rsv_rec.attribute13 := NULL;
5899 l_rsv_rec.attribute14 := NULL;
5900 l_rsv_rec.attribute15 := NULL;
5901 l_rsv_rec.ship_ready_flag := NULL;
5902 l_rsv_rec.staged_flag := NULL;
5903
5904 l_rsv_rec.crossdock_flag := NULL;
5905 l_rsv_rec.crossdock_criteria_id := NULL;
5906
5907 l_rsv_rec.serial_reservation_quantity := NULL;
5908 l_rsv_rec.supply_receipt_date := l_supply_expected_time;
5909 l_rsv_rec.demand_ship_date := l_demand_expected_time;
5910 l_rsv_rec.project_id := NULL;
5911 l_rsv_rec.task_id := NULL;
5912 l_rsv_rec.serial_number := NULL;
5913
5914 IF (l_debug = 1) THEN
5915 print_debug('Call the create_reservation API to create the replenishemnt reservation');
5916 END IF;
5917
5918 INV_RESERVATION_PVT.create_reservation(p_api_version_number => 1.0,
5919 p_init_msg_lst => fnd_api.g_false,
5920 x_return_status => x_return_status,
5921 x_msg_count => x_msg_count,
5922 x_msg_data => x_msg_data,
5923 p_rsv_rec => l_rsv_rec,
5924 p_serial_number => l_serial_number,
5925 x_serial_number => l_to_serial_number,
5926 p_partial_reservation_flag => fnd_api.g_false,
5927 p_force_reservation_flag => fnd_api.g_false,
5928 p_validation_flag => fnd_api.g_true,
5929 x_quantity_reserved => l_quantity_reserved,
5930 x_secondary_quantity_reserved => l_quantity_reserved2,
5931 x_reservation_id => l_rsv_id);
5932
5933 IF (x_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
5934 IF (l_debug = 1) THEN
5935
5936 print_debug('Error returned from INV create_reservation API: ' ||
5937 x_return_status);
5938 END IF;
5939 -- Raise an exception. The caller will do the rollback, cleanups,
5940 RAISE FND_API.G_EXC_ERROR;
5941
5942 END IF;
5943
5944 l_progress := '20';
5945
5946 EXCEPTION
5947 WHEN OTHERS THEN
5948 x_return_status := fnd_api.g_ret_sts_error;
5949 fnd_msg_pub.count_and_get(p_count => x_msg_count,
5950 p_data => x_msg_data);
5951 IF (l_debug = 1) THEN
5952 print_debug('Exiting Create_RSV - Execution error: ' || l_progress || ' ' ||
5953 TO_CHAR(SYSDATE, 'YYYY-MM-DD HH:DD:SS')|| ' ' ||x_msg_data);
5954 END IF;
5955
5956 END Create_RSV;
5957
5958
5959
5960
5961 FUNCTION Get_Expected_Time(p_demand_type_id in number,
5962 p_source_header_id in number,
5963 p_source_line_id in number,
5964 p_delivery_line_id in number) RETURN DATE
5965 IS
5966
5967
5968
5969 l_demand_expected_time DATE := null;
5970
5971 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
5972
5973
5974 CURSOR wdd_rec_cursor IS
5975 SELECT NVL(wts.planned_departure_date,
5976 NVL(wdd.date_scheduled,
5977 NVL(ool.schedule_ship_date, ool.promise_date))) AS expected_ship_date
5978 FROM wsh_delivery_details wdd, oe_order_lines_all ool,
5979 wsh_delivery_assignments_v wda, wsh_new_deliveries wnd, wsh_delivery_legs wdl,
5980 wsh_trip_stops wts, wsh_trips wt
5981 WHERE wdd.delivery_detail_id = p_delivery_line_id
5982 AND ool.line_id = p_source_line_id
5983 AND wdd.source_line_id = ool.line_id
5984 AND wdd.source_header_id = p_source_header_id
5985 AND wdd.delivery_detail_id = wda.delivery_detail_id (+)
5986 AND wda.delivery_id = wnd.delivery_id (+)
5987 AND wnd.delivery_id = wdl.delivery_id (+)
5988 AND (wdl.sequence_number IS NULL OR
5989 wdl.sequence_number = (SELECT MIN(sequence_number)
5990 FROM wsh_delivery_legs wdl_first_leg
5991 WHERE wdl_first_leg.delivery_id = wdl.delivery_id))
5992 AND wdl.pick_up_stop_id = wts.stop_id (+)
5993 AND wts.trip_id = wt.trip_id (+);
5994
5995 BEGIN
5996
5997 IF (p_demand_type_id NOT IN (2, 8)) THEN
5998 RETURN NULL;
5999 END IF;
6000
6001 -- IF (l_debug = 1) THEN
6002 -- print_debug('===============================');
6003 -- print_debug('p_demand_type_id : ' ||p_demand_type_id);
6004 -- print_debug(' p_source_header_id : ' || p_source_header_id);
6005 -- print_debug('p_source_line_id : ' ||p_source_line_id );
6006 -- print_debug('p_delivery_line_id : ' ||p_delivery_line_id);
6007 -- END IF;
6008
6009
6010 OPEN wdd_rec_cursor;
6011 FETCH wdd_rec_cursor INTO l_demand_expected_time;
6012 IF (wdd_rec_cursor%NOTFOUND) THEN
6013 IF (l_debug = 1) THEN
6014 print_debug('WDD cursor did not return any records!');
6015 END IF;
6016 l_demand_expected_time := NULL;
6017 END IF;
6018 CLOSE wdd_rec_cursor;
6019
6020 IF l_debug = 1 THEN
6021 print_debug('******Returning Get_Expected_Time : '||l_demand_expected_time );
6022 END IF;
6023
6024 RETURN l_demand_expected_time;
6025
6026 EXCEPTION
6027 WHEN OTHERS THEN
6028 IF l_debug = 1 THEN
6029 print_debug('Get_Expected_Time: ' || sqlcode || ', ' || sqlerrm);
6030 END IF;
6031 END Get_Expected_Time;
6032
6033
6034
6035
6036 FUNCTION GET_SORT_TRIP_STOP_DATE(P_delivery_detail_id IN NUMBER,
6037 P_TRIP_STOP_DATE_SORT IN VARCHAR2)
6038 RETURN NUMBER
6039 IS
6040
6041 -- If the current delivery detail is a part of a trip that has multiple
6042 -- deliveries each HAVING its own planned_departure_date, THEN MIN needs to
6043 -- be selected
6044
6045 CURSOR c_planned_departure_date IS
6046 SELECT MIN(NVL(wts.planned_departure_date, wdd.date_scheduled))
6047 -- MIN(NVL(wts.planned_departure_date,
6048 -- NVL(wdd.date_scheduled,
6049 -- NVL(ool.schedule_ship_date, ool.promise_date)))) AS min_expected_ship_date,
6050 FROM wsh_new_deliveries wnd, wsh_delivery_details wdd, wsh_delivery_assignments_v wda,
6051 wsh_delivery_legs wdl, wsh_trip_stops wts
6052 -- oe_order_lines_all ool
6053
6054 WHERE wdd.delivery_detail_id = p_delivery_detail_id
6055 -- AND wdd.source_line_id = ool.line_id (+)
6056 AND wnd.shipment_direction = 'O'
6057 AND wnd.delivery_id = wda.delivery_id (+)
6058 AND wda.delivery_detail_id = wdd.delivery_detail_id (+)
6059 AND wnd.delivery_id = wdl.delivery_id (+)
6060 AND (wdl.sequence_number IS NULL OR
6061 wdl.sequence_number = (SELECT MIN(sequence_number)
6062 FROM wsh_delivery_legs wdl_first_leg
6063 WHERE wdl_first_leg.delivery_id = wdl.delivery_id))
6064 AND wdl.pick_up_stop_id = wts.stop_id (+)
6065 GROUP BY wnd.organization_id, wnd.delivery_id, wts.stop_id;
6066
6067
6068 l_planned_departure_date date;
6069 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6070
6071 BEGIN
6072
6073 -- <<c_planned_departure_date(wdd.delivery_detail_id) will return planned trip date based on WTS.PLANNED_DEPARTURE_DATE if any exists>>
6074
6075 --TEST: correst planned date is passed
6076 OPEN c_planned_departure_date;
6077 LOOP
6078 FETCH c_planned_departure_date INTO l_planned_departure_date;
6079 EXIT WHEN c_planned_departure_date%NOTFOUND;
6080 END LOOP;
6081 CLOSE c_planned_departure_date;
6082
6083 IF (l_debug = 1) THEN
6084 print_debug('get_planned_departure_date: '||l_planned_departure_date);
6085 END IF;
6086
6087
6088 IF l_planned_departure_date is NULL THEN
6089 RETURN NULL;
6090
6091 ELSE
6092
6093 IF P_TRIP_STOP_DATE_SORT = 'ASC' then
6094 RETURN (l_planned_departure_date - TO_DATE('01-01-1700 23:59:59', 'DD-MM-YYYY HH24:MI:SS'));
6095
6096 ELSIF P_TRIP_STOP_DATE_SORT = 'DESC' then
6097 RETURN (TO_DATE('01-01-1700 23:59:59', 'DD-MM-YYYY HH24:MI:SS') - l_planned_departure_date);
6098
6099 ELSE
6100 --means P_TRIP_STOP_DATE_SORT is NULL
6101 RETURN NULL;
6102 END IF;
6103
6104 END IF;
6105
6106 EXCEPTION
6107 WHEN OTHERS THEN
6108 IF l_debug = 1 THEN
6109 print_debug('GET_SORT_TRIP_STOP_DATE: ' || sqlcode || ', ' || sqlerrm);
6110 END IF;
6111 END GET_SORT_TRIP_STOP_DATE;
6112
6113
6114
6115
6116 FUNCTION GET_SORT_INVOICE_VALUE(P_SOURCE_HEADER_ID NUMBER, P_INVOICE_VALUE_SORT VARCHAR2)
6117 RETURN NUMBER
6118 IS
6119 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6120 BEGIN
6121
6122
6123 IF P_INVOICE_VALUE_SORT = 'ASC' THEN
6124 RETURN WSH_PICK_CUSTOM.OUTSTANDING_ORDER_VALUE(p_SOURCE_HEADER_ID);
6125
6126 ELSIF P_INVOICE_VALUE_SORT = 'DESC' THEN
6127 RETURN (-1 * WSH_PICK_CUSTOM.OUTSTANDING_ORDER_VALUE(p_SOURCE_HEADER_ID));
6128
6129 ELSE
6130 RETURN NULL;
6131 END IF;
6132
6133
6134 EXCEPTION
6135 WHEN OTHERS THEN
6136 IF l_debug = 1 THEN
6137 print_debug('GET_SORT_INVOICE_VALUE: ' || sqlcode || ', ' || sqlerrm);
6138 END IF;
6139
6140 END GET_SORT_INVOICE_VALUE;
6141
6142
6143 FUNCTION get_available_capacity(p_quantity_function IN NUMBER,
6144 p_organization_id IN NUMBER,
6145 p_subinventory_code IN VARCHAR2,
6146 p_locator_id IN NUMBER,
6147 p_inventory_item_id IN NUMBER,
6148 p_unit_volume IN NUMBER,
6149 p_unit_volume_uom_code IN VARCHAR2,
6150 p_unit_weight IN NUMBER,
6151 p_unit_weight_uom_code IN VARCHAR2,
6152 p_primary_uom IN VARCHAR2,
6153 p_transaction_uom IN VARCHAR2,
6154 p_base_uom IN VARCHAR2,
6155 p_transaction_quantity IN NUMBER)
6156 RETURN NUMBER
6157
6158 IS
6159 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6160 l_possible_quantity NUMBER;
6161 l_sec_possible_quantity NUMBER;
6162
6163 BEGIN
6164 IF (l_debug = 1) THEN
6165 print_debug('get_available_capacity - qty function code: ' || p_quantity_function);
6166 END IF;
6167
6168
6169 IF p_quantity_function is NOT NULL THEN
6170 IF p_quantity_function = 530003 THEN
6171 l_possible_quantity :=
6172 wms_parameter_pvt.getavailableunitcapacity
6173 (
6174 p_organization_id => p_organization_id
6175 , p_subinventory_code => p_subinventory_code
6176 , p_locator_id => p_locator_id
6177 );
6178 ELSIF p_quantity_function = 530007 THEN
6179 l_possible_quantity :=
6180 wms_parameter_pvt.getavailablevolumecapacity
6181 (
6182 p_organization_id => p_organization_id
6183 , p_subinventory_code => p_subinventory_code
6184 , p_locator_id => p_locator_id
6185 , p_inventory_item_id => p_inventory_item_id
6186 , p_unit_volume => p_unit_volume
6187 , p_unit_volume_uom_code => p_unit_volume_uom_code
6188 , p_primary_uom => p_primary_uom
6189 , p_transaction_uom => p_transaction_uom
6190 , p_base_uom => p_base_uom
6191 );
6192 ELSIF p_quantity_function = 530011 THEN
6193 l_possible_quantity :=
6194 wms_parameter_pvt.getavailableweightcapacity
6195 (
6196 p_organization_id => p_organization_id
6197 , p_subinventory_code => p_subinventory_code
6198 , p_locator_id => p_locator_id
6199 , p_inventory_item_id => p_inventory_item_id
6200 , p_unit_weight => p_unit_weight
6201 , p_unit_weight_uom_code => p_unit_weight_uom_code
6202 , p_primary_uom => p_primary_uom
6203 , p_transaction_uom => p_transaction_uom
6204 , p_base_uom => p_base_uom
6205 );
6206 ELSIF p_quantity_function = 530015 THEN
6207 l_possible_quantity :=
6208 wms_parameter_pvt.getminimumavailablevwcapacity
6209 (
6210 p_organization_id => p_organization_id
6211 , p_subinventory_code => p_subinventory_code
6212 , p_locator_id => p_locator_id
6213 , p_inventory_item_id => p_inventory_item_id
6214 , p_unit_volume => p_unit_volume
6215 , p_unit_volume_uom_code => p_unit_volume_uom_code
6216 , p_unit_weight => p_unit_weight
6217 , p_unit_weight_uom_code => p_unit_weight_uom_code
6218 , p_primary_uom => p_primary_uom
6219 , p_transaction_uom => p_transaction_uom
6220 , p_base_uom => p_base_uom
6221 );
6222 ELSIF p_quantity_function = 530019 THEN
6223 l_possible_quantity :=
6224 wms_parameter_pvt.getminimumavailableuvwcapacity
6225 (
6226 p_organization_id => p_organization_id
6227 , p_subinventory_code => p_subinventory_code
6228 , p_locator_id => p_locator_id
6229 , p_inventory_item_id => p_inventory_item_id
6230 , p_unit_volume => p_unit_volume
6231 , p_unit_volume_uom_code => p_unit_volume_uom_code
6232 , p_unit_weight => p_unit_weight
6233 , p_unit_weight_uom_code => p_unit_weight_uom_code
6234 , p_primary_uom => p_primary_uom
6235 , p_transaction_uom => p_transaction_uom
6236 , p_base_uom => p_base_uom
6237 );
6238 ELSIF p_quantity_function = 530023 THEN
6239 l_possible_quantity :=
6240 wms_re_custom_pub.getavailablelocationcapacity
6241 (
6242 p_organization_id => p_organization_id
6243 , p_subinventory_code => p_subinventory_code
6244 , p_locator_id => p_locator_id
6245 , p_inventory_item_id => p_inventory_item_id
6246 , p_transaction_quantity => p_transaction_quantity
6247 , p_transaction_uom => p_transaction_uom
6248 );
6249 ELSE
6250 l_possible_quantity := 0;
6251 IF (l_debug = 1) THEN
6252 print_debug('bad_qtyF - Invalid Quantity Function');
6253 END IF;
6254 END IF;
6255
6256 ELSE -- means p_quantity_function is null
6257 -- capacity should not be considered
6258 l_possible_quantity := 1e125;
6259 l_sec_possible_quantity := 1e125;
6260 END IF;
6261
6262 IF l_debug = 1 THEN
6263 print_debug('Avail. capacity: ' || l_possible_quantity);
6264
6265 END IF;
6266
6267 RETURN l_possible_quantity ;
6268
6269 EXCEPTION
6270 WHEN OTHERS THEN
6271 IF l_debug = 1 THEN
6272 print_debug('Exception in Get_Available_Capacity: ' || sqlcode || ', ' || sqlerrm);
6273 END IF;
6274
6275 END Get_Available_Capacity;
6276
6277
6278
6279
6280 PROCEDURE Get_to_Sub_For_Dynamic_Repl(P_Org_id IN NUMBER,
6281 P_Item_id IN NUMBER,
6282 P_PRIMARY_DEMAND_QTY IN NUMBER,
6283 X_TO_SUBINVENTORY_CODE IN OUT NOCOPY VARCHAR2,
6284 X_REPL_UOM_CODE OUT NOCOPY VARCHAR2)
6285 IS
6286 CURSOR c_destination_sub IS
6287 SELECT SECONDARY_INVENTORY, PICK_UOM_CODE
6288 FROM (select MISI.SECONDARY_INVENTORY,
6289 MSI.PICK_UOM_CODE,
6290 MSIB.PRIMARY_UOM_CODE,
6291 get_conversion_rate(MISI.INVENTORY_ITEM_id,
6292 MSI.PICK_UOM_CODE,
6293 MSIB.PRIMARY_UOM_CODE) AS CONVERSION_RATE
6294 from MTL_ITEM_SUB_INVENTORIES MISI,
6295 MTL_SECONDARY_INVENTORIES MSI,
6296 MTL_SYSTEM_ITEMS_B MSIB
6297 WHERE MISI.organization_id = P_Org_id
6298 and MISI.INVENTORY_ITEM_ID = P_Item_id
6299 AND MISI.SECONDARY_INVENTORY = MSI.SECONDARY_INVENTORY_NAME
6300 AND MISI.ORGANIZATION_ID = MSI.ORGANIZATION_ID
6301 AND MSI.PICK_UOM_CODE IS NOT NULL
6302 --AND MOD(P_PRIMARY_DEMAND_QTY,(get_conversion_rate(MISI.INVENTORY_ITEM_id,MSI.PICK_UOM_CODE,MSIB.PRIMARY_UOM_CODE)))=0
6303 AND P_PRIMARY_DEMAND_QTY/get_conversion_rate(MISI.INVENTORY_ITEM_id,MSI.PICK_UOM_CODE,MSIB.PRIMARY_UOM_CODE) >= 1 --13419401
6304 AND get_conversion_rate(MISI.INVENTORY_ITEM_id,
6305 MSI.PICK_UOM_CODE,
6306 MSIB.PRIMARY_UOM_CODE) > 0
6307 AND MISI.INVENTORY_ITEM_id = MSIB.INVENTORY_ITEM_id
6308 AND MISI.ORGANIZATION_ID = MSIB.ORGANIZATION_ID
6309 ORDER BY CONVERSION_RATE DESC, MSI.PICKING_ORDER) X
6310 WHERE ROWNUM = 1;
6311
6312 l_debug number := NVL(FND_PROFILE.VALUE('INV_DEBUG_TRACE'),0);
6313
6314
6315 BEGIN
6316
6317 IF (l_debug = 1) THEN
6318 print_debug('Inside Get_to_Sub_For_Dynamic_Repl: TO_SUB :' ||X_TO_SUBINVENTORY_CODE);
6319 END IF;
6320
6321
6322 IF x_to_subinventory_code IS NOT NULL THEN
6323 -- THIS SUB VALUE WAS SPECIFIED WHILE CREATING THE SO, JUST FIND THE UOM CODE
6324
6325 SELECT PICK_UOM_CODE INTO x_repl_uom_code
6326 FROM MTL_SECONDARY_INVENTORIES MSI
6327 WHERE MSI.ORGANIZATION_ID = p_org_id
6328 and secondary_inventory_name = x_to_subinventory_code;
6329
6330
6331 ELSE
6332 -- FIND THE TO_SUB BASED ON LOGIC BELOW
6333
6334 -- 2.1- Get the item and find out possible destination-sub candidates
6335 --from the item-subinventory table (MTL_ITEM_SUB_INVENTORIES).
6336 -- Make sure that these subinventories have pick-uom defined as well.
6337
6338 --2.2- Rank these subinventories in the decreasing order of pick-uom
6339 --conversion (with respect to primary UOM for the item) and 'Picking
6340 -- order defined for the sub (Note: it does not matter whether source subinventory is defined for these destination subs in the item-subinventory form)
6341
6342 --2.3- Among all these destination Sub with pick-UOM, pick the one that has the replenishment_qty as a whole number multiple of conversion qty.
6343 -- (Example: Consider the hierarchy PALLET(PLT) > CASE(CS) > EACH(Ea);
6344 -- Conversion factors of PLT= 100Ea and CS = 10 Ea;
6345 -- If the repl_qty = 23; then chosen destination sub will be EACH
6346 -- If the repl_qty = 30; then chosen destination sub will be CASE
6347 -- If the repl_qty = 123; then chosen destination sub will be EACH
6348 -- If the repl_qty = 130; then chosen destination sub will be CASE
6349 -- If the repl_qty = 100; then chosen destination sub will be PALLET)
6350
6351 -- Justification: in 80% of the cases, qty need to be replenished for small orders from small pick uom areas. For all big orders they order in whole numbers only (like PLT or CS)
6352
6353 -- Note: conversion rate is in from higher UOM to lower UOM
6354
6355 OPEN c_destination_sub;
6356 LOOP
6357 FETCH c_destination_sub
6358 INTO X_TO_SUBINVENTORY_CODE, X_REPL_UOM_CODE;
6359 EXIT WHEN c_destination_sub%NOTFOUND;
6360 END LOOP;
6361 CLOSE c_destination_sub;
6362
6363 -- Value of X_TO_SUBINVENTORY_CODE and X_REPL_UOM_CODE is NULL menas
6364 -- Either no record for the item exist in the item-sub form
6365 -- OR Conversion UOM was not specified the identified sub and corresponding picking uom for the sub
6366 -- OR PICK_UOM_CODE was not specified for the sub that is specified in the item-sub form
6367
6368 END IF; -- FOR x_to_subinventory_code IS NOT NULL
6369
6370
6371 IF (l_debug = 1) THEN
6372
6373 print_debug( 'Dynamic Repl: X_TO_SUBINVENTORY_CODE :' || X_TO_SUBINVENTORY_CODE);
6374 print_debug( 'Dynamic Repl: X_REPL_UOM_CODE :' || X_REPL_UOM_CODE);
6375
6376 END IF;
6377
6378 EXCEPTION
6379 WHEN OTHERS THEN
6380
6381 IF c_destination_sub%ISOPEN THEN
6382 CLOSE c_destination_sub;
6383 END IF;
6384 IF l_debug = 1 THEN
6385 print_debug('Exception in Get_to_Sub_For_Dynamic_Repl: ' || sqlcode || ', ' || sqlerrm);
6386 END IF;
6387
6388 END Get_to_Sub_For_Dynamic_Repl;
6389
6390
6391
6392 PROCEDURE POPULATE_DYNAMIC_REPL_DEMAND(p_repl_level IN NUMBER,
6393 p_org_id IN NUMBER,
6394 P_Batch_id IN NUMBER,
6395 p_Release_Sequence_Rule_Id IN NUMBER,
6396 x_consol_item_repl_tbl OUT NOCOPY CONSOL_ITEM_REPL_TBL,
6397 x_return_status OUT NOCOPY VARCHAR2,
6398 x_msg_count OUT NOCOPY NUMBER,
6399 x_msg_data OUT NOCOPY VARCHAR2)
6400 IS
6401
6402 L_ORDER_ID_SORT VARCHAR2(4) := NULL;
6403 L_INVOICE_VALUE_SORT VARCHAR2(4) := NULL;
6404 L_SCHEDULE_DATE_SORT VARCHAR2(4) := NULL;
6405 L_TRIP_STOP_DATE_SORT VARCHAR2(4) := NULL;
6406 L_SHIPMENT_PRI_SORT VARCHAR2(4) := NULL;
6407 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
6408
6409 CURSOR c_dynamic_repl_demand IS
6410 SELECT wdd.inventory_item_id as item_id,
6411 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id) AS header_id,
6412 wdd.source_line_id AS line_id,
6413 wdd.delivery_detail_id,
6414 decode(wdd.source_document_type_id, 10, 8, 2) as demand_type_id, -- for SO=2 and Internal Order=8
6415 wdd.requested_quantity, -- this is always stored in primary UOM
6416 wdd.requested_quantity_uom,
6417 NVL(WMS_REPLENISHMENT_PVT.Get_Expected_Time(decode(wdd.source_document_type_id, 10, 8, 2),
6418 wdd.source_header_id,
6419 wdd.source_line_id,
6420 wdd.delivery_detail_id),
6421 WDD.date_scheduled) as expected_ship_date,
6422 wdd.subinventory,
6423 wdd.replenishment_status,
6424 wdd.released_status,
6425 -- get for sort_attribute1
6426 To_number(DECODE(p_Release_Sequence_Rule_Id,
6427 null,
6428 null,
6429 DECODE(g_ordered_psr(1).attribute_name,
6430 'ORDER_NUMBER',
6431 DECODE(L_ORDER_ID_SORT,
6432 'ASC',
6433 To_number(wdd.source_header_number),
6434 'DESC',
6435 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
6436 null),
6437 'SHIPMENT_PRIORITY',
6438 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
6439 'High',
6440 20,
6441 'Standard',
6442 10,
6443 NULL),
6444 'INVOICE_VALUE',
6445 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
6446 L_INVOICE_VALUE_SORT),
6447 'SCHEDULE_DATE',
6448 DECODE(L_SCHEDULE_DATE_SORT,
6449 'ASC',
6450 (WDD.DATE_SCHEDULED -
6451 TO_DATE('01-01-1700 23:59:59',
6452 'DD-MM-YYYY HH24:MI:SS')),
6453 'DESC',
6454 (TO_DATE('01-01-1700 23:59:59',
6455 'DD-MM-YYYY HH24:MI:SS') -
6456 WDD.DATE_SCHEDULED),
6457 null),
6458 'TRIP_STOP_DATE',
6459 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
6460 L_TRIP_STOP_DATE_SORT),
6461 NULL))) as sort_attribute1,
6462
6463 -- get for sort_attribute2
6464 To_number(DECODE(p_Release_Sequence_Rule_Id,
6465 null,
6466 null,
6467 DECODE(g_ordered_psr(2).attribute_name,
6468 'ORDER_NUMBER',
6469 DECODE(L_ORDER_ID_SORT,
6470 'ASC',
6471 To_number(wdd.source_header_number),
6472 'DESC',
6473 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
6474 null),
6475 'SHIPMENT_PRIORITY',
6476 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
6477 'High',
6478 20,
6479 'Standard',
6480 10,
6481 NULL),
6482 'INVOICE_VALUE',
6483 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
6484 L_INVOICE_VALUE_SORT),
6485 'SCHEDULE_DATE',
6486 DECODE(L_SCHEDULE_DATE_SORT,
6487 'ASC',
6488 (WDD.DATE_SCHEDULED -
6489 TO_DATE('01-01-1700 23:59:59',
6490 'DD-MM-YYYY HH24:MI:SS')),
6491 'DESC',
6492 (TO_DATE('01-01-1700 23:59:59',
6493 'DD-MM-YYYY HH24:MI:SS') -
6494 WDD.DATE_SCHEDULED),
6495 null),
6496 'TRIP_STOP_DATE',
6497 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
6498 L_TRIP_STOP_DATE_SORT),
6499 NULL))) as sort_attribute2,
6500
6501 -- get for sort_attribute3
6502 To_number(DECODE(p_Release_Sequence_Rule_Id,
6503 null,
6504 null,
6505 DECODE(g_ordered_psr(3).attribute_name,
6506 'ORDER_NUMBER',
6507 DECODE(L_ORDER_ID_SORT,
6508 'ASC',
6509 To_number(wdd.source_header_number),
6510 'DESC',
6511 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
6512 null),
6513 'SHIPMENT_PRIORITY',
6514 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
6515 'High',
6516 20,
6517 'Standard',
6518 10,
6519 NULL),
6520 'INVOICE_VALUE',
6521 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
6522 L_INVOICE_VALUE_SORT),
6523 'SCHEDULE_DATE',
6524 DECODE(L_SCHEDULE_DATE_SORT,
6525 'ASC',
6526 (WDD.DATE_SCHEDULED -
6527 TO_DATE('01-01-1700 23:59:59',
6528 'DD-MM-YYYY HH24:MI:SS')),
6529 'DESC',
6530 (TO_DATE('01-01-1700 23:59:59',
6531 'DD-MM-YYYY HH24:MI:SS') -
6532 WDD.DATE_SCHEDULED),
6533 null),
6534 'TRIP_STOP_DATE',
6535 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
6536 L_TRIP_STOP_DATE_SORT),
6537 NULL))) as sort_attribute3,
6538
6539 -- get for sort_attribute4
6540 To_number(DECODE(p_Release_Sequence_Rule_Id,
6541 null,
6542 null,
6543 DECODE(g_ordered_psr(4).attribute_name,
6544 'ORDER_NUMBER',
6545 DECODE(L_ORDER_ID_SORT,
6546 'ASC',
6547 To_number(wdd.source_header_number),
6548 'DESC',
6549 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
6550 null),
6551 'SHIPMENT_PRIORITY',
6552 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
6553 'High',
6554 20,
6555 'Standard',
6556 10,
6557 NULL),
6558 'INVOICE_VALUE',
6559 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
6560 L_INVOICE_VALUE_SORT),
6561 'SCHEDULE_DATE',
6562 DECODE(L_SCHEDULE_DATE_SORT,
6563 'ASC',
6564 (WDD.DATE_SCHEDULED -
6565 TO_DATE('01-01-1700 23:59:59',
6566 'DD-MM-YYYY HH24:MI:SS')),
6567 'DESC',
6568 (TO_DATE('01-01-1700 23:59:59',
6569 'DD-MM-YYYY HH24:MI:SS') -
6570 WDD.DATE_SCHEDULED),
6571 null),
6572 'TRIP_STOP_DATE',
6573 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
6574 L_TRIP_STOP_DATE_SORT),
6575 NULL))) as sort_attribute4,
6576
6577 -- get for sort_attribute5
6578 To_number(DECODE(p_Release_Sequence_Rule_Id,
6579 null,
6580 null,
6581 DECODE(g_ordered_psr(5).attribute_name,
6582 'ORDER_NUMBER',
6583 DECODE(L_ORDER_ID_SORT,
6584 'ASC',
6585 To_number(wdd.source_header_number),
6586 'DESC',
6587 (-1 * To_number(wdd.SOURCE_HEADER_NUMBER)),
6588 null),
6589 'SHIPMENT_PRIORITY',
6590 DECODE(WDD.SHIPMENT_PRIORITY_CODE,
6591 'High',
6592 20,
6593 'Standard',
6594 10,
6595 NULL),
6596 'INVOICE_VALUE',
6597 GET_SORT_INVOICE_VALUE(WDD.SOURCE_HEADER_ID,
6598 L_INVOICE_VALUE_SORT),
6599 'SCHEDULE_DATE',
6600 DECODE(L_SCHEDULE_DATE_SORT,
6601 'ASC',
6602 (WDD.DATE_SCHEDULED -
6603 TO_DATE('01-01-1700 23:59:59',
6604 'DD-MM-YYYY HH24:MI:SS')),
6605 'DESC',
6606 (TO_DATE('01-01-1700 23:59:59',
6607 'DD-MM-YYYY HH24:MI:SS') -
6608 WDD.DATE_SCHEDULED),
6609 null),
6610 'TRIP_STOP_DATE',
6611 GET_SORT_TRIP_STOP_DATE(wdd.delivery_detail_id,
6612 L_TRIP_STOP_DATE_SORT),
6613 NULL))) as sort_attribute5
6614 FROM wsh_delivery_details wdd
6615 WHERE wdd.source_code = 'OE'
6616 AND wdd.organization_id = p_org_id
6617 AND wdd.requested_quantity > 0
6618 -- excluding Replenishment Requested status
6619 AND wdd.released_status in ('R', 'B') and wdd.replenishment_status = 'R'
6620 -- there might not be reservation
6621 AND NOT EXISTS
6622 (select 1
6623 from mtl_reservations mr
6624 WHERE MR.DEMAND_SOURCE_LINE_ID = wdd.source_line_id
6625 and MR.DEMAND_SOURCE_HEADER_ID =
6626 inv_salesorder.get_salesorder_for_oeheader(wdd.source_header_id)
6627 and MR.demand_source_type_id =
6628 decode(wdd.source_document_type_id, 10, 8, 2)
6629 and MR.SUBINVENTORY_CODE IS NOT NULL --locator is not needed
6630 and (nvl(mr.staged_flag,'N') = 'N' and nvl(mr.detailed_quantity,0) = 0)) --13398141 ; Exclude detailed RSV
6631 AND NOT EXISTS
6632 (select wrd.demand_line_detail_id
6633 from WMS_REPLENISHMENT_DETAILS wrd
6634 where wrd.demand_line_detail_id = wdd.delivery_detail_id
6635 and wrd.demand_line_id = wdd.source_line_id
6636 and wrd.organization_id = wdd.organization_id
6637 AND wrd.organization_id = p_org_id)
6638 AND wdd.batch_id = P_Batch_id
6639 ORDER BY sort_attribute1,
6640 sort_attribute2,
6641 sort_attribute3,
6642 sort_attribute4,
6643 sort_attribute5
6644 FOR UPDATE SKIP LOCKED;
6645
6646
6647 CURSOR c_item_repl_cur IS
6648 SELECT inventory_item_id,
6649 sum(quantity_in_repl_uom) as total_demand_qty,
6650 MIN(expected_ship_date) as date_required,
6651 repl_to_subinventory_code,
6652 repl_uom_code
6653 FROM wms_repl_demand_gtmp
6654 WHERE organization_id = p_org_id
6655 GROUP BY inventory_item_id, repl_to_subinventory_code,repl_uom_code
6656 ORDER BY inventory_item_id, repl_to_subinventory_code;
6657
6658
6659 l_repl_uom_code VARCHAR2(3);
6660 L_quantity_in_repl_uom NUMBER;
6661 l_conversion_rate NUMBER;
6662
6663 l_return_value BOOLEAN;
6664 l_atr_ORG NUMBER;
6665
6666 l_detail_info_tab WSH_INTERFACE_EXT_GRP.delivery_details_Attr_tbl_Type;
6667 l_in_rec WSH_INTERFACE_EXT_GRP.detailInRecType;
6668 l_out_rec WSH_INTERFACE_EXT_GRP.detailOutRecType;
6669
6670 l_pr_sub VARCHAR2(10);
6671
6672 -- BULK OPERATION: Table to store results from the open demand for replenishment
6673 l_item_id_tb num_tab;
6674 l_header_id_tb num_tab;
6675 l_line_id_tb num_tab;
6676 l_delivery_detail_id_tb num_tab;
6677 l_demand_type_id_tb num_tab;
6678 l_requested_quantity_tb num_tab;
6679 l_requested_quantity_uom_tb uom_tab;
6680 l_quantity_in_repl_uom_tb num_tab;
6681 l_expected_ship_date_tb date_tab;
6682 l_repl_status_tb char1_tab;
6683 l_released_status_tb char1_tab;
6684 l_attr1_tb num_tab;
6685 l_attr2_tb num_tab;
6686 l_attr3_tb num_tab;
6687 l_attr4_tb num_tab;
6688 l_attr5_tb num_tab;
6689 l_repl_to_sub_code_tb char_tab;
6690 l_repl_UOM_CODE_tb uom_tab;
6691
6692
6693 -- BULK OPERATION: Table to store consolidate demand results for replenishment
6694 l_total_demand_qty_tb num_tab;
6695 l_date_required_tb date_tab;
6696
6697 l_temp_cnt NUMBER; -- removei t
6698
6699 l_return_status VARCHAR2(3) := fnd_api.g_ret_sts_success;
6700 l_revert_wdd BOOLEAN := FALSE;
6701
6702 l_bkorder_cnt NUMBER;
6703 BEGIN
6704
6705 x_return_status := l_return_status;
6706 SAVEPOINT populate_dyn_demand_sp;
6707 IF (l_debug = 1) THEN
6708 print_debug('Inside POPULATE_DYNAMIC_REPL_DEMAND Procedure');
6709 print_debug('Release_Sequence_Rule_Id: '||p_Release_Sequence_Rule_Id);
6710 END IF;
6711
6712
6713 -- Get the Order By Clause based on Pick Release Rule
6714 --initialize gloabl variables
6715 -- delete old value
6716 g_ordered_psr.DELETE;
6717 init_rules(p_pick_seq_rule_id => p_Release_Sequence_Rule_Id,
6718 x_order_id_sort => l_ORDER_ID_SORT,
6719 x_INVOICE_VALUE_SORT => l_INVOICE_VALUE_SORT,
6720 x_SCHEDULE_DATE_SORT => l_SCHEDULE_DATE_SORT,
6721 x_trip_stop_date_sort => l_TRIP_STOP_DATE_SORT,
6722 x_SHIPMENT_PRI_SORT => l_shipment_pri_sort,
6723 x_ordered_psr => g_ordered_psr,
6724 x_api_status => l_return_status );
6725
6726
6727 IF (l_debug = 1) THEN
6728 print_debug('Status after calling init_rules'||l_return_status);
6729 END IF;
6730 IF (l_return_status <> fnd_api.g_ret_sts_success) THEN
6731 GOTO end_populate;
6732 END IF;
6733
6734
6735 -- 1- Go through all the demand lines that are marked as Replenishement requested and insert them in the
6736 -- WMS_REPL_DEMAND_GTMP table
6737
6738 -- USE BULK INSERT FROM CURSOR TO THE TABLE AND THEN UPDATE THE TABLE FOR
6739 -- l_repl_to_sub_code, l_repl_uom_code and l_quantity in repl_uom
6740
6741 l_item_id_tb.DELETE;
6742 l_header_id_tb.DELETE;
6743 l_line_id_tb.DELETE;
6744 l_delivery_detail_id_tb.DELETE;
6745 l_demand_type_id_tb.DELETE;
6746 l_requested_quantity_tb.DELETE;
6747 l_requested_quantity_uom_tb.DELETE;
6748 l_expected_ship_date_tb.DELETE;
6749 l_repl_status_tb.DELETE;
6750 l_released_status_tb.DELETE;
6751 l_attr1_tb.DELETE;
6752 l_attr2_tb.DELETE;
6753 l_attr3_tb.DELETE;
6754 l_attr4_tb.DELETE;
6755 l_attr5_tb.DELETE;
6756 l_repl_to_sub_code_tb.DELETE;
6757 l_quantity_in_repl_uom_tb.DELETE;
6758 l_repl_uom_code_tb.DELETE;
6759
6760 -- BULK Fetch all data from the demand cursor
6761 BEGIN
6762 OPEN c_dynamic_repl_demand;
6763 FETCH c_dynamic_repl_demand BULK COLLECT INTO
6764 l_item_id_tb,l_header_id_tb, l_line_id_tb,
6765 l_delivery_detail_id_tb,l_demand_type_id_tb,
6766 l_requested_quantity_tb,l_requested_quantity_uom_tb,
6767 l_expected_ship_date_tb,l_repl_to_sub_code_tb,l_repl_status_tb, l_released_status_tb,
6768 l_attr1_tb,l_attr2_tb,l_attr3_tb,l_attr4_tb,l_attr5_tb;
6769 CLOSE c_dynamic_repl_demand;
6770 EXCEPTION
6771 WHEN OTHERS THEN
6772 IF (l_debug = 1) THEN
6773 print_debug('Exception retrieving open repl demand records');
6774 END IF;
6775 l_return_status := fnd_api.g_ret_sts_error;
6776 GOTO end_populate;
6777 END;
6778
6779 select pick_from_subinventory INTO l_PR_sub
6780 from wsh_picking_batches where batch_id = p_batch_id;
6781
6782 IF (l_debug = 1) THEN
6783 print_debug('At this point total number of dd_ids considered :' ||l_delivery_detail_id_tb.COUNT);
6784 print_debug('Subinventory specified at the time of pick release:'||l_PR_sub);
6785 END IF;
6786
6787
6788 -- Now process/calculate ALL records
6789 IF (l_delivery_detail_id_tb.count>0) THEN --bug#10185153
6790 FOR j IN l_delivery_detail_id_tb.FIRST..l_delivery_detail_id_tb.LAST LOOP
6791
6792 l_revert_wdd := FALSE;
6793
6794 -- Consider for replenishment
6795 -- Try to get the Destination sub for the to_be_created replenishemnt move order
6796
6797 -- Subinventory specified at Pick release time should take priority
6798 -- subinvnetory specifeid while creating the SO.
6799 IF l_pr_sub IS NULL THEN
6800 l_pr_sub := l_repl_to_sub_code_tb(j);
6801 END IF;
6802
6803 --Store values in l_repl_to_sub_code_tb and l_repl_uom_code_tb table
6804 Get_to_Sub_For_Dynamic_Repl(P_Org_id => p_org_id,
6805 P_Item_id => l_Item_id_tb(j),
6806 P_PRIMARY_DEMAND_QTY => l_requested_quantity_tb(j),
6807 X_TO_SUBINVENTORY_CODE => l_PR_sub,
6808 X_REPL_UOM_CODE => l_repl_uom_code_tb(j));
6809
6810
6811 l_repl_to_sub_code_tb(j) :=l_pr_sub;
6812 l_pr_sub := NULL ; --10633351.Null out variable for next iteration of LOOP
6813
6814 IF l_repl_to_sub_code_tb(j) IS NOT NULL AND l_repl_uom_code_tb(j) IS NOT NULL THEN
6815 -- keep only those records which has to_sub_code
6816
6817 l_conversion_rate := get_conversion_rate(l_Item_id_tb(j),
6818 l_requested_quantity_uom_tb(j),
6819 l_repl_uom_code_tb(j));
6820
6821
6822 IF (l_conversion_rate < 0) THEN
6823
6824 IF (l_debug = 1) THEN
6825 print_debug('Error while obtaining conversion rate');
6826 print_debug('Skipping REPL for the delivery detail:'||l_delivery_detail_id_tb(j) );
6827 END IF;
6828 -- this records should not be added to the WRDT:
6829 -- Must delete this records jth element from the bulk uploaded tables later
6830 l_revert_wdd := TRUE;
6831 GOTO next_wdd;
6832
6833 ELSE
6834
6835 -- Store values in l_quantity_in_repl_uom_tb table
6836 l_quantity_in_repl_uom_tb(j) := ROUND(l_conversion_rate *
6837 l_requested_quantity_tb(j));
6838
6839 END IF;
6840
6841 ELSE
6842 --TO_SUB_CODE could not be identified
6843 IF (l_debug = 1) THEN
6844 print_debug('TO_SUB_CODE could not be identified for delivery_detail');
6845 print_debug('Skipping REPL for the delivery detail:'||l_delivery_detail_id_tb(j) );
6846 END IF;
6847 -- this records should not be added to the WRDT:
6848 -- Must delete this records jth element from the bulk uploaded tables later
6849 l_revert_wdd := TRUE;
6850 GOTO next_wdd;
6851
6852 END IF; -- for l_repl_to_sub_code_tb(j) IS NOT NULL
6853
6854 <<next_wdd>>
6855 IF (l_revert_wdd) THEN
6856 l_revert_wdd := FALSE;
6857 -- We can not replenish this line
6858 -- Backorder this demand line - Add to the global variable to be
6859 -- called AT the END OF the dynamic repl process
6860
6861 IF (l_debug = 1) THEN
6862 print_debug('Revert wdd' );
6863 print_debug('--Backorder this demand line, add to the global variable :'||l_delivery_detail_id_tb(j));
6864 END IF;
6865
6866 l_bkorder_cnt := g_backorder_deliv_tab.COUNT() + 1;
6867
6868 g_backorder_deliv_tab(l_bkorder_cnt):= l_delivery_detail_id_tb(j) ;
6869 g_backorder_qty_tab(l_bkorder_cnt) := l_requested_quantity_tb(j);
6870 -- since we are backordering entire qty parameters
6871 -- p_bo_qtys AND p_req_qtys will have same value
6872 g_dummy_table(l_bkorder_cnt) := 0;
6873
6874
6875 -- this records should not be added to the WRDT:
6876 -- Must delete this records jth element from the bulk uploaded tables later
6877 IF (l_debug = 1) THEN
6878 print_debug('Skipping REPL for the delivery detail:'||l_delivery_detail_id_tb(j) );
6879 END IF;
6880
6881 -- Note: these delete in pl/sql table do not reindex
6882 -- data. element deleted at J remains NULL. it works sort of
6883 -- key-value pair for id and values
6884
6885 l_item_id_tb.DELETE(j);
6886 l_header_id_tb.DELETE(j);
6887 l_line_id_tb.DELETE(j);
6888 l_delivery_detail_id_tb.DELETE(j);
6889 l_demand_type_id_tb.DELETE(j);
6890 l_requested_quantity_tb.DELETE(j);
6891 l_requested_quantity_uom_tb.DELETE(j);
6892 l_expected_ship_date_tb.DELETE(j);
6893 l_repl_status_tb.DELETE(j);
6894 l_released_status_tb.DELETE(j);
6895 l_repl_to_sub_code_tb.DELETE(j);
6896 l_quantity_in_repl_uom_tb.DELETE(j);
6897 l_repl_uom_code_tb.DELETE(j);
6898
6899
6900 IF (l_return_status <> fnd_api.g_ret_sts_success) THEN
6901 -- if we are unable to revert a WDD, we should
6902 -- essentially revery everything back
6903 -- as if could not do anything in populating
6904 l_item_id_tb.DELETE;
6905 l_header_id_tb.DELETE;
6906 l_line_id_tb.DELETE;
6907 l_delivery_detail_id_tb.DELETE;
6908 l_demand_type_id_tb.DELETE;
6909 l_requested_quantity_tb.DELETE;
6910 l_requested_quantity_uom_tb.DELETE;
6911 l_expected_ship_date_tb.DELETE;
6912 l_repl_status_tb.DELETE;
6913 l_released_status_tb.DELETE;
6914 l_repl_to_sub_code_tb.DELETE;
6915 l_quantity_in_repl_uom_tb.DELETE;
6916 l_repl_uom_code_tb.DELETE;
6917 l_return_status := fnd_api.g_ret_sts_error;
6918 GOTO end_populate;
6919 END IF;
6920 END IF; -- IF (l_revert_wdd) THEN
6921 END LOOP; -- FOR j IN 1..l_delivery_detail_id_tb.COUNT LOOP
6922 END IF;
6923
6924
6925 -- Bulk upload all eligible demand lines
6926 -- since some recprds from the l_delivery_detail_id_tb has been deleted,
6927 -- use 'INDICES OF' instead of table count
6928 FORALL k IN INDICES OF l_delivery_detail_id_tb
6929 INSERT INTO WMS_REPL_DEMAND_GTMP
6930 (Repl_Sequence_id,
6931 repl_level,
6932 Inventory_item_id,
6933 Organization_id,
6934 demand_header_id,
6935 demand_line_id,
6936 demand_line_detail_id,
6937 demand_type_id,
6938 quantity_in_repl_uom,
6939 REPL_UOM_code,
6940 Quantity,
6941 Uom_code,
6942 Expected_ship_date,
6943 Repl_To_Subinventory_code,
6944 filter_item_flag,
6945 repl_status,
6946 repl_type,
6947 RELEASED_STATUS)
6948 VALUES
6949 (WMS_REPL_DEMAND_GTMP_S.NEXTVAL,
6950 p_repl_level,
6951 l_item_id_tb(k),
6952 p_org_id,
6953 l_header_id_tb(k),
6954 l_line_id_tb(k),
6955 l_delivery_detail_id_tb(k),
6956 l_demand_type_id_tb(k),
6957 l_quantity_in_repl_uom_tb(k),
6958 l_repl_uom_code_tb(k),
6959 l_requested_quantity_tb(k),
6960 l_requested_quantity_uom_tb(k),
6961 l_expected_ship_date_tb(k),
6962 l_repl_to_sub_code_tb(k),
6963 NULL,
6964 l_repl_status_tb(k),
6965 2, -- for dynamic replenishment
6966 l_released_status_tb(k));
6967
6968 IF (l_debug = 1) THEN
6969 print_debug('DONE with storing all records in WRDT table');
6970 print_debug('Now Store consolidated date in the PL/SQL table');
6971 END IF;
6972
6973
6974 --=====================TEST CODE STARTS =======
6975 -- for debugging purpise only, entire code should be inside l_debug = 1
6976 IF (l_debug = 1) THEN
6977 SELECT COUNT(1) INTO l_temp_cnt FROM wms_repl_demand_gtmp;
6978 print_debug('FINAL record count in gtmp :'||l_temp_cnt);
6979 END IF;
6980 --=====================TEST CODE ENDS =======
6981
6982
6983
6984 -- 3- For replenishment MO creation, all demand line qty will be consolidated/grouped for Item_id and destiniation_sub
6985
6986 -- Clear tables for bulk operation
6987 l_item_id_tb.DELETE;
6988 l_total_demand_qty_tb.DELETE;
6989 l_date_required_tb.DELETE;
6990 l_repl_to_sub_code_tb.DELETE;
6991 l_repl_uom_code_tb.DELETE;
6992
6993 -- BULK COLLECT THESE RECORDS
6994 BEGIN
6995 OPEN c_item_repl_cur;
6996 FETCH c_item_repl_cur BULK COLLECT INTO l_item_id_tb,
6997 l_total_demand_qty_tb,
6998 l_date_required_tb,l_repl_to_sub_code_tb,l_repl_uom_code_tb;
6999 CLOSE c_item_repl_cur;
7000 EXCEPTION
7001 WHEN OTHERS THEN
7002 IF (l_debug = 1) THEN
7003 print_debug('Exception retrieving item repl records for Dynamic');
7004 END IF;
7005 l_return_status := fnd_api.g_ret_sts_error;
7006 GOTO end_populate;
7007 END;
7008
7009 --Clear consolidated table
7010 x_consol_item_repl_tbl.DELETE;
7011
7012 FOR k IN 1 .. l_item_id_tb.COUNT LOOP
7013 x_consol_item_repl_tbl(k).Organization_id := p_org_id;
7014 x_consol_item_repl_tbl(k).Item_id := l_item_id_tb(k);
7015 x_consol_item_repl_tbl(k).total_demand_qty := l_total_demand_qty_tb(k);
7016 x_consol_item_repl_tbl(k).date_required := l_date_required_tb(k);
7017
7018 x_consol_item_repl_tbl(k).available_onhand_qty := 0; --calculated later
7019 x_consol_item_repl_tbl(k).open_mo_qty := 0; --calculated later
7020 x_consol_item_repl_tbl(k).final_replenishment_qty := 0; --calculated later
7021
7022 x_consol_item_repl_tbl(k).repl_to_subinventory_code := l_repl_to_sub_code_tb(k);
7023 x_consol_item_repl_tbl(k).repl_uom_code := l_repl_uom_code_tb(k);
7024 END LOOP;
7025
7026 -- At this point, we do not know whether the demand could not be fulfilled becs of rules restrictions or
7027 -- material is not available in the entire organization
7028 -- Check the high level availability (atr) at the org level.and adjust ALL qty accordingly for all items
7029
7030 IF l_debug = 1 THEN
7031 print_debug('Number of consolidated demand records :'||x_consol_item_repl_tbl.COUNT());
7032 END IF;
7033
7034
7035 IF x_consol_item_repl_tbl.COUNT() <> 0 THEN
7036
7037 ADJUST_ATR_FOR_ITEM (p_repl_level => p_repl_level
7038 , p_repl_type => g_dynamic_repl
7039 , x_consol_item_repl_tbl => x_consol_item_repl_tbl
7040 , x_return_status => l_return_status
7041 );
7042
7043 IF l_debug = 1 THEN
7044 print_debug('Return Status after call to ADJUST_ATR_FOR_ITEM :'|| l_return_status);
7045 END IF;
7046
7047 IF l_return_status <> FND_API.g_ret_sts_success THEN
7048 -- All error out
7049 GOTO end_populate;
7050 END IF;
7051 END IF;
7052
7053
7054 <<end_populate>>
7055 IF (l_return_status <> fnd_api.g_ret_sts_success) THEN
7056 -- Raising excetion so that will call revert of WDD status for all WDDs
7057 -- in the DYNAMIC_REPLENISHMENT api
7058 RAISE fnd_api.g_exc_unexpected_error;
7059 END IF;
7060
7061 x_return_status := FND_API.G_RET_STS_SUCCESS;
7062 IF l_debug = 1 THEN
7063 print_debug('DONE WITH API POPULATE_DYNAMIC_REPL_DEMAND');
7064 END IF;
7065
7066 EXCEPTION
7067 WHEN OTHERS THEN
7068 IF l_debug = 1 THEN
7069 print_debug('Exception in POPULATE_DYNAMIC_REPL_DEMAND: ' || sqlcode || ', ' || sqlerrm);
7070 END IF;
7071 ROLLBACK TO populate_dyn_demand_sp;
7072 x_return_status := fnd_api.g_ret_sts_error;
7073 x_consol_item_repl_tbl.DELETE;
7074 END POPULATE_DYNAMIC_REPL_DEMAND;
7075
7076
7077
7078 PROCEDURE allocate_repl_move_order(
7079 p_Quantity_function_id IN NUMBER,
7080 x_return_status OUT NOCOPY VARCHAR2,
7081 x_msg_count OUT NOCOPY NUMBER,
7082 x_msg_data OUT nocopy VARCHAR2
7083 )
7084 IS
7085
7086
7087
7088 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
7089
7090 L_LOC_ID NUMBER;
7091
7092 l_prev_to_sub VARCHAR2(10);
7093 l_prev_item_id NUMBER;
7094
7095
7096 L_PICK_UOM_CODE VARCHAR2(3);
7097 L_FIXED_LOT_MULTIPLE NUMBER;
7098 L_UNIT_CONV_QTY NUMBER;
7099
7100 l_rsv_tbl_tmp inv_reservation_global.mtl_reservation_tbl_type;
7101 i NUMBER;
7102
7103 L_CUR_SUB_HAS_CAPACITY BOOLEAN ;
7104 l_available_capacity NUMBER;
7105 l_base_uom_code VARCHAR2(3);
7106 l_return_status VARCHAR2(1);
7107 l_msg_count NUMBER;
7108 l_msg_data VARCHAR2(1000);
7109 l_trigger_allocation BOOLEAN := FALSE;
7110
7111 l_quantity_detailed NUMBER;
7112 l_quantity_detailed_conv NUMBER;
7113 l_num_detail_recs NUMBER;
7114
7115 l_prim_quantity_detailed NUMBER;
7116 l_mo_line_id NUMBER;
7117 l_task_id NUMBER;
7118
7119 -- We are NOT doing this at the moment: For the available capacity at the destination sub there can be competing replenishment move order lines.
7120 -- Consume queued and competing repl MO lines in the order of priority of demand lines based on wrd.Demand_Sort_Order
7121 -- (Since Demand_Sort_Order will alredy give priority orders first
7122 -- within a release_batch.Since we want to give high priority to earlier pick releases,
7123 -- the wrd. WRD.Demand_Sort_Order will take care of this as well as it gets value from a DB sequence.
7124
7125 CURSOR c_open_repl_mo IS
7126 select
7127 mtrl.organization_id,
7128 mtrl.INVENTORY_ITEM_ID,
7129 mtrl.FROM_SUBINVENTORY_CODE,
7130 mtrl.TO_SUBINVENTORY_CODE,
7131 mtrl.quantity mol_qty,
7132 Nvl(mtrl.quantity_detailed,0) mol_detailed_qty,
7133 Nvl(mtrl.quantity_delivered,0) mol_delivered_qty,
7134 mtrl.uom_code,
7135 mtrl.header_id,
7136 mtrl.line_id
7137 FROM mtl_txn_request_lines mtrl,
7138 Mtl_txn_request_headers mtrh
7139 WHERE mtrl.header_id = mtrh.header_id
7140 And mtrl.organization_id = mtrh.organization_id
7141 and mtrl.organization_id in (select organization_id from mtl_parameters where wms_enabled_flag = 'Y')
7142 And MTRH.move_order_type = 2
7143 and mtrl.line_status in (3,7) -- only approved and pre-approved
7144 and (mtrl.quantity - (Nvl(mtrl.quantity_detailed,0) + Nvl(mtrl.quantity_delivered,0))) > 0
7145 and mtrh.transaction_type_id = 64
7146 and mtrl.transaction_type_id = 64
7147 and mtrl.transaction_source_type_id = 4
7148 ORDER BY mtrl.organization_id, mtrl.TO_SUBINVENTORY_CODE, mtrl.line_id, mtrl.INVENTORY_ITEM_ID;
7149
7150 -- Note we have mtrl.line_Id in the order_by clause to have some predictable consumption of move order behavior in
7151 -- case of conflicting priority among MO lines.
7152 --(Note: We could have put a better consumption order of repl move
7153 --order lines based on assigning the priority number as MIN[priority of associated demand lines].)
7154
7155 --We need to order by mtrl.INVENTORY_ITEM_ID to process lines more efficiently below
7156
7157 CURSOR c_locators_in_sub(P_ORGANIZATION_ID NUMBER, p_sub_code VARCHAR2) IS
7158 SELECT INVENTORY_LOCATION_ID
7159 FROM MTL_ITEM_LOCATIONS
7160 WHERE SUBINVENTORY_CODE = P_SUB_CODE
7161 AND ORGANIZATION_ID = p_organization_id
7162 ORDER BY PICKING_ORDER;
7163
7164 CURSOR c_trigger_parameters(P_ORG_ID NUMBER, p_item_id NUMBER, p_src_sub VARCHAR2, p_dest_sub VARCHAR2) IS
7165 SELECT MSI.PICK_UOM_CODE, MISI.FIXED_LOT_MULTIPLE
7166 from MTL_ITEM_SUB_INVENTORIES MISI,
7167 MTL_SECONDARY_INVENTORIES MSI
7168 where MISI.organization_id = p_org_id
7169 AND MISI.SOURCE_SUBINVENTORY = MSI.SECONDARY_INVENTORY_NAME
7170 AND MISI.ORGANIZATION_ID = MSI.ORGANIZATION_ID
7171 AND nvl(MISI.SOURCE_SUBINVENTORY, '@@@') = NVL(p_src_sub , nvl(MISI.SOURCE_SUBINVENTORY,'@@@'))
7172 AND MISI.SECONDARY_INVENTORY = p_dest_sub
7173 AND MISI.INVENTORY_ITEM_ID = p_Item_id
7174 and MISI.source_type = 3 --(for Subinventory)
7175 AND MISI.source_organization_id = p_org_id;
7176
7177 CURSOR c_base_uom(p_txn_uom_code VARCHAR2) IS
7178 SELECT muom.uom_code
7179 FROM mtl_units_of_measure_tl muom,mtl_units_of_measure_tl muom2
7180 WHERE muom2.uom_code = p_txn_uom_code
7181 AND muom2.language = userenv('LANG')
7182 AND muom.uom_class = muom2.uom_class
7183 AND muom.language = userenv('LANG')
7184 AND muom.base_uom_flag = 'Y';
7185
7186
7187 CURSOR c_mmtt_rec IS
7188 SELECT transaction_temp_id
7189 FROM mtl_material_transactions_temp
7190 WHERE move_order_line_id = l_mo_line_id;
7191
7192 BEGIN
7193
7194 IF l_debug = 1 THEN
7195 print_debug('API allocate_repl_move_order - quantity function id :'|| p_quantity_function_id) ;
7196 END IF;
7197
7198 --It will keep looking at the locators of the destination subinventories of the queued replenishemt MO and see if any capacity becomes available.
7199
7200 --If there is 'Fixed Lot Multiple' value specified for the item-subinventory form for the destination sub,
7201 --then this value must be used in the decision making to trigger allocation. If the available capacity at
7202 --destination locator is more than single unit 'Fixed Lot Multiple' qty of the source subinventory on
7203 --the queued replenishment MO, then trigger the allocation process of the MO based on the priority of the
7204 --associated demand orders.
7205
7206 --If the 'Fixed Lot multiple' value is NOT specified on the item-subinventory form for the tiem and
7207 --destination sub, then see if the source subinventory is stamped on the item_sub Form.
7208 --Check if the 'Pick UOM' for the source sub is set in the subinventory Form. Get the unit qty conversion
7209 --of this pick uom to the primary qty (say l_src_uom_unit_qty). If l_src_uom_unit_qty
7210 --is less than the available capacity of the destination sub, then trigger the allocation for the open repl MO.
7211
7212 --Otherwise
7213 --IF
7214 --( 'Fixed Lot Multiple' value is NOT specified on the item-sub form)
7215 --AND (the source_sub is also NOT specified for the item+destination_sub OR the pick_uom of the
7216 --source_sub is not defined on the source sub ) THEN
7217 --Trigger the allocation anyway.
7218 --END IF;
7219
7220 -- Get all destination subinventories from the replenishment move
7221 --orders that have some qty to be replenished for demands.
7222
7223
7224 L_CUR_SUB_HAS_CAPACITY := TRUE;
7225
7226 FOR l_open_repl_mo IN c_open_repl_mo LOOP
7227
7228 IF l_debug = 1 THEN
7229 print_debug('Processing MO Line: '||l_open_repl_mo.line_id ||
7230 ' ,with destination sub: '||l_open_repl_mo.to_subinventory_code||
7231 ' ,FOR ITEM : '||l_open_repl_mo.inventory_item_id
7232 ) ;
7233 END IF;
7234
7235 --IF l_available_capacity <= 0 for ALL locations in the current sub,
7236 --then skip ALL Open move orders in the batch that has destination of the current sub
7237
7238 IF (NOT l_cur_sub_has_capacity) AND (l_prev_to_sub = l_open_repl_mo.to_subinventory_code) THEN
7239 -- Skip to the next open MO
7240 IF l_debug = 1 THEN
7241 print_debug('DEST SUB HAS NO CAPACITY : SKIPPING allocation of current MO') ;
7242 END IF;
7243 GOTO next_mo_line;
7244 ELSE
7245
7246 -- Get the available capacity for EACH valid locator in the l_open_repl_mo.TO_SUBINVENTORY_CODE
7247 -- Scan each locator in the sub for capacity
7248 L_CUR_SUB_HAS_CAPACITY := FALSE;
7249
7250 -- Setting Item information in the Cache
7251 IF inv_cache.set_item_rec(l_open_repl_mo.organization_id, l_open_repl_mo.inventory_item_id) THEN
7252 NULL;
7253 IF (l_debug = 1) THEN
7254 print_debug('Primary UOM for the Item:' ||inv_cache.item_rec.primary_uom_code);
7255 END IF;
7256 END IF;
7257
7258 OPEN c_locators_in_sub(l_open_repl_mo.organization_id, l_open_repl_mo.TO_SUBINVENTORY_CODE);
7259 LOOP
7260 FETCH c_locators_in_sub INTO L_loc_id;
7261
7262 IF l_debug = 1 THEN
7263 print_debug('*******Getting capacity for Next LOC :'||L_loc_id) ;
7264 END IF;
7265
7266 EXIT WHEN c_locators_in_sub%NOTFOUND;
7267
7268 IF p_quantity_function_id IS NULL THEN -- not specified
7269
7270 l_available_capacity := 1e125;
7271
7272 ELSIF (p_quantity_function_ID = 530003) THEN -- Unit Capacity Quantity Function
7273
7274 -- Call capacity calculation function ONLY for each to_sub change
7275 IF (l_prev_to_sub IS NULL OR (l_prev_to_sub <> l_open_repl_mo.to_subinventory_code)) THEN
7276 IF l_debug = 1 THEN
7277 print_debug('CALLING Unit Capacity API FOR AVAILABLE CAPACITY') ;
7278 END IF;
7279
7280 l_available_capacity := get_available_capacity
7281 (
7282 p_quantity_function => p_Quantity_function_id
7283 , p_organization_id => l_open_repl_mo.organization_id
7284 , p_subinventory_code => l_open_repl_mo.TO_SUBINVENTORY_CODE
7285 , p_locator_id => l_loc_id
7286 , p_inventory_item_id => NULL
7287 , p_unit_volume => NULL
7288 , p_unit_volume_uom_code => NULL
7289 , p_unit_weight => NULL
7290 , p_unit_weight_uom_code => NULL
7291 , p_primary_uom => NULL
7292 , p_transaction_uom => NULL
7293 , p_base_uom => NULL
7294 , p_transaction_quantity => NULL );
7295 END IF;
7296
7297 ELSE -- all other kind of quantity function
7298
7299 -- Call capacity calculation function for EACH to_sub change OR item change
7300
7301 IF (l_prev_to_sub IS NULL OR l_prev_to_sub <> l_open_repl_mo.TO_SUBINVENTORY_CODE OR
7302 l_prev_item_id IS NULL OR l_prev_item_id <> l_open_repl_mo.INVENTORY_ITEM_ID) THEN
7303 IF l_debug = 1 THEN
7304 print_debug('CALCULATING AVAILABLE CAPACITY WITH other APIs') ;
7305 END IF;
7306
7307 OPEN c_base_uom(l_open_repl_mo.uom_code) ;
7308 FETCH c_base_uom INTO l_base_uom_code;
7309 IF c_base_uom%NOTFOUND THEN
7310 GOTO next_mo_line;
7311 END IF;
7312 CLOSE c_base_uom;
7313
7314 l_available_capacity := get_available_capacity
7315 (
7316 p_quantity_function => p_Quantity_function_id
7317 , p_organization_id => l_open_repl_mo.organization_id
7318 , p_subinventory_code => l_open_repl_mo.TO_SUBINVENTORY_CODE
7319 , p_locator_id => l_loc_id
7320 , p_inventory_item_id => l_open_repl_mo.inventory_item_id
7321 , p_unit_volume => inv_cache.item_rec.unit_volume
7322 , p_unit_volume_uom_code =>inv_cache.item_rec.volume_uom_code
7323 , p_unit_weight =>inv_cache.item_rec.unit_weight
7324 , p_unit_weight_uom_code =>inv_cache.item_rec.weight_uom_code
7325 , p_primary_uom =>inv_cache.item_rec.primary_uom_code
7326 , p_transaction_uom => l_open_repl_mo.uom_code
7327 , p_base_uom => l_base_uom_code
7328 , p_transaction_quantity => (l_open_repl_mo.mol_qty - l_open_repl_mo.mol_detailed_qty - l_open_repl_mo.mol_delivered_qty));
7329
7330 ELSE
7331 IF (l_debug = 1) THEN
7332 print_debug('No data Found and hence no capacity for the Item');
7333 END IF;
7334
7335 GOTO next_mo_line;
7336 END IF; -- FOR l_prev_to_sub <> l_open_repl_mo.TO_SUBINVENTORY_CODE
7337 END IF; -- all other kind of quantity function
7338
7339 --Note: CAPACITY changes after each allocation even if the material has not physically moved to the destination.
7340
7341 --So we need to rely on the condition that once L_CUR_SUB_HAS_CAPACITY becomes FALSE for a location,
7342 -- there is no chance of it becoming true as the API get_available_capacity() will be
7343 -- returning the updated available capacity.
7344
7345 IF (l_debug = 1) THEN
7346 print_debug('Capacity of current locator: '||l_available_capacity);
7347 END IF;
7348
7349 IF l_available_capacity > 0 then
7350 L_CUR_SUB_HAS_CAPACITY := TRUE;
7351 -- DO NOT PUT the : ELSE L_CUR_SUB_HAS_CAPACITY := FALSE;
7352 END IF;
7353
7354 -- get the Picking UOM AND 'Fixed Lot Multiple' for l_open_repl_mo.FROM_SUBINVENTORY_CODE,
7355 OPEN c_trigger_parameters(l_open_repl_mo.organization_id,
7356 l_open_repl_mo.INVENTORY_ITEM_ID,
7357 l_open_repl_mo.FROM_SUBINVENTORY_CODE ,l_open_repl_mo.TO_SUBINVENTORY_CODE);
7358 LOOP
7359 FETCH c_trigger_parameters INTO L_PICK_UOM_CODE, L_FIXED_LOT_MULTIPLE;
7360 EXIT WHEN c_trigger_parameters%NOTFOUND;
7361
7362 IF (l_debug = 1) THEN
7363 print_debug('Trigger parameter value l_fixed_lot_multiple: '||l_fixed_lot_multiple);
7364 print_debug('Trigger parameter value L_PICK_UOM_CODE: '||L_PICK_UOM_CODE);
7365 END IF;
7366
7367 -- NOW DECIDE WHETHER TO TRIGGER ALLOCATION OR NOT
7368 -- l_available_capacity and l_fixed_lot_multiple are in primary UOM
7369 IF l_fixed_lot_multiple IS NOT NULL THEN
7370 IF (l_debug = 1) THEN
7371 print_debug('USING Fixed Lot Multiplier for decision making');
7372 END IF;
7373 IF l_available_capacity > 0 AND l_available_capacity >= l_fixed_lot_multiple THEN
7374 l_trigger_allocation := TRUE;
7375 ELSE
7376 l_trigger_allocation := FALSE;
7377 END IF;
7378
7379 ELSIF l_pick_uom_code IS NOT NULL THEN --see if the source sub pick UOM is valid
7380 IF (l_debug = 1) THEN
7381 print_debug('USING Src Sub Pick UOM Unit Qty for decision making');
7382 END IF;
7383
7384 L_UNIT_CONV_QTY := ROUND(1* get_conversion_rate(l_open_repl_mo.inventory_item_id,
7385 l_pick_uom_code,
7386 inv_cache.item_rec.primary_uom_code),
7387 g_conversion_precision);
7388
7389 IF (l_debug = 1) THEN
7390 print_debug(' L_UNIT_CONV_QTY:' ||L_UNIT_CONV_QTY);
7391 END IF;
7392
7393 IF L_UNIT_CONV_QTY < 0 THEN
7394 IF (l_debug = 1) THEN
7395 print_debug('Error while obtaining L_mo_uom_code conversion rate for demand qty');
7396 END IF;
7397 l_trigger_allocation := FALSE;
7398 ELSE
7399 IF l_available_capacity > 0 AND (l_available_capacity >= l_unit_conv_qty) THEN
7400 l_trigger_allocation := TRUE;
7401 ELSE
7402 l_trigger_allocation := FALSE;
7403 END IF;
7404 END IF;
7405
7406 ELSE --Trigger it anyway
7407 IF (l_debug = 1) THEN
7408 print_debug('Trigger allocation since fixed_lot_multiplier AND src sub unit qty NOT available');
7409 END IF;
7410 l_trigger_allocation := TRUE;
7411
7412 -- in case the 'effective qty' that need to be allocated ON MO
7413 -- IS more than the available capacity at the destination
7414 -- rule engine will allocate whatever it could
7415 -- effective qty = (mtrl.quantity - (Nvl(mtrl.quantity_detailed,0) + Nvl(mtrl.quantity_delivered,0)))
7416 END IF; --for l_fixed_lot_multiple IS NOT null
7417
7418
7419 -- Now actually allocate the MO
7420 IF (NOT l_trigger_allocation) THEN
7421 --Do nothing, get to the next mo line to allocate
7422 IF (l_debug = 1) THEN
7423 print_debug('Could not meet capacity Criteria in current Sub/Loc');
7424 print_debug('Skip to next Loc in the Sub OR Next repl MO Line......');
7425 END IF;
7426 GOTO next_loc_in_sub;
7427
7428 ELSE -- allocate the replenishment move order
7429 -- Call Allocation API
7430 IF (l_debug = 1) THEN
7431 print_debug('Available capacity is enough to trigger allocation....');
7432 END IF;
7433
7434 WMS_Engine_PVT.create_suggestions(
7435 p_api_version => 1.0,
7436 p_init_msg_list => fnd_api.g_false,
7437 p_commit => fnd_api.g_false,
7438 p_validation_level => fnd_api.g_valid_level_none,
7439 x_return_status => l_return_status,
7440 x_msg_count => l_msg_count,
7441 x_msg_data => l_msg_data,
7442 p_transaction_temp_id => l_open_repl_mo.line_id,
7443 p_reservations => l_rsv_tbl_tmp, --NULL value AS no rsv FOR repl MO
7444 p_suggest_serial => fnd_api.g_false,
7445 p_plan_tasks => FALSE);
7446
7447
7448 IF (l_return_status <> FND_API.G_RET_STS_SUCCESS) THEN
7449 IF (l_debug = 1) THEN
7450 print_debug('Error returned from create_suggestions API: '
7451 || l_return_status);
7452 END IF;
7453
7454 -- If an exception occurs while modifying a database record, rollback the changes
7455 -- and raise exception. Should we proceed to next record
7456 ROLLBACK TO Current_MOL_SP;
7457 RAISE fnd_api.g_exc_error;
7458 ELSE
7459
7460 IF (l_debug = 1) THEN
7461 print_debug('Success returned from create_suggestions API');
7462 print_debug('Now Assign Task Type for all Repl tasks created FOR the MO Line');
7463 END IF;
7464 l_mo_line_id:=l_open_repl_mo.line_id;
7465
7466 OPEN c_mmtt_rec;
7467 LOOP
7468 FETCH c_mmtt_rec INTO l_task_id;
7469 EXIT WHEN c_mmtt_rec%notfound;
7470
7471 IF (l_debug = 1) THEN
7472 print_debug('Assign Task Type for MMTT_id: '||l_task_id);
7473 END IF;
7474
7475 wms_rule_pvt.assigntt(
7476 p_api_version => 1.0
7477 , p_task_id => l_task_id
7478 , x_return_status => l_return_status
7479 , x_msg_count => x_msg_count
7480 , x_msg_data => x_msg_data
7481 );
7482
7483 END LOOP;
7484 CLOSE c_mmtt_rec;
7485
7486 END IF;
7487
7488 --update the MO line quantity_detailed field or close the MO
7489 BEGIN
7490 SELECT NVL(SUM(primary_quantity), 0)
7491 ,NVL(sum(transaction_quantity),0)
7492 ,COUNT(*)
7493 INTO l_prim_quantity_detailed
7494 ,l_quantity_detailed_conv
7495 ,l_num_detail_recs
7496 FROM mtl_material_transactions_temp
7497 WHERE move_order_line_id = l_open_repl_mo.line_id;
7498
7499 IF (l_debug = 1) THEN
7500 print_debug('primary l_quantity detailed is '|| l_prim_quantity_detailed);
7501 print_debug('l_num_detail_recs is '|| l_num_detail_recs);
7502 END IF;
7503 EXCEPTION
7504 WHEN NO_DATA_FOUND THEN
7505 IF (l_debug = 1) THEN
7506 print_debug('no detail records found');
7507 END IF;
7508 l_quantity_detailed := 0;
7509 l_quantity_detailed_conv := 0;
7510 l_num_detail_recs := 0;
7511 END;
7512
7513
7514 --Convert the MOL detailed qty into MOL UOM code qty
7515 IF inv_cache.item_rec.primary_uom_code <> l_open_repl_mo.uom_code THEN
7516
7517 l_quantity_detailed :=
7518 ROUND((l_prim_quantity_detailed* get_conversion_rate(l_open_repl_mo.inventory_item_id,
7519 inv_cache.item_rec.primary_uom_code,
7520 l_open_repl_mo.UOM_Code )),
7521 g_conversion_precision);
7522
7523 ELSE
7524 l_quantity_detailed := l_prim_quantity_detailed;
7525 END IF;
7526
7527 IF (l_debug = 1) THEN
7528 print_debug('Qty Detailed :'||l_quantity_detailed );
7529 print_debug('MOL Line Qty :'||l_open_repl_mo.mol_qty);
7530 print_debug('MOL Line Qty Delivered :'||l_open_repl_mo.mol_delivered_qty);
7531 END IF;
7532
7533 -- NOTE: l_quantity_detailed contains all qty of MMTT related TO CURRENT mo line whether in this
7534 -- RUN OR ANY previous runs
7535 IF l_quantity_detailed < (l_open_repl_mo.mol_qty - l_open_repl_mo.mol_delivered_qty) THEN -- partial allocation
7536 -- update the quantity detailed correctly
7537 UPDATE mtl_txn_request_lines mtrl
7538 SET mtrl.quantity_detailed = l_quantity_detailed
7539 where line_id = l_open_repl_mo.line_id;
7540
7541 IF (l_debug = 1) THEN
7542 print_debug('Updated the detailed qty on the MO line');
7543 END IF;
7544
7545 ELSE -- Fully allocated
7546 -- it has been completely detailed
7547 -- DO NOT Close the MO, otherwise finalize Pick
7548 -- Confirm fails WHILE dropping the task
7549 UPDATE mtl_txn_request_lines mtrl
7550 SET mtrl.quantity_detailed = l_quantity_detailed
7551 where line_id = l_open_repl_mo.line_id;
7552
7553 IF (l_debug = 1) THEN
7554 print_debug('MO line completely detailed');
7555 END IF;
7556
7557 END IF; -- for partial allocation
7558
7559 END IF; -- for (NOT l_trigger_allocation)
7560
7561 END LOOP; -- get pick_uom_code and fixed_multiple
7562 <<next_loc_in_sub>>
7563 CLOSE c_trigger_parameters;
7564 IF (l_debug = 1) THEN
7565 print_debug('Done with the Capacity of current Locator in the Sub');
7566 END IF;
7567 END LOOP; -- For each locator in the sub
7568 CLOSE c_locators_in_sub;
7569 END IF; -- for L_CUR_SUB_HAS_CAPACITY
7570
7571 <<next_mo_line>>
7572
7573 IF c_trigger_parameters%isopen THEN
7574 CLOSE c_trigger_parameters;
7575 END IF;
7576 IF c_locators_in_sub%isopen THEN
7577 CLOSE c_locators_in_sub;
7578 END IF;
7579
7580 l_prev_to_sub := l_open_repl_mo.TO_SUBINVENTORY_CODE;
7581 l_prev_item_id := l_open_repl_mo.INVENTORY_ITEM_ID;
7582
7583 IF (l_debug = 1) THEN
7584 print_debug('Done Allocating CURRENT MO record ');
7585 END IF;
7586 END LOOP; -- For each REPL MO line under consideration
7587
7588
7589 COMMIT;
7590 x_return_status := FND_API.G_RET_STS_SUCCESS;
7591
7592 EXCEPTION
7593 WHEN OTHERS THEN
7594 IF l_debug = 1 THEN
7595 print_debug('Exception in ALLOCATE_REPL_MOVE_ORDER: ' || sqlcode || ', ' || sqlerrm);
7596 END IF;
7597 x_return_status := FND_API.G_RET_STS_ERROR;
7598 END ALLOCATE_REPL_MOVE_ORDER;
7599
7600
7601 PROCEDURE UPDATE_DELIVERY_DETAIL (
7602 p_delivery_detail_id IN NUMBER,
7603 P_PRIMARY_QUANTITY IN NUMBER,
7604 P_SPLIT_DELIVERY_DETAIL_ID IN NUMBER DEFAULT NULL,
7605 p_split_source_line_id IN NUMBER DEFAULT NULL,
7606 x_return_status OUT NOCOPY VARCHAR2
7607 )
7608
7609 IS
7610 l_debug NUMBER := NVL(fnd_profile.VALUE('INV_DEBUG_TRACE'), 0);
7611 l_orig_pri_qty NUMBER;
7612
7613 l_source_header_id NUMBER;
7614 l_source_line_id NUMBER;
7615 l_source_line_detail_id NUMBER;
7616 l_source_type_id NUMBER;
7617 l_demand_header_id NUMBER;
7618 l_demand_line_id NUMBER;
7619 l_demand_type_id NUMBER;
7620 l_primary_uom VARCHAR2(3);
7621 l_demand_sort_order NUMBER;
7622 l_item_id NUMBER;
7623 l_org_id NUMBER;
7624 L_repl_type NUMBER;
7625 L_REPL_LEVEL NUMBER;
7626 l_no_deliv_in_wrd BOOLEAN := FALSE;
7627
7628 BEGIN
7629
7630 IF l_debug = 1 THEN
7631 print_debug('P_SPLIT_DELIVERY_DETAIL_ID :'||P_SPLIT_DELIVERY_DETAIL_ID );
7632 print_debug('p_delivery_detail_id: '|| p_delivery_detail_id);
7633 print_debug('p_delivery_detail_id: '|| p_split_source_line_id);
7634 print_debug('p_primary_quantity :' || p_primary_quantity);
7635 END IF;
7636
7637 -- This API will be called by the shipping team to update the qty in wrd
7638 -- if the demand qty changes in the process
7639 -- if P_QUANTITY = 0, then WMS will remove those demands from the
7640 -- replenishment consideration
7641
7642 IF p_split_delivery_detail_id IS NULL THEN
7643
7644 IF P_PRIMARY_QUANTITY > 0 THEN
7645 --UPDATE THE PRIMARY QTY FOR THE DEMAND
7646
7647 UPDATE WMS_REPLENISHMENT_DETAILS
7648 SET PRIMARY_QUANTITY = P_PRIMARY_QUANTITY
7649 WHERE DEMAND_LINE_DETAIL_ID = p_delivery_detail_id
7650 AND primary_quantity >= P_PRIMARY_QUANTITY;
7651
7652 ELSE
7653
7654 -- NEED TO REMOVE THE ENTRY FROM WRD.
7655 -- In this case we will have More qty in the replenishment mover
7656 -- ORDER that will be consumed BY later processing
7657
7658
7659 DELETE FROM WMS_REPLENISHMENT_DETAILS
7660 WHERE DEMAND_LINE_DETAIL_ID = P_DELIVERY_DETAIL_ID;
7661
7662 END IF;
7663
7664
7665
7666 ELSE -- MEANS DELIVERY IS SPLIT
7667
7668 --Note: There can be case when this API will be called after
7669 -- splitting a delivery detail that was NOT originally tracked in the
7670 -- WRD table to start with
7671
7672 -- p_delivery_detail_id is tied up with P_PRIMARY_QUANTITY and
7673 -- remaining qty go with new delivery detail p_split_delivery_detail_id
7674 BEGIN
7675 SELECT
7676 source_header_id, Source_line_id,
7677 Source_line_detail_id,Source_type_id, demand_header_id,
7678 demand_line_id,demand_type_id, Primary_UOM, Primary_Quantity,
7679 demand_sort_order, inventory_item_id, organization_id
7680 , Nvl(repl_level,1), repl_type
7681 INTO l_source_header_id,l_Source_line_id,
7682 l_Source_line_detail_id, l_Source_type_id,
7683 l_demand_header_id,l_demand_line_id, l_demand_type_id,l_Primary_UOM, l_orig_pri_qty, l_demand_sort_order,
7684 l_item_id, l_org_id , l_repl_level, l_repl_type
7685 FROM WMS_REPLENISHMENT_DETAILS
7686 WHERE DEMAND_LINE_DETAIL_ID = p_delivery_detail_id;
7687 EXCEPTION
7688 WHEN no_data_found THEN
7689 l_orig_pri_qty := -9999;
7690 l_no_deliv_in_wrd := TRUE;
7691 END;
7692
7693 -- Insert split delivery details id only if the original delivery
7694 -- detail id is found IN WRD
7695 IF (NOT l_no_deliv_in_wrd) AND l_orig_pri_qty <> -9999 AND p_primary_quantity < l_orig_pri_qty THEN
7696
7697 -- Update old delivery with decreased qty
7698 UPDATE WMS_REPLENISHMENT_DETAILS
7699 SET PRIMARY_QUANTITY = P_PRIMARY_QUANTITY
7700 WHERE DEMAND_LINE_DETAIL_ID = p_delivery_detail_id;
7701
7702 -- Insert a new record in WRD with remaining qty
7703 -- Note: Priority of the Split demand Order remain same as the
7704 -- original one
7705 INSERT INTO WMS_REPLENISHMENT_DETAILS
7706 (Replenishment_id,
7707 Organization_Id,
7708 source_header_id,
7709 Source_line_id,
7710 Source_line_detail_id,
7711 Source_type_id,
7712 demand_header_id,
7713 demand_line_id,
7714 demand_line_detail_id,
7715 demand_type_id,
7716 Inventory_item_id,
7717 Primary_UOM,
7718 Primary_Quantity,
7719 demand_sort_order,
7720 repl_type,
7721 repl_level,
7722 CREATION_DATE,
7723 LAST_UPDATE_DATE,
7724 CREATED_BY,
7725 LAST_UPDATED_BY,
7726 LAST_UPDATE_LOGIN
7727 )VALUES (
7728 WMS_REPLENISHMENT_DETAILS_S.NEXTVAL,
7729 l_org_id,
7730 l_source_header_id,
7731 l_source_line_id,
7732 l_Source_line_detail_id,
7733 l_Source_type_id,
7734 l_demand_header_id,
7735 Nvl(p_split_source_line_id,l_demand_line_id),
7736 p_split_delivery_detail_id,
7737 l_demand_type_id,
7738 l_item_id,
7739 l_Primary_UOM,
7740 (l_orig_pri_qty - p_primary_quantity) ,
7741 l_demand_sort_order,
7742 L_repl_type,
7743 l_repl_level,
7744 Sysdate,
7745 Sysdate,
7746 fnd_global.user_id,
7747 fnd_global.user_id,
7748 fnd_global.user_id);
7749
7750 END IF; -- FOR l_orig_pri_qty <> -9999
7751
7752 END IF; -- MEANS DELIVERY IS SPLIT
7753
7754 x_return_status := FND_API.G_RET_STS_SUCCESS;
7755 EXCEPTION
7756 WHEN OTHERS THEN
7757 IF l_debug = 1 THEN
7758 print_debug('Exception in update_delivery_detail: ' || sqlcode || ', ' || sqlerrm);
7759 END IF;
7760 END update_delivery_detail;
7761
7762
7763 END wms_replenishment_pvt;