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